diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 8d05a8188f..88e2d2a5cb 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,8 +1,6 @@ name: Test on: - push: - branches: [develop] pull_request: branches: [develop] diff --git a/Makefile b/Makefile index 3e0dabf847..e20bd94800 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,13 @@ GIT_COMMIT_SHA := $(shell git rev-list -1 HEAD) BUILD_TAGS = rocksdb,builtin_static BUILD_LD_FLAGS = "-X github.com/iotaledger/wasp/packages/wasp.VersionHash=$(GIT_COMMIT_SHA)" +# +# You can override these e.g. as +# make test TEST_PKG=./packages/vm/core/testcore/ TEST_ARG="-v --run TestAccessNodes" +# +TEST_PKG=./... +TEST_ARG= + all: build-lint build: @@ -16,7 +23,7 @@ test-full: install go test -tags $(BUILD_TAGS),runheavy ./... --timeout 60m --count 1 -failfast test: install - go test -tags $(BUILD_TAGS) ./... --timeout 30m --count 1 -failfast + go test -tags $(BUILD_TAGS) $(TEST_PKG) --timeout 30m --count 1 -failfast $(TEST_ARG) test-short: go test -tags $(BUILD_TAGS) --short --count 1 -failfast ./... @@ -39,5 +46,5 @@ docker-build: --build-arg BUILD_LD_FLAGS='${BUILD_LD_FLAGS}' \ . -.PHONY: all build build-windows build-lint test test-short install install-windows lint gofumpt-list docker-build +.PHONY: all build build-windows build-lint test test-short test-full install install-windows lint gofumpt-list docker-build diff --git a/README.md b/README.md index cb3fcf6a78..3d52418289 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ introduction](https://blog.iota.org/an-introduction-to-iota-smart-contracts-16ea6f247936) into ISCP. +The comprehensive overview of design decisions of _IOTA Smart Contracts_ can be found in the +[whitepaper](https://github.com/iotaledger/wasp/raw/master/documentation/ISC_WP_Nov_10_2021.pdf). + ## Documentation The documentation for Wasp and IOTA Smart Contracts can be found on the [IOTA Wiki](https://wiki.iota.org/wasp/overview). diff --git a/client/chainclient/chainclient.go b/client/chainclient/chainclient.go index 6317221c1d..e2d9e70c9b 100644 --- a/client/chainclient/chainclient.go +++ b/client/chainclient/chainclient.go @@ -82,7 +82,7 @@ func (c *Client) PostOffLedgerRequest( c.nonces[c.KeyPair.PublicKey]++ par.Nonce = c.nonces[c.KeyPair.PublicKey] } - offledgerReq := request.NewOffLedger(contractHname, entrypoint, par.Args).WithTransfer(par.Transfer) + offledgerReq := request.NewOffLedger(c.ChainID, contractHname, entrypoint, par.Args).WithTransfer(par.Transfer) offledgerReq.WithNonce(par.Nonce) offledgerReq.Sign(c.KeyPair) return offledgerReq, c.WaspClient.PostOffLedgerRequest(c.ChainID, offledgerReq) diff --git a/client/committee_record.go b/client/committee_record.go index acbd99cea4..064f5091da 100644 --- a/client/committee_record.go +++ b/client/committee_record.go @@ -27,7 +27,7 @@ func (c *WaspClient) GetCommitteeRecord(addr ledgerstate.Address) (*registry.Com // 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()), nil, res); err != nil { + 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/metrics.go b/client/metrics.go new file mode 100644 index 0000000000..ec241a3a89 --- /dev/null +++ b/client/metrics.go @@ -0,0 +1,27 @@ +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" +) + +// GetNodeConnectionMetrics fetches a connection to L1 metrics for all addresses +func (c *WaspClient) GetNodeConnectionMetrics() (*model.NodeConnectionMetrics, error) { + ncm := &model.NodeConnectionMetrics{} + if err := c.do(http.MethodGet, routes.GetChainsNodeConnectionMetrics(), nil, ncm); err != nil { + return nil, err + } + return ncm, nil +} + +// GetNodeConnectionMetrics fetches a connection to L1 metrics by address +func (c *WaspClient) GetChainNodeConnectionMetrics(chID *iscp.ChainID) (*model.NodeConnectionMessagesMetrics, error) { + ncmm := &model.NodeConnectionMessagesMetrics{} + if err := c.do(http.MethodGet, routes.GetChainNodeConnectionMetrics(chID.Base58()), nil, ncmm); err != nil { + return nil, err + } + return ncmm, nil +} diff --git a/contracts/native/evm/README.md b/contracts/native/evm/README.md index dc7ef524e7..21ee749f5d 100644 --- a/contracts/native/evm/README.md +++ b/contracts/native/evm/README.md @@ -108,3 +108,22 @@ Finally we start the JSON-RPC server: ``` wasp-cli chain evm jsonrpc ``` + +## Predictable block time + +Some EVM contracts depend on blocks being minted periodically with regular +intervals. ISCP does not support that natively, so by default a new EVM block +is minted every time an ISCP batch is executed that contains at least one EVM +transaction. In other words, by default no EVM blocks will be minted until an +EVM transaction is received. + +However, the `evmlight` implementation supports emulating predictable block +times. To enable this feature, just pass the `--block-time n` flag when +deploying the EVM chain with `wasp-cli chain evm deploy`, where `n` is +the desired average amount of seconds between blocks. + +Note that this may change the behavior of JSON-RPC functions that query the +EVM state (e.g. `getBalance`), since `evmlight` is not able to store the state +in both the latest minted block and the pending block. These functions will +always return the state computed after accepting the latest transaction (i.e. +the state of the pending block). diff --git a/contracts/native/evm/evmchain/emulator/emulator_test.go b/contracts/native/evm/evmchain/emulator/emulator_test.go index a0bf039542..5c47474f05 100644 --- a/contracts/native/evm/evmchain/emulator/emulator_test.go +++ b/contracts/native/evm/evmchain/emulator/emulator_test.go @@ -471,7 +471,6 @@ func initBenchmark(b *testing.B) (*EVMEmulator, []*types.Transaction, dict.Dict) InitGenesis(evm.DefaultChainID, db, genesisAlloc, evm.GasLimitDefault, 0) emu := NewEVMEmulator(db) - defer emu.Close() contractABI, err := abi.JSON(strings.NewReader(evmtest.StorageContractABI)) require.NoError(b, err) @@ -520,6 +519,7 @@ func initBenchmark(b *testing.B) (*EVMEmulator, []*types.Transaction, dict.Dict) func benchmarkEVMEmulator(b *testing.B, k int) { // setup: deploy the storage contract and prepare N transactions to send emu, txs, db := initBenchmark(b) + defer emu.Close() b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/contracts/native/evm/evmchain/impl.go b/contracts/native/evm/evmchain/impl.go index 588fac615c..c2f1e1ea0e 100644 --- a/contracts/native/evm/evmchain/impl.go +++ b/contracts/native/evm/evmchain/impl.go @@ -43,13 +43,17 @@ func initialize(ctx iscp.Sandbox) (dict.Dict, error) { a := assert.NewAssert(ctx.Log()) genesisAlloc, err := evmtypes.DecodeGenesisAlloc(ctx.Params().MustGet(evm.FieldGenesisAlloc)) a.RequireNoError(err) + + gasLimit, err := codec.DecodeUint64(ctx.Params().MustGet(evm.FieldGasLimit), evm.GasLimitDefault) + a.RequireNoError(err) + chainID, err := codec.DecodeUint16(ctx.Params().MustGet(evm.FieldChainID), evm.DefaultChainID) a.RequireNoError(err) emulator.InitGenesis( int(chainID), - rawdb.NewDatabase(emulator.NewKVAdapter(ctx.State())), // TODO: use subrealm to avoid collisions with evm management + rawdb.NewDatabase(emulator.NewKVAdapter(evminternal.EVMStateSubrealm(ctx.State()))), genesisAlloc, - evm.GasLimitDefault, + gasLimit, timestamp(ctx), ) evminternal.InitializeManagement(ctx) @@ -57,18 +61,10 @@ func initialize(ctx iscp.Sandbox) (dict.Dict, error) { } func applyTransaction(ctx iscp.Sandbox) (dict.Dict, error) { - a := assert.NewAssert(ctx.Log()) - - tx := &types.Transaction{} - err := tx.UnmarshalBinary(ctx.Params().MustGet(evm.FieldTransactionData)) - a.RequireNoError(err) - - return evminternal.RequireGasFee(ctx, tx.Gas(), func() uint64 { - emu := getOrCreateEmulator(ctx) - receipt, err := emu.SendTransaction(tx) - a.RequireNoError(err) - return receipt.GasUsed - }), nil + return evminternal.ApplyTransaction(ctx, func(tx *types.Transaction, _ uint32) (*types.Receipt, error) { + emu := getEmulatorInBlockContext(ctx) + return emu.SendTransaction(tx) + }) } func getBalance(ctx iscp.SandboxView) (dict.Dict, error) { diff --git a/contracts/native/evm/evmchain/internal.go b/contracts/native/evm/evmchain/internal.go index 19eddbe21f..d702498f74 100644 --- a/contracts/native/evm/evmchain/internal.go +++ b/contracts/native/evm/evmchain/internal.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/iotaledger/wasp/contracts/native/evm" "github.com/iotaledger/wasp/contracts/native/evm/evmchain/emulator" + "github.com/iotaledger/wasp/contracts/native/evm/evminternal" "github.com/iotaledger/wasp/packages/evm/evmtypes" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/assert" @@ -33,16 +34,16 @@ func isNotFound(err error) bool { return false } -// getOrCreateEmulator creates a new emulator instance if this is the first call to applyTransaction +// getEmulatorInBlockContext creates a new emulator instance if this is the first call to applyTransaction // in the ISCP block; otherwise it returns the previously created instance. The purpose is to // create a single Ethereum block for each ISCP block. -func getOrCreateEmulator(ctx iscp.Sandbox) *emulator.EVMEmulator { +func getEmulatorInBlockContext(ctx iscp.Sandbox) *emulator.EVMEmulator { bctx := ctx.BlockContext(createEmulator, commitEthereumBlock) return bctx.(*emulator.EVMEmulator) } func createEmulator(ctx iscp.Sandbox) interface{} { - return emulator.NewEVMEmulator(rawdb.NewDatabase(emulator.NewKVAdapter(ctx.State())), timestamp(ctx)) + return emulator.NewEVMEmulator(rawdb.NewDatabase(emulator.NewKVAdapter(evminternal.EVMStateSubrealm(ctx.State()))), timestamp(ctx)) } // timestamp returns the current timestamp in seconds since epoch @@ -59,7 +60,7 @@ func commitEthereumBlock(blockContext interface{}) { func withEmulatorR(ctx iscp.SandboxView, f func(*emulator.EVMEmulator) (dict.Dict, error)) (dict.Dict, error) { emu := emulator.NewEVMEmulator( - rawdb.NewDatabase(emulator.NewKVAdapter(buffered.NewBufferedKVStoreAccess(ctx.State()))), + rawdb.NewDatabase(emulator.NewKVAdapter(evminternal.EVMStateSubrealm(buffered.NewBufferedKVStoreAccess(ctx.State())))), timestamp(ctx), ) defer emu.Close() diff --git a/contracts/native/evm/evminternal/management.go b/contracts/native/evm/evminternal/management.go index 8e3fd26a9b..5a727eb935 100644 --- a/contracts/native/evm/evminternal/management.go +++ b/contracts/native/evm/evminternal/management.go @@ -4,14 +4,19 @@ package evminternal import ( + "time" + + "github.com/ethereum/go-ethereum/core/types" "github.com/iotaledger/wasp/contracts/native/evm" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/assert" "github.com/iotaledger/wasp/packages/iscp/colored" "github.com/iotaledger/wasp/packages/iscp/coreutil" + "github.com/iotaledger/wasp/packages/kv" "github.com/iotaledger/wasp/packages/kv/codec" "github.com/iotaledger/wasp/packages/kv/dict" "github.com/iotaledger/wasp/packages/kv/kvdecoder" + "github.com/iotaledger/wasp/packages/kv/subrealm" "github.com/iotaledger/wasp/packages/vm/core/accounts" "github.com/iotaledger/wasp/packages/vm/core/governance" ) @@ -20,6 +25,10 @@ const ( keyGasPerIota = "g" keyEVMOwner = "o" keyNextEVMOwner = "n" + keyBlockTime = "b" + + // keyEVMState is the subrealm prefix for the EVM state + keyEVMState = "s" ) var ManagementHandlers = []coreutil.ProcessorEntryPoint{ @@ -29,6 +38,11 @@ var ManagementHandlers = []coreutil.ProcessorEntryPoint{ evm.FuncWithdrawGasFees.WithHandler(withdrawGasFees), evm.FuncGetOwner.WithHandler(getOwner), evm.FuncGetGasPerIota.WithHandler(getGasPerIota), + evm.FuncSetBlockTime.WithHandler(setBlockTime), +} + +func EVMStateSubrealm(state kv.KVStore) kv.KVStore { + return subrealm.New(state, keyEVMState) } func InitializeManagement(ctx iscp.Sandbox) { @@ -36,11 +50,57 @@ func InitializeManagement(ctx iscp.Sandbox) { ctx.State().Set(keyEVMOwner, codec.EncodeAgentID(ctx.ContractCreator())) } -func requireOwner(ctx iscp.Sandbox) { +func setBlockTime(ctx iscp.Sandbox) (dict.Dict, error) { + requireOwner(ctx) + + params := kvdecoder.New(ctx.Params(), ctx.Log()) + a := assert.NewAssert(ctx.Log()) + + blockTime := params.MustGetUint32(evm.FieldBlockTime) + a.Require(blockTime > 0, "blockTime must be > 0") + + mustSchedule := !ctx.State().MustHas(keyBlockTime) + + ctx.State().Set(keyBlockTime, codec.EncodeUint32(blockTime)) + if mustSchedule { + ScheduleNextBlock(ctx) + } + return nil, nil +} + +func getBlockTime(state kv.KVStoreReader) uint32 { + bt, _ := codec.DecodeUint32(state.MustGet(keyBlockTime), 0) + return bt +} + +func ScheduleNextBlock(ctx iscp.Sandbox) { + requireOwner(ctx, true) + + a := assert.NewAssert(ctx.Log()) + + blockTime := getBlockTime(ctx.State()) + a.Require(blockTime > 0, "ScheduleNextBlock: blockTime must be > 0") + + ok := ctx.Send(ctx.ChainID().AsAddress(), colored.NewBalancesForIotas(1), &iscp.SendMetadata{ + TargetContract: ctx.Contract(), + EntryPoint: evm.FuncMintBlock.Hname(), + }, iscp.SendOptions{ + TimeLock: uint32(time.Unix(0, ctx.GetTimestamp()).Unix()) + blockTime, + }) + a.Require(ok, "failed to schedule next block") +} + +func requireOwner(ctx iscp.Sandbox, allowSelf ...bool) { contractOwner, err := codec.DecodeAgentID(ctx.State().MustGet(keyEVMOwner)) a := assert.NewAssert(ctx.Log()) a.RequireNoError(err) - a.Require(contractOwner.Equals(ctx.Caller()), "can only be called by the contract owner") + + allowed := []*iscp.AgentID{contractOwner} + if len(allowSelf) > 0 && allowSelf[0] { + allowed = append(allowed, iscp.NewAgentID(ctx.ChainID().AsAddress(), ctx.Contract())) + } + + a.RequireCaller(ctx, allowed) } func setNextOwner(ctx iscp.Sandbox) (dict.Dict, error) { @@ -55,7 +115,7 @@ func claimOwnership(ctx iscp.Sandbox) (dict.Dict, error) { nextOwner, err := codec.DecodeAgentID(ctx.State().MustGet(keyNextEVMOwner)) a.RequireNoError(err) - a.Require(nextOwner.Equals(ctx.Caller()), "Can only be called by the contract owner") + a.RequireCaller(ctx, []*iscp.AgentID{nextOwner}) ctx.State().Set(keyEVMOwner, codec.EncodeAgentID(nextOwner)) return nil, nil @@ -102,30 +162,50 @@ func withdrawGasFees(ctx iscp.Sandbox) (dict.Dict, error) { return nil, nil } -func RequireGasFee(ctx iscp.Sandbox, txGasLimit uint64, f func() uint64) dict.Dict { +func ApplyTransaction(ctx iscp.Sandbox, apply func(tx *types.Transaction, blockTime uint32) (*types.Receipt, error)) (dict.Dict, error) { + a := assert.NewAssert(ctx.Log()) + + tx := &types.Transaction{} + err := tx.UnmarshalBinary(ctx.Params().MustGet(evm.FieldTransactionData)) + a.RequireNoError(err) + + transferredIotas, gasPerIota := takeGasFee(ctx, tx) + + blockTime := getBlockTime(ctx.State()) + receipt, err := apply(tx, blockTime) + a.RequireNoError(err) + + return refundUnusedGasFee(ctx, ctx.Caller(), transferredIotas, gasPerIota, receipt.GasUsed), nil +} + +func takeGasFee(ctx iscp.Sandbox, tx *types.Transaction) (uint64, uint64) { a := assert.NewAssert(ctx.Log()) transferredIotas := ctx.IncomingTransfer().Get(getFeeColor(ctx)) gasPerIota, err := codec.DecodeUint64(ctx.State().MustGet(keyGasPerIota), 0) a.RequireNoError(err) + txGasLimit := tx.Gas() a.Require( transferredIotas >= txGasLimit/gasPerIota, "transferred tokens (%d) not enough to cover the gas limit set in the transaction (%d at %d gas per iota token)", transferredIotas, txGasLimit, gasPerIota, ) - gasUsed := f() + return transferredIotas, gasPerIota +} +func refundUnusedGasFee(ctx iscp.Sandbox, caller *iscp.AgentID, transferredIotas, gasPerIota, gasUsed uint64) dict.Dict { iotasGasFee := gasUsed / gasPerIota if transferredIotas > iotasGasFee { // refund unspent gas fee to the sender's on-chain account iotasGasRefund := transferredIotas - iotasGasFee - _, err = ctx.Call( + _, err := ctx.Call( accounts.Contract.Hname(), accounts.FuncDeposit.Hname(), - dict.Dict{accounts.ParamAgentID: codec.EncodeAgentID(ctx.Caller())}, + dict.Dict{accounts.ParamAgentID: codec.EncodeAgentID(caller)}, colored.NewBalancesForIotas(iotasGasRefund), ) + a := assert.NewAssert(ctx.Log()) a.RequireNoError(err) } diff --git a/contracts/native/evm/evmlight/emulator/blockchaindb.go b/contracts/native/evm/evmlight/emulator/blockchaindb.go index 8f5ae71e21..2220b584da 100644 --- a/contracts/native/evm/evmlight/emulator/blockchaindb.go +++ b/contracts/native/evm/evmlight/emulator/blockchaindb.go @@ -4,6 +4,8 @@ package emulator import ( + "bytes" + "encoding/gob" "math/big" "github.com/ethereum/go-ethereum/common" @@ -12,26 +14,36 @@ import ( "github.com/iotaledger/wasp/packages/evm/evmtypes" "github.com/iotaledger/wasp/packages/kv" "github.com/iotaledger/wasp/packages/kv/codec" + "github.com/iotaledger/wasp/packages/kv/collections" ) const ( - keyChainID = "c" - keyGasLimit = "g" - keyNumber = "n" - keyTransactionByBlockNumber = "n:t" - keyReceiptByBlockNumber = "n:r" - keyTimestampByBlockNumber = "n:ts" - keyBlockHashByBlockNumber = "n:bh" + // config values: + + // EVM chain ID + keyChainID = "c" + // Block gas limit + keyGasLimit = "g" + // Amount of blocks to keep in DB. Older blocks will be pruned every time a transaction is added + keyKeepAmount = "k" + + // blocks: + + keyNumber = "n" + keyPendingTimestamp = "pt" + keyTransactionsByBlockNumber = "n:t" + keyReceiptsByBlockNumber = "n:r" + keyBlockHeaderByBlockNumber = "n:bh" // indexes: keyBlockNumberByBlockHash = "bh:n" keyBlockNumberByTxHash = "th:n" + keyBlockIndexByTxHash = "th:i" ) -// Amount of blocks to keep in DB. Older blocks will be pruned every time a transaction is added -const keepAmount = 100 - +// BlockchainDB contains logic for storing a fake blockchain (more like a list of blocks), +// intended for satisfying EVM tools that depend on the concept of a block. type BlockchainDB struct { kv kv.KVStore } @@ -44,10 +56,11 @@ func (bc *BlockchainDB) Initialized() bool { return bc.kv.MustGet(keyChainID) != nil } -func (bc *BlockchainDB) Init(chainID uint16, gasLimit, timestamp uint64) { +func (bc *BlockchainDB) Init(chainID uint16, keepAmount int32, gasLimit, timestamp uint64) { bc.SetChainID(chainID) bc.SetGasLimit(gasLimit) - bc.AddBlock(bc.makeHeader(nil, nil, timestamp)) + bc.SetKeepAmount(keepAmount) + bc.addBlock(bc.makeHeader(nil, nil, 0, timestamp), timestamp+1) } func (bc *BlockchainDB) SetChainID(chainID uint16) { @@ -74,30 +87,52 @@ func (bc *BlockchainDB) GetGasLimit() uint64 { return gas } -func (bc *BlockchainDB) SetNumber(n *big.Int) { - bc.kv.Set(keyNumber, n.Bytes()) +func (bc *BlockchainDB) SetKeepAmount(keepAmount int32) { + bc.kv.Set(keyKeepAmount, codec.EncodeInt32(keepAmount)) } -func (bc *BlockchainDB) GetNumber() *big.Int { - r := new(big.Int) - r.SetBytes(bc.kv.MustGet(keyNumber)) - return r +func (bc *BlockchainDB) keepAmount() int32 { + gas, err := codec.DecodeInt32(bc.kv.MustGet(keyKeepAmount), -1) + if err != nil { + panic(err) + } + return gas +} + +func (bc *BlockchainDB) setPendingTimestamp(timestamp uint64) { + bc.kv.Set(keyPendingTimestamp, codec.EncodeUint64(timestamp)) +} + +func (bc *BlockchainDB) getPendingTimestamp() uint64 { + timestamp, err := codec.DecodeUint64(bc.kv.MustGet(keyPendingTimestamp)) + if err != nil { + panic(err) + } + return timestamp +} + +func (bc *BlockchainDB) setNumber(n uint64) { + bc.kv.Set(keyNumber, codec.EncodeUint64(n)) } -func makeTransactionByBlockNumberKey(blockNumber *big.Int) kv.Key { - return keyTransactionByBlockNumber + kv.Key(blockNumber.Bytes()) +func (bc *BlockchainDB) GetNumber() uint64 { + n, err := codec.DecodeUint64(bc.kv.MustGet(keyNumber)) + if err != nil { + panic(err) + } + return n } -func makeReceiptByBlockNumberKey(blockNumber *big.Int) kv.Key { - return keyReceiptByBlockNumber + kv.Key(blockNumber.Bytes()) +func makeTransactionsByBlockNumberKey(blockNumber uint64) kv.Key { + return keyTransactionsByBlockNumber + kv.Key(codec.EncodeUint64(blockNumber)) } -func makeTimestampByBlockNumberKey(blockNumber *big.Int) kv.Key { - return keyTimestampByBlockNumber + kv.Key(blockNumber.Bytes()) +func makeReceiptsByBlockNumberKey(blockNumber uint64) kv.Key { + return keyReceiptsByBlockNumber + kv.Key(codec.EncodeUint64(blockNumber)) } -func makeBlockHashByBlockNumberKey(blockNumber *big.Int) kv.Key { - return keyBlockHashByBlockNumber + kv.Key(blockNumber.Bytes()) +func makeBlockHeaderByBlockNumberKey(blockNumber uint64) kv.Key { + return keyBlockHeaderByBlockNumber + kv.Key(codec.EncodeUint64(blockNumber)) } func makeBlockNumberByBlockHashKey(hash common.Hash) kv.Key { @@ -108,99 +143,246 @@ func makeBlockNumberByTxHashKey(hash common.Hash) kv.Key { return keyBlockNumberByTxHash + kv.Key(hash.Bytes()) } -func (bc *BlockchainDB) AddTransaction(tx *types.Transaction, receipt *types.Receipt, timestamp uint64) { - bc.kv.Set( - makeTransactionByBlockNumberKey(receipt.BlockNumber), - evmtypes.EncodeTransaction(tx), - ) +func makeBlockIndexByTxHashKey(hash common.Hash) kv.Key { + return keyBlockIndexByTxHash + kv.Key(hash.Bytes()) +} + +func (bc *BlockchainDB) getTxArray(blockNumber uint64) *collections.Array32 { + return collections.NewArray32(bc.kv, string(makeTransactionsByBlockNumberKey(blockNumber))) +} + +func (bc *BlockchainDB) getReceiptArray(blockNumber uint64) *collections.Array32 { + return collections.NewArray32(bc.kv, string(makeReceiptsByBlockNumberKey(blockNumber))) +} + +func (bc *BlockchainDB) GetPendingBlockNumber() uint64 { + return bc.GetNumber() + 1 +} + +func (bc *BlockchainDB) GetPendingHeader() *types.Header { + return &types.Header{ + Difficulty: &big.Int{}, + Number: new(big.Int).SetUint64(bc.GetPendingBlockNumber()), + GasLimit: bc.GetGasLimit(), + Time: bc.getPendingTimestamp(), + } +} + +func (bc *BlockchainDB) GetLatestPendingReceipt() *types.Receipt { + blockNumber := bc.GetPendingBlockNumber() + receiptArray := bc.getReceiptArray(blockNumber) + n, err := receiptArray.Len() + if err != nil { + panic(err) + } + if n == 0 { + return nil + } + return bc.GetReceiptByBlockNumberAndIndex(blockNumber, n-1) +} + +func (bc *BlockchainDB) AddTransaction(tx *types.Transaction, receipt *types.Receipt) { + blockNumber := bc.GetPendingBlockNumber() + + txArray := bc.getTxArray(blockNumber) + txArray.MustPush(evmtypes.EncodeTransaction(tx)) bc.kv.Set( - makeReceiptByBlockNumberKey(receipt.BlockNumber), - evmtypes.EncodeReceipt(receipt), + makeBlockNumberByTxHashKey(tx.Hash()), + codec.EncodeUint64(blockNumber), ) bc.kv.Set( - makeBlockNumberByTxHashKey(tx.Hash()), - receipt.BlockNumber.Bytes(), + makeBlockIndexByTxHashKey(tx.Hash()), + codec.EncodeUint32(txArray.MustLen()-1), ) - header := bc.makeHeader(tx, receipt, timestamp) - bc.AddBlock(header) - bc.prune(header.Number) + receiptArray := bc.getReceiptArray(blockNumber) + receiptArray.MustPush(evmtypes.EncodeReceipt(receipt)) +} + +func (bc *BlockchainDB) MintBlock(timestamp uint64) { + blockNumber := bc.GetPendingBlockNumber() + header := bc.makeHeader( + bc.GetTransactionsByBlockNumber(blockNumber), + bc.GetReceiptsByBlockNumber(blockNumber), + blockNumber, + bc.getPendingTimestamp(), + ) + bc.addBlock(header, timestamp) + bc.prune(header.Number.Uint64()) } -func (bc *BlockchainDB) prune(currentNumber *big.Int) { - forget := new(big.Int).Sub(currentNumber, big.NewInt(int64(keepAmount))) - if forget.Cmp(common.Big1) >= 0 { - blockHash := bc.GetBlockHashByBlockNumber(forget) - txHash := bc.GetTransactionByBlockNumber(forget).Hash() +func (bc *BlockchainDB) prune(currentNumber uint64) { + keepAmount := bc.keepAmount() + if keepAmount < 0 { + // keep all blocks + return + } + if currentNumber <= uint64(keepAmount) { + return + } + toDelete := currentNumber - uint64(keepAmount) + // assume that all blocks prior to `toDelete` have been already deleted, so + // we only need to delete this one. + bc.deleteBlock(toDelete) +} - bc.kv.Del(makeTransactionByBlockNumberKey(forget)) - bc.kv.Del(makeReceiptByBlockNumberKey(forget)) - bc.kv.Del(makeTimestampByBlockNumberKey(forget)) - bc.kv.Del(makeBlockHashByBlockNumberKey(forget)) - bc.kv.Del(makeBlockNumberByBlockHashKey(blockHash)) +func (bc *BlockchainDB) deleteBlock(blockNumber uint64) { + header := bc.getHeaderGobByBlockNumber(blockNumber) + if header == nil { + // already deleted? + return + } + txs := bc.getTxArray(blockNumber) + n := txs.MustLen() + for i := uint32(0); i < n; i++ { + txHash := bc.GetTransactionByBlockNumberAndIndex(blockNumber, i).Hash() bc.kv.Del(makeBlockNumberByTxHashKey(txHash)) + bc.kv.Del(makeBlockIndexByTxHashKey(txHash)) + } + txs.MustErase() + bc.getReceiptArray(blockNumber).MustErase() + bc.kv.Del(makeBlockHeaderByBlockNumberKey(blockNumber)) + bc.kv.Del(makeBlockNumberByBlockHashKey(header.Hash)) +} + +type headerGob struct { + Hash common.Hash + GasUsed uint64 + Time uint64 + TxHash common.Hash + ReceiptHash common.Hash + Bloom types.Bloom +} + +func makeHeaderGob(header *types.Header) *headerGob { + return &headerGob{ + Hash: header.Hash(), + GasUsed: header.GasUsed, + Time: header.Time, + TxHash: header.TxHash, + ReceiptHash: header.ReceiptHash, + Bloom: header.Bloom, } } -func (bc *BlockchainDB) AddBlock(header *types.Header) { - bc.kv.Set( - makeTimestampByBlockNumberKey(header.Number), - codec.EncodeUint64(header.Time), - ) +func encodeHeaderGob(g *headerGob) []byte { + buf := new(bytes.Buffer) + err := gob.NewEncoder(buf).Encode(g) + if err != nil { + panic(err) + } + return buf.Bytes() +} + +func (bc *BlockchainDB) decodeHeaderGob(b []byte) *headerGob { + var g headerGob + err := gob.NewDecoder(bytes.NewReader(b)).Decode(&g) + if err != nil { + panic(err) + } + return &g +} + +func (bc *BlockchainDB) headerFromGob(g *headerGob, blockNumber uint64) *types.Header { + var parentHash common.Hash + if blockNumber > 0 { + parentHash = bc.GetBlockHashByBlockNumber(blockNumber - 1) + } + return &types.Header{ + Difficulty: &big.Int{}, + Number: new(big.Int).SetUint64(blockNumber), + GasLimit: bc.GetGasLimit(), + Time: g.Time, + ParentHash: parentHash, + GasUsed: g.GasUsed, + TxHash: g.TxHash, + ReceiptHash: g.ReceiptHash, + Bloom: g.Bloom, + UncleHash: types.EmptyUncleHash, + } +} + +func (bc *BlockchainDB) addBlock(header *types.Header, pendingTimestamp uint64) { + blockNumber := header.Number.Uint64() bc.kv.Set( - makeBlockHashByBlockNumberKey(header.Number), - header.Hash().Bytes(), + makeBlockHeaderByBlockNumberKey(blockNumber), + encodeHeaderGob(makeHeaderGob(header)), ) bc.kv.Set( makeBlockNumberByBlockHashKey(header.Hash()), - header.Number.Bytes(), + codec.EncodeUint64(blockNumber), ) - bc.SetNumber(header.Number) + bc.setNumber(blockNumber) + bc.setPendingTimestamp(pendingTimestamp) } -func (bc *BlockchainDB) GetReceiptByBlockNumber(blockNumber *big.Int) *types.Receipt { - b := bc.kv.MustGet(makeReceiptByBlockNumberKey(blockNumber)) - if b == nil { +func (bc *BlockchainDB) GetReceiptByBlockNumberAndIndex(blockNumber uint64, i uint32) *types.Receipt { + receipts := bc.getReceiptArray(blockNumber) + if i >= receipts.MustLen() { return nil } - r, err := evmtypes.DecodeReceipt(b) + r, err := evmtypes.DecodeReceipt(receipts.MustGetAt(i)) if err != nil { panic(err) } - tx := bc.GetTransactionByBlockNumber(blockNumber) + tx := bc.GetTransactionByBlockNumberAndIndex(blockNumber, i) r.TxHash = tx.Hash() if tx.To() == nil { from, _ := types.Sender(evmtypes.Signer(big.NewInt(int64(bc.GetChainID()))), tx) r.ContractAddress = crypto.CreateAddress(from, tx.Nonce()) } r.GasUsed = r.CumulativeGasUsed + if i > 0 { + prev, err := evmtypes.DecodeReceipt(receipts.MustGetAt(i - 1)) + if err != nil { + panic(err) + } + r.GasUsed -= prev.CumulativeGasUsed + } r.BlockHash = bc.GetBlockHashByBlockNumber(blockNumber) - r.BlockNumber = blockNumber + r.BlockNumber = new(big.Int).SetUint64(blockNumber) return r } -func (bc *BlockchainDB) GetBlockNumberByTxHash(txHash common.Hash) *big.Int { - b := bc.kv.MustGet(makeBlockNumberByTxHashKey(txHash)) +func (bc *BlockchainDB) getBlockNumberBy(key kv.Key) (uint64, bool) { + b := bc.kv.MustGet(key) if b == nil { - return nil + return 0, false + } + n, err := codec.DecodeUint64(b) + if err != nil { + panic(err) + } + return n, true +} + +func (bc *BlockchainDB) GetBlockNumberByTxHash(txHash common.Hash) (uint64, bool) { + return bc.getBlockNumberBy(makeBlockNumberByTxHashKey(txHash)) +} + +func (bc *BlockchainDB) GetBlockIndexByTxHash(txHash common.Hash) uint32 { + n, err := codec.DecodeUint32(bc.kv.MustGet(makeBlockIndexByTxHashKey(txHash)), 0) + if err != nil { + panic(err) } - return new(big.Int).SetBytes(b) + return n } func (bc *BlockchainDB) GetReceiptByTxHash(txHash common.Hash) *types.Receipt { - blockNumber := bc.GetBlockNumberByTxHash(txHash) - if blockNumber == nil { + blockNumber, ok := bc.GetBlockNumberByTxHash(txHash) + if !ok { return nil } - return bc.GetReceiptByBlockNumber(blockNumber) + i := bc.GetBlockIndexByTxHash(txHash) + return bc.GetReceiptByBlockNumberAndIndex(blockNumber, i) } -func (bc *BlockchainDB) GetTransactionByBlockNumber(blockNumber *big.Int) *types.Transaction { - b := bc.kv.MustGet(makeTransactionByBlockNumberKey(blockNumber)) - if b == nil { +func (bc *BlockchainDB) GetTransactionByBlockNumberAndIndex(blockNumber uint64, i uint32) *types.Transaction { + txs := bc.getTxArray(blockNumber) + if i >= txs.MustLen() { return nil } - tx, err := evmtypes.DecodeTransaction(b) + tx, err := evmtypes.DecodeTransaction(txs.MustGetAt(i)) if err != nil { panic(err) } @@ -208,79 +390,81 @@ func (bc *BlockchainDB) GetTransactionByBlockNumber(blockNumber *big.Int) *types } func (bc *BlockchainDB) GetTransactionByHash(txHash common.Hash) *types.Transaction { - blockNumber := bc.GetBlockNumberByTxHash(txHash) - if blockNumber == nil { + blockNumber, ok := bc.GetBlockNumberByTxHash(txHash) + if !ok { return nil } - return bc.GetTransactionByBlockNumber(blockNumber) + i := bc.GetBlockIndexByTxHash(txHash) + return bc.GetTransactionByBlockNumberAndIndex(blockNumber, i) } -func (bc *BlockchainDB) GetBlockHashByBlockNumber(blockNumber *big.Int) common.Hash { - b := bc.kv.MustGet(makeBlockHashByBlockNumberKey(blockNumber)) - if b == nil { +func (bc *BlockchainDB) GetBlockHashByBlockNumber(blockNumber uint64) common.Hash { + g := bc.getHeaderGobByBlockNumber(blockNumber) + if g == nil { return common.Hash{} } - return common.BytesToHash(b) + return g.Hash } -func (bc *BlockchainDB) GetBlockNumberByBlockHash(hash common.Hash) *big.Int { - b := bc.kv.MustGet(makeBlockNumberByBlockHashKey(hash)) - if b == nil { - return nil - } - return new(big.Int).SetBytes(b) +func (bc *BlockchainDB) GetBlockNumberByBlockHash(hash common.Hash) (uint64, bool) { + return bc.getBlockNumberBy(makeBlockNumberByBlockHashKey(hash)) } -func (bc *BlockchainDB) GetTimestampByBlockNumber(blockNumber *big.Int) uint64 { - n, err := codec.DecodeUint64(bc.kv.MustGet(makeTimestampByBlockNumberKey(blockNumber))) - if err != nil { - panic(err) +func (bc *BlockchainDB) GetTimestampByBlockNumber(blockNumber uint64) uint64 { + g := bc.getHeaderGobByBlockNumber(blockNumber) + if g == nil { + return 0 } - return n + return g.Time } -func (bc *BlockchainDB) makeHeader(tx *types.Transaction, receipt *types.Receipt, timestamp uint64) *types.Header { - if tx == nil { - // genesis block hash - blockNumber := common.Big0 - return &types.Header{ - Number: blockNumber, - GasLimit: bc.GetGasLimit(), - Time: timestamp, - TxHash: types.EmptyRootHash, - ReceiptHash: types.EmptyRootHash, - UncleHash: types.EmptyUncleHash, - } - } - blockNumber := receipt.BlockNumber - prevBlockNumber := new(big.Int).Sub(blockNumber, common.Big1) - return &types.Header{ - ParentHash: bc.GetBlockHashByBlockNumber(prevBlockNumber), - Number: blockNumber, +func (bc *BlockchainDB) makeHeader(txs []*types.Transaction, receipts []*types.Receipt, blockNumber, timestamp uint64) *types.Header { + header := &types.Header{ + Difficulty: &big.Int{}, + Number: new(big.Int).SetUint64(blockNumber), GasLimit: bc.GetGasLimit(), - GasUsed: receipt.GasUsed, Time: timestamp, - TxHash: types.DeriveSha(types.Transactions{tx}, &fakeHasher{}), - ReceiptHash: types.DeriveSha(types.Receipts{receipt}, &fakeHasher{}), - Bloom: types.CreateBloom([]*types.Receipt{receipt}), + TxHash: types.EmptyRootHash, + ReceiptHash: types.EmptyRootHash, UncleHash: types.EmptyUncleHash, } + if blockNumber == 0 { + // genesis block hash + return header + } + prevBlockNumber := blockNumber - 1 + gasUsed := uint64(0) + if len(receipts) > 0 { + gasUsed = receipts[len(receipts)-1].CumulativeGasUsed + } + header.ParentHash = bc.GetBlockHashByBlockNumber(prevBlockNumber) + header.GasUsed = gasUsed + if len(txs) > 0 { + header.TxHash = types.DeriveSha(types.Transactions(txs), &fakeHasher{}) + header.ReceiptHash = types.DeriveSha(types.Receipts(receipts), &fakeHasher{}) + } + header.Bloom = types.CreateBloom(receipts) + return header } -func (bc *BlockchainDB) GetHeaderByBlockNumber(blockNumber *big.Int) *types.Header { - if blockNumber.Cmp(bc.GetNumber()) > 0 { +func (bc *BlockchainDB) GetHeaderByBlockNumber(blockNumber uint64) *types.Header { + if blockNumber > bc.GetNumber() { return nil } - return bc.makeHeader( - bc.GetTransactionByBlockNumber(blockNumber), - bc.GetReceiptByBlockNumber(blockNumber), - bc.GetTimestampByBlockNumber(blockNumber), - ) + return bc.headerFromGob(bc.getHeaderGobByBlockNumber(blockNumber), blockNumber) +} + +func (bc *BlockchainDB) getHeaderGobByBlockNumber(blockNumber uint64) *headerGob { + b := bc.kv.MustGet(makeBlockHeaderByBlockNumberKey(blockNumber)) + if b == nil { + return nil + } + return bc.decodeHeaderGob(b) } func (bc *BlockchainDB) GetHeaderByHash(hash common.Hash) *types.Header { - n := bc.GetBlockNumberByBlockHash(hash) - if n == nil { + n, ok := bc.GetBlockNumberByBlockHash(hash) + if !ok { return nil } return bc.GetHeaderByBlockNumber(n) @@ -290,7 +474,7 @@ func (bc *BlockchainDB) GetBlockByHash(hash common.Hash) *types.Block { return bc.makeBlock(bc.GetHeaderByHash(hash)) } -func (bc *BlockchainDB) GetBlockByNumber(blockNumber *big.Int) *types.Block { +func (bc *BlockchainDB) GetBlockByNumber(blockNumber uint64) *types.Block { return bc.makeBlock(bc.GetHeaderByBlockNumber(blockNumber)) } @@ -298,26 +482,36 @@ func (bc *BlockchainDB) GetCurrentBlock() *types.Block { return bc.GetBlockByNumber(bc.GetNumber()) } +func (bc *BlockchainDB) GetTransactionsByBlockNumber(blockNumber uint64) []*types.Transaction { + txArray := bc.getTxArray(blockNumber) + n := txArray.MustLen() + txs := make([]*types.Transaction, n) + for i := uint32(0); i < n; i++ { + txs[i] = bc.GetTransactionByBlockNumberAndIndex(blockNumber, i) + } + return txs +} + +func (bc *BlockchainDB) GetReceiptsByBlockNumber(blockNumber uint64) []*types.Receipt { + txArray := bc.getTxArray(blockNumber) + n := txArray.MustLen() + receipts := make([]*types.Receipt, n) + for i := uint32(0); i < n; i++ { + receipts[i] = bc.GetReceiptByBlockNumberAndIndex(blockNumber, i) + } + return receipts +} + func (bc *BlockchainDB) makeBlock(header *types.Header) *types.Block { if header == nil { return nil } - tx := bc.GetTransactionByBlockNumber(header.Number) - if tx == nil { - return types.NewBlock( - header, - []*types.Transaction{}, - []*types.Header{}, - []*types.Receipt{}, - &fakeHasher{}, - ) - } - receipt := bc.GetReceiptByBlockNumber(header.Number) + blockNumber := header.Number.Uint64() return types.NewBlock( header, - []*types.Transaction{tx}, + bc.GetTransactionsByBlockNumber(blockNumber), []*types.Header{}, - []*types.Receipt{receipt}, + bc.GetReceiptsByBlockNumber(blockNumber), &fakeHasher{}, ) } diff --git a/contracts/native/evm/evmlight/emulator/emulator.go b/contracts/native/evm/evmlight/emulator/emulator.go index 38c09b70e0..32eb4fa9a6 100644 --- a/contracts/native/evm/evmlight/emulator/emulator.go +++ b/contracts/native/evm/evmlight/emulator/emulator.go @@ -5,7 +5,6 @@ package emulator import ( "errors" - "fmt" "math/big" "github.com/ethereum/go-ethereum" @@ -64,12 +63,12 @@ func newBlockchainDB(store kv.KVStore) *BlockchainDB { } // Init initializes the EVM state with the provided genesis allocation parameters -func Init(store kv.KVStore, chainID uint16, gasLimit, timestamp uint64, alloc core.GenesisAlloc) { +func Init(store kv.KVStore, chainID uint16, blockKeepAmount int32, gasLimit, timestamp uint64, alloc core.GenesisAlloc) { bdb := newBlockchainDB(store) if bdb.Initialized() { panic("evm state already initialized in kvstore") } - bdb.Init(chainID, gasLimit, timestamp) + bdb.Init(chainID, blockKeepAmount, gasLimit, timestamp) statedb := newStateDB(store) for addr, account := range alloc { @@ -179,7 +178,7 @@ func (e *EVMEmulator) EstimateGas(call ethereum.CallMsg) (uint64, error) { if errors.Is(err, core.ErrIntrinsicGas) { return true, nil, nil // Special case, raise gas limit } - return true, nil, fmt.Errorf("Bail out: %w", err) + return true, nil, xerrors.Errorf("Bail out: %w", err) } return res.Failed(), res, nil //nolint:gocritic } @@ -192,7 +191,7 @@ func (e *EVMEmulator) EstimateGas(call ethereum.CallMsg) (uint64, error) { // call or transaction will never be accepted no matter how much gas it is // assigned. Return the error directly, don't struggle any more if err != nil { - return 0, fmt.Errorf("executable(mid): %w", err) + return 0, xerrors.Errorf("executable(mid): %w", err) } if failed { lo = mid @@ -205,31 +204,22 @@ func (e *EVMEmulator) EstimateGas(call ethereum.CallMsg) (uint64, error) { if hi == max { failed, result, err := executable(hi) if err != nil { - return 0, fmt.Errorf("executable(hi): %w", err) + return 0, xerrors.Errorf("executable(hi): %w", err) } if failed { if result != nil && !errors.Is(result.Err, vm.ErrOutOfGas) { if len(result.Revert()) > 0 { return 0, newRevertError(result) } - return 0, fmt.Errorf("revert: %w", result.Err) + return 0, xerrors.Errorf("revert: %w", result.Err) } // Otherwise, the specified gas cap is too low - return 0, fmt.Errorf("gas required exceeds allowance (%d)", max) + return 0, xerrors.Errorf("gas required exceeds allowance (%d)", max) } } return hi, nil } -func (e *EVMEmulator) PendingHeader() *types.Header { - return &types.Header{ - Difficulty: &big.Int{}, - Number: new(big.Int).Add(e.BlockchainDB().GetNumber(), common.Big1), - GasLimit: e.GasLimit(), - Time: e.timestamp, - } -} - func (e *EVMEmulator) ChainContext() core.ChainContext { return &chainContext{ engine: ethash.NewFaker(), @@ -249,16 +239,16 @@ func (e *EVMEmulator) callContract(call ethereum.CallMsg) (*core.ExecutionResult } msg := callMsg{call} + pendingHeader := e.BlockchainDB().GetPendingHeader() // run the EVM code on a buffered state (so that writes are not committed) statedb := e.StateDB().Buffered().StateDB() - return e.applyMessage(msg, statedb) + return e.applyMessage(msg, statedb, pendingHeader) } -func (e *EVMEmulator) applyMessage(msg core.Message, statedb vm.StateDB) (*core.ExecutionResult, error) { - pendingHeader := e.PendingHeader() - blockContext := core.NewEVMBlockContext(pendingHeader, e.ChainContext(), nil) +func (e *EVMEmulator) applyMessage(msg core.Message, statedb vm.StateDB, header *types.Header) (*core.ExecutionResult, error) { + blockContext := core.NewEVMBlockContext(header, e.ChainContext(), nil) txContext := core.NewEVMTxContext(msg) vmEnv := vm.NewEVM(blockContext, txContext, statedb, e.chainConfig, e.vmConfig()) gasPool := core.GasPool(msg.Gas()) @@ -276,9 +266,11 @@ func (e *EVMEmulator) GetIEVMBackend() vm.ISCPBackend { return e.IEVMBackend } -// SendTransaction updates the pending block to include the given transaction. -// It returns an error if the transaction is invalid. func (e *EVMEmulator) SendTransaction(tx *types.Transaction) (*types.Receipt, error) { + buf := e.StateDB().Buffered() + statedb := buf.StateDB() + pendingHeader := e.BlockchainDB().GetPendingHeader() + sender, err := types.Sender(e.Signer(), tx) if err != nil { return nil, xerrors.Errorf("invalid transaction: %w", err) @@ -288,32 +280,35 @@ func (e *EVMEmulator) SendTransaction(tx *types.Transaction) (*types.Receipt, er return nil, xerrors.Errorf("invalid transaction nonce: got %d, want %d", tx.Nonce(), nonce) } - buf := e.StateDB().Buffered() - - pendingHeader := e.PendingHeader() msg, err := tx.AsMessage(types.MakeSigner(e.chainConfig, pendingHeader.Number), pendingHeader.BaseFee) if err != nil { return nil, err } - statedb := buf.StateDB() - - result, err := e.applyMessage(msg, statedb) + result, err := e.applyMessage(msg, statedb, pendingHeader) if err != nil { return nil, err } + cumulativeGasUsed := result.UsedGas + index := uint(0) + latest := e.BlockchainDB().GetLatestPendingReceipt() + if latest != nil { + cumulativeGasUsed += latest.CumulativeGasUsed + index = latest.TransactionIndex + 1 + } + receipt := &types.Receipt{ Type: tx.Type(), - CumulativeGasUsed: result.UsedGas, + CumulativeGasUsed: cumulativeGasUsed, TxHash: tx.Hash(), GasUsed: result.UsedGas, Logs: statedb.GetLogs(tx.Hash()), - BlockNumber: e.PendingHeader().Number, + BlockNumber: pendingHeader.Number, + TransactionIndex: index, } receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) if result.Failed() { - fmt.Printf("%s - gas limit %d - gas used %d - refund %d\n", result.Err, msg.Gas(), result.UsedGas, statedb.GetRefund()) receipt.Status = types.ReceiptStatusFailed } else { receipt.Status = types.ReceiptStatusSuccessful @@ -323,12 +318,15 @@ func (e *EVMEmulator) SendTransaction(tx *types.Transaction) (*types.Receipt, er } buf.Commit() - - e.BlockchainDB().AddTransaction(tx, receipt, e.timestamp) + e.BlockchainDB().AddTransaction(tx, receipt) return receipt, nil } +func (e *EVMEmulator) MintBlock() { + e.BlockchainDB().MintBlock(e.timestamp) +} + // FilterLogs executes a log filter operation, blocking during execution and // returning all the results in one batch. func (e *EVMEmulator) FilterLogs(query *ethereum.FilterQuery) []*types.Log { @@ -340,20 +338,16 @@ func (e *EVMEmulator) getReceiptsInFilterRange(query *ethereum.FilterQuery) []*t bc := e.BlockchainDB() if query.BlockHash != nil { - blockNumber := bc.GetBlockNumberByBlockHash(*query.BlockHash) - if blockNumber == nil { - return nil - } - receipt := bc.GetReceiptByBlockNumber(blockNumber) - if receipt == nil { + blockNumber, ok := bc.GetBlockNumberByBlockHash(*query.BlockHash) + if !ok { return nil } - return []*types.Receipt{receipt} + return bc.GetReceiptsByBlockNumber(blockNumber) } // Initialize unset filter boundaries to run from genesis to chain head first := big.NewInt(1) // skip genesis since it has no logs - last := bc.GetNumber() + last := new(big.Int).SetUint64(bc.GetNumber()) from := first if query.FromBlock != nil && query.FromBlock.Cmp(first) >= 0 && query.FromBlock.Cmp(last) <= 0 { from = query.FromBlock @@ -364,10 +358,10 @@ func (e *EVMEmulator) getReceiptsInFilterRange(query *ethereum.FilterQuery) []*t } var receipts []*types.Receipt - for i := new(big.Int).Set(from); i.Cmp(to) <= 0; i = i.Add(i, common.Big1) { - receipt := bc.GetReceiptByBlockNumber(i) - if receipt != nil { - receipts = append(receipts, receipt) + { + to := to.Uint64() + for i := from.Uint64(); i <= to; i++ { + receipts = append(receipts, bc.GetReceiptsByBlockNumber(i)...) } } return receipts diff --git a/contracts/native/evm/evmlight/emulator/emulator_test.go b/contracts/native/evm/evmlight/emulator/emulator_test.go index f45f0df61c..69fdbdfbe5 100644 --- a/contracts/native/evm/evmlight/emulator/emulator_test.go +++ b/contracts/native/evm/evmlight/emulator/emulator_test.go @@ -52,6 +52,7 @@ func sendTransaction(t testing.TB, emu *EVMEmulator, sender *ecdsa.PrivateKey, r receipt, err := emu.SendTransaction(tx) require.NoError(t, err) + emu.MintBlock() return receipt } @@ -73,7 +74,7 @@ func TestBlockchain(t *testing.T) { } db := dict.Dict{} - Init(db, evm.DefaultChainID, evm.GasLimitDefault, 0, genesisAlloc) + Init(db, evm.DefaultChainID, evm.BlockKeepAll, evm.GasLimitDefault, 0, genesisAlloc) emu := NewEVMEmulator(db, 1, &iscpBackend{}) // some assertions @@ -81,7 +82,7 @@ func TestBlockchain(t *testing.T) { require.EqualValues(t, evm.GasLimitDefault, emu.BlockchainDB().GetGasLimit()) require.EqualValues(t, evm.DefaultChainID, emu.BlockchainDB().GetChainID()) - genesis := emu.BlockchainDB().GetBlockByNumber(common.Big0) + genesis := emu.BlockchainDB().GetBlockByNumber(0) require.NotNil(t, genesis) // the genesis block has block number 0 @@ -117,13 +118,13 @@ func TestBlockchain(t *testing.T) { { receipt := sendTransaction(t, emu, faucet, receiverAddress, transferAmount, nil) - require.EqualValues(t, 1, emu.BlockchainDB().GetNumber().Uint64()) + require.EqualValues(t, 1, emu.BlockchainDB().GetNumber()) block := emu.BlockchainDB().GetCurrentBlock() require.EqualValues(t, 1, block.Header().Number.Uint64()) require.EqualValues(t, evm.GasLimitDefault, block.Header().GasLimit) require.EqualValues(t, receipt.Bloom, block.Bloom()) require.EqualValues(t, receipt.GasUsed, block.GasUsed()) - require.EqualValues(t, emu.BlockchainDB().GetBlockByNumber(common.Big0).Hash(), block.ParentHash()) + require.EqualValues(t, emu.BlockchainDB().GetBlockByNumber(0).Hash(), block.ParentHash()) } { @@ -152,7 +153,7 @@ func TestBlockchainPersistence(t *testing.T) { transferAmount := big.NewInt(1000) db := dict.Dict{} - Init(db, evm.DefaultChainID, evm.GasLimitDefault, 0, genesisAlloc) + Init(db, evm.DefaultChainID, evm.BlockKeepAll, evm.GasLimitDefault, 0, genesisAlloc) // do a transfer using one instance of EVMEmulator func() { @@ -200,12 +201,13 @@ func deployEVMContract(t testing.TB, emu *EVMEmulator, creator *ecdsa.PrivateKey receipt, err := emu.SendTransaction(tx) require.NoError(t, err) + emu.MintBlock() contractAddress := crypto.CreateAddress(creatorAddress, nonce) // assertions { - require.EqualValues(t, 1, emu.BlockchainDB().GetNumber().Uint64()) + require.EqualValues(t, 1, emu.BlockchainDB().GetNumber()) // verify contract address { @@ -253,7 +255,7 @@ func TestStorageContract(t *testing.T) { } db := dict.Dict{} - Init(db, evm.DefaultChainID, evm.GasLimitDefault, 0, genesisAlloc) + Init(db, evm.DefaultChainID, evm.BlockKeepAll, evm.GasLimitDefault, 0, genesisAlloc) emu := NewEVMEmulator(db, 1, &iscpBackend{}) contractABI, err := abi.JSON(strings.NewReader(evmtest.StorageContractABI)) @@ -284,13 +286,13 @@ func TestStorageContract(t *testing.T) { require.EqualValues(t, 42, v) // no state change - require.EqualValues(t, 1, emu.BlockchainDB().GetNumber().Uint64()) + require.EqualValues(t, 1, emu.BlockchainDB().GetNumber()) } // send tx that calls `store(43)` { callFn(faucet, "store", uint32(43)) - require.EqualValues(t, 2, emu.BlockchainDB().GetNumber().Uint64()) + require.EqualValues(t, 2, emu.BlockchainDB().GetNumber()) } // call `retrieve` view again, get 43 @@ -311,7 +313,7 @@ func TestStorageContract(t *testing.T) { require.EqualValues(t, 43, v) // no state change - require.EqualValues(t, 2, emu.BlockchainDB().GetNumber().Uint64()) + require.EqualValues(t, 2, emu.BlockchainDB().GetNumber()) } } @@ -327,7 +329,7 @@ func TestERC20Contract(t *testing.T) { } db := dict.Dict{} - Init(db, evm.DefaultChainID, evm.GasLimitDefault, 0, genesisAlloc) + Init(db, evm.DefaultChainID, evm.BlockKeepAll, evm.GasLimitDefault, 0, genesisAlloc) emu := NewEVMEmulator(db, 1, &iscpBackend{}) contractABI, err := abi.JSON(strings.NewReader(evmtest.ERC20ContractABI)) @@ -418,7 +420,7 @@ func initBenchmark(b *testing.B) (*EVMEmulator, []*types.Transaction, dict.Dict) } db := dict.Dict{} - Init(db, evm.DefaultChainID, evm.GasLimitDefault, 0, genesisAlloc) + Init(db, evm.DefaultChainID, evm.BlockKeepAll, evm.GasLimitDefault, 0, genesisAlloc) emu := NewEVMEmulator(db, 1, &iscpBackend{}) contractABI, err := abi.JSON(strings.NewReader(evmtest.StorageContractABI)) @@ -457,26 +459,48 @@ func initBenchmark(b *testing.B) (*EVMEmulator, []*types.Transaction, dict.Dict) return emu, txs, db } -// BenchmarkEVMEmulator is a benchmark for the EVMEmulator that sends N EVM transactions. +// benchmarkEVMEmulator is a benchmark for the EVMEmulator that sends N EVM transactions +// calling `storage.store()`, committing a block every k transactions. // // run with: go test -benchmem -cpu=1 -run=' ' -bench='Bench.*' // // To generate mem and cpu profiles, add -cpuprofile=cpu.out -memprofile=mem.out // Then: go tool pprof -http :8080 {cpu,mem}.out -func BenchmarkEVMEmulator(b *testing.B) { +func benchmarkEVMEmulator(b *testing.B, k int) { // setup: deploy the storage contract and prepare N transactions to send emu, txs, db := initBenchmark(b) + var chunks [][]*types.Transaction + var chunk []*types.Transaction + for _, tx := range txs { + chunk = append(chunk, tx) + if len(chunk) == k { + chunks = append(chunks, chunk) + chunk = nil + } + } + if len(chunk) > 0 { + chunks = append(chunks, chunk) + } + b.ResetTimer() - for i := 0; i < b.N; i++ { - receipt, err := emu.SendTransaction(txs[i]) - require.NoError(b, err) - require.Equal(b, types.ReceiptStatusSuccessful, receipt.Status) + for _, chunk := range chunks { + for _, tx := range chunk { + receipt, err := emu.SendTransaction(tx) + require.NoError(b, err) + require.Equal(b, types.ReceiptStatusSuccessful, receipt.Status) + } + emu.MintBlock() } b.ReportMetric(dbSize(db)/float64(b.N), "db:bytes/op") } +func BenchmarkEVMEmulator1(b *testing.B) { benchmarkEVMEmulator(b, 1) } +func BenchmarkEVMEmulator10(b *testing.B) { benchmarkEVMEmulator(b, 10) } +func BenchmarkEVMEmulator50(b *testing.B) { benchmarkEVMEmulator(b, 50) } +func BenchmarkEVMEmulator100(b *testing.B) { benchmarkEVMEmulator(b, 100) } + func dbSize(db kv.KVStore) float64 { r := float64(0) db.MustIterate("", func(key kv.Key, value []byte) bool { diff --git a/contracts/native/evm/evmlight/impl.go b/contracts/native/evm/evmlight/impl.go index 087f6f460d..5ecee157cb 100644 --- a/contracts/native/evm/evmlight/impl.go +++ b/contracts/native/evm/evmlight/impl.go @@ -4,6 +4,8 @@ package evmlight import ( + "math/big" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/iotaledger/wasp/contracts/native/evm" @@ -20,6 +22,7 @@ import ( var Processor = Contract.Processor(initialize, append( evminternal.ManagementHandlers, + evm.FuncMintBlock.WithHandler(mintBlock), evm.FuncSendTransaction.WithHandler(applyTransaction), evm.FuncGetBalance.WithHandler(getBalance), evm.FuncCallContract.WithHandler(callContract), @@ -44,15 +47,22 @@ func initialize(ctx iscp.Sandbox) (dict.Dict, error) { genesisAlloc, err := evmtypes.DecodeGenesisAlloc(ctx.Params().MustGet(evm.FieldGenesisAlloc)) a.RequireNoError(err) + gasLimit, err := codec.DecodeUint64(ctx.Params().MustGet(evm.FieldGasLimit), evm.GasLimitDefault) + a.RequireNoError(err) + + blockKeepAmount, err := codec.DecodeInt32(ctx.Params().MustGet(evm.FieldBlockKeepAmount), evm.BlockKeepAmountDefault) + a.RequireNoError(err) + // add the standard ISCP contract at arbitrary address 0x1074 iscpcontract.DeployOnGenesis(genesisAlloc, ctx.ChainID()) chainID, err := codec.DecodeUint16(ctx.Params().MustGet(evm.FieldChainID), evm.DefaultChainID) a.RequireNoError(err) emulator.Init( - evmStateSubrealm(ctx.State()), + evminternal.EVMStateSubrealm(ctx.State()), chainID, - evm.GasLimitDefault, // TODO: make gas limit configurable + blockKeepAmount, + gasLimit, timestamp(ctx), genesisAlloc, ) @@ -60,19 +70,25 @@ func initialize(ctx iscp.Sandbox) (dict.Dict, error) { return nil, nil } -func applyTransaction(ctx iscp.Sandbox) (dict.Dict, error) { - a := assert.NewAssert(ctx.Log()) - - tx := &types.Transaction{} - err := tx.UnmarshalBinary(ctx.Params().MustGet(evm.FieldTransactionData)) - a.RequireNoError(err) +func mintBlock(ctx iscp.Sandbox) (dict.Dict, error) { + evminternal.ScheduleNextBlock(ctx) + emu := createEmulator(ctx) + emu.MintBlock() + return nil, nil +} - return evminternal.RequireGasFee(ctx, tx.Gas(), func() uint64 { - emu := createEmulator(ctx) - receipt, err := emu.SendTransaction(tx) - a.RequireNoError(err) - return receipt.GasUsed - }), nil +func applyTransaction(ctx iscp.Sandbox) (dict.Dict, error) { + return evminternal.ApplyTransaction(ctx, func(tx *types.Transaction, blockTime uint32) (*types.Receipt, error) { + var emu *emulator.EVMEmulator + if blockTime > 0 { + // next block will be minted when mintBlock() is called (via timelocked request) + emu = createEmulator(ctx) + } else { + // next block will be minted when the ISCP block is closed + emu = getEmulatorInBlockContext(ctx) + } + return emu.SendTransaction(tx) + }) } func getBalance(ctx iscp.SandboxView) (dict.Dict, error) { @@ -84,7 +100,7 @@ func getBalance(ctx iscp.SandboxView) (dict.Dict, error) { func getBlockNumber(ctx iscp.SandboxView) (dict.Dict, error) { emu := createEmulatorR(ctx) - return evminternal.Result(emu.BlockchainDB().GetNumber().Bytes()), nil + return evminternal.Result(new(big.Int).SetUint64(emu.BlockchainDB().GetNumber()).Bytes()), nil } func getBlockByNumber(ctx iscp.SandboxView) (dict.Dict, error) { diff --git a/contracts/native/evm/evmlight/internal.go b/contracts/native/evm/evmlight/internal.go index 67579d4e00..3eece7f9d6 100644 --- a/contracts/native/evm/evmlight/internal.go +++ b/contracts/native/evm/evmlight/internal.go @@ -16,27 +16,28 @@ import ( "github.com/iotaledger/wasp/packages/evm/evmtypes" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/assert" - "github.com/iotaledger/wasp/packages/kv" "github.com/iotaledger/wasp/packages/kv/buffered" "github.com/iotaledger/wasp/packages/kv/codec" "github.com/iotaledger/wasp/packages/kv/dict" - "github.com/iotaledger/wasp/packages/kv/subrealm" ) -// keyEVMState is the subrealm prefix for the EVM state -// If changed, make sure it does not collide with evm management keys -const keyEVMState = "s" - -func evmStateSubrealm(state kv.KVStore) kv.KVStore { - return subrealm.New(state, keyEVMState) +// getEmulatorInBlockContext creates a new emulator instance if this is the first call to applyTransaction +// in the ISCP block; otherwise it returns the previously created instance. The purpose is to +// create a single Ethereum block for each ISCP block. +func getEmulatorInBlockContext(ctx iscp.Sandbox) *emulator.EVMEmulator { + bctx := ctx.BlockContext( + func(ctx iscp.Sandbox) interface{} { return createEmulator(ctx) }, + func(bctx interface{}) { bctx.(*emulator.EVMEmulator).MintBlock() }, + ) + return bctx.(*emulator.EVMEmulator) } func createEmulator(ctx iscp.Sandbox) *emulator.EVMEmulator { - return emulator.NewEVMEmulator(evmStateSubrealm(ctx.State()), timestamp(ctx), &iscpBackend{ctx}) + return emulator.NewEVMEmulator(evminternal.EVMStateSubrealm(ctx.State()), timestamp(ctx), &iscpBackend{ctx}) } func createEmulatorR(ctx iscp.SandboxView) *emulator.EVMEmulator { - return emulator.NewEVMEmulator(evmStateSubrealm(buffered.NewBufferedKVStoreAccess(ctx.State())), timestamp(ctx), &iscpBackendR{ctx}) + return emulator.NewEVMEmulator(evminternal.EVMStateSubrealm(buffered.NewBufferedKVStoreAccess(ctx.State())), timestamp(ctx), &iscpBackendR{ctx}) } // timestamp returns the current timestamp in seconds since epoch @@ -57,11 +58,14 @@ func txResult(emu *emulator.EVMEmulator, tx *types.Transaction) (dict.Dict, erro return nil, nil } bc := emu.BlockchainDB() - blockNumber := bc.GetBlockNumberByTxHash(tx.Hash()) + blockNumber, ok := bc.GetBlockNumberByTxHash(tx.Hash()) + if !ok { + panic("cannot find block number of tx") + } return dict.Dict{ evm.FieldTransaction: evmtypes.EncodeTransaction(tx), evm.FieldBlockHash: bc.GetBlockHashByBlockNumber(blockNumber).Bytes(), - evm.FieldBlockNumber: codec.EncodeUint64(blockNumber.Uint64()), + evm.FieldBlockNumber: codec.EncodeUint64(blockNumber), }, nil } @@ -101,17 +105,13 @@ func transactionByBlockHashAndIndex(ctx iscp.SandboxView) (*emulator.EVMEmulator a := assert.NewAssert(ctx.Log()) index, err := codec.DecodeUint64(ctx.Params().MustGet(evm.FieldTransactionIndex), 0) a.RequireNoError(err) - // all blocks contain at most 1 tx - if index > 0 { - return emu, nil - } bc := emu.BlockchainDB() - blockNumber := bc.GetBlockNumberByBlockHash(blockHash) - if blockNumber == nil { + blockNumber, ok := bc.GetBlockNumberByBlockHash(blockHash) + if !ok { return emu, nil } - return emu, bc.GetTransactionByBlockNumber(blockNumber) + return emu, bc.GetTransactionByBlockNumberAndIndex(blockNumber, uint32(index)) } func transactionByBlockNumberAndIndex(ctx iscp.SandboxView) (*emulator.EVMEmulator, *types.Transaction) { @@ -121,38 +121,34 @@ func transactionByBlockNumberAndIndex(ctx iscp.SandboxView) (*emulator.EVMEmulat a := assert.NewAssert(ctx.Log()) index, err := codec.DecodeUint64(ctx.Params().MustGet(evm.FieldTransactionIndex), 0) a.RequireNoError(err) - // all blocks contain at most 1 tx - if index > 0 { - return emu, nil - } - return emu, emu.BlockchainDB().GetTransactionByBlockNumber(blockNumber) + return emu, emu.BlockchainDB().GetTransactionByBlockNumberAndIndex(blockNumber, uint32(index)) } -func requireLatestBlock(ctx iscp.SandboxView, emu *emulator.EVMEmulator, allowPrevious bool, blockNumber *big.Int) *big.Int { +func requireLatestBlock(ctx iscp.SandboxView, emu *emulator.EVMEmulator, allowPrevious bool, blockNumber uint64) uint64 { current := emu.BlockchainDB().GetNumber() - if blockNumber.Cmp(current) != 0 { + if blockNumber != current { assert.NewAssert(ctx.Log()).Require(allowPrevious, "unsupported operation") } return blockNumber } -func paramBlockNumber(ctx iscp.SandboxView, emu *emulator.EVMEmulator, allowPrevious bool) *big.Int { +func paramBlockNumber(ctx iscp.SandboxView, emu *emulator.EVMEmulator, allowPrevious bool) uint64 { current := emu.BlockchainDB().GetNumber() if ctx.Params().MustHas(evm.FieldBlockNumber) { blockNumber := new(big.Int).SetBytes(ctx.Params().MustGet(evm.FieldBlockNumber)) - return requireLatestBlock(ctx, emu, allowPrevious, blockNumber) + return requireLatestBlock(ctx, emu, allowPrevious, blockNumber.Uint64()) } return current } -func paramBlockNumberOrHashAsNumber(ctx iscp.SandboxView, emu *emulator.EVMEmulator, allowPrevious bool) *big.Int { // nolint:unparam +func paramBlockNumberOrHashAsNumber(ctx iscp.SandboxView, emu *emulator.EVMEmulator, allowPrevious bool) uint64 { // nolint:unparam if ctx.Params().MustHas(evm.FieldBlockHash) { a := assert.NewAssert(ctx.Log()) blockHash := common.BytesToHash(ctx.Params().MustGet(evm.FieldBlockHash)) header := emu.BlockchainDB().GetHeaderByHash(blockHash) a.Require(header != nil, "block not found") - return requireLatestBlock(ctx, emu, allowPrevious, header.Number) + return requireLatestBlock(ctx, emu, allowPrevious, header.Number.Uint64()) } return paramBlockNumber(ctx, emu, allowPrevious) } diff --git a/contracts/native/evm/evmtest/evm_test.go b/contracts/native/evm/evmtest/evm_test.go index 3da67cd6ca..c19ecdd059 100644 --- a/contracts/native/evm/evmtest/evm_test.go +++ b/contracts/native/evm/evmtest/evm_test.go @@ -7,12 +7,14 @@ import ( "bytes" "math/big" "testing" + "time" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/iotaledger/wasp/contracts/native/evm" "github.com/iotaledger/wasp/contracts/native/evm/evmchain" "github.com/iotaledger/wasp/contracts/native/evm/evmlight" + "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/evm/evmflavors" "github.com/iotaledger/wasp/packages/evm/evmtest" "github.com/iotaledger/wasp/packages/iscp" @@ -45,6 +47,7 @@ func TestStorageContract(t *testing.T) { // deploy solidity `storage` contract storage := evmChain.deployStorageContract(evmChain.faucetKey, 42) + require.EqualValues(t, 1, evmChain.getBlockNumber()) // call FuncCallView to call EVM contract's `retrieve` view, get 42 require.EqualValues(t, 42, storage.retrieve()) @@ -53,6 +56,7 @@ func TestStorageContract(t *testing.T) { res, err := storage.store(43) require.NoError(t, err) require.Equal(t, types.ReceiptStatusSuccessful, res.receipt.Status) + require.EqualValues(t, 2, evmChain.getBlockNumber()) // call `retrieve` view, get 43 require.EqualValues(t, 43, storage.retrieve()) @@ -214,7 +218,7 @@ func TestGasPerIotas(t *testing.T) { newGasPerIota := evm.DefaultGasPerIota * 1000 newUserWallet, _ := evmChain.solo.NewKeyPairWithFunds() err = evmChain.setGasPerIotas(newGasPerIota, iotaCallOptions{wallet: newUserWallet}) - require.Contains(t, err.Error(), "can only be called by the contract owner") + require.Contains(t, err.Error(), "unauthorized access") require.Equal(t, evm.DefaultGasPerIota, evmChain.getGasPerIotas()) // current owner is able to set a new gasPerIotas @@ -239,7 +243,7 @@ func TestWithdrawalOwnerFees(t *testing.T) { user1AgentID := iscp.NewAgentID(user1Address, 0) err := evmChain.withdrawGasFees(user1Wallet) - require.Contains(t, err.Error(), "can only be called by the contract owner") + require.Contains(t, err.Error(), "unauthorized access") // change owner to user1 err = evmChain.setNextOwner(user1AgentID) @@ -438,6 +442,48 @@ func TestISCPEntropy(t *testing.T) { require.NotEqualValues(t, entropy, make([]byte, 32)) } +func TestBlockTime(t *testing.T) { + evmChain := initEVMChain(t, evmlight.Contract) + evmChain.setBlockTime(60) + + storage := evmChain.deployStorageContract(evmChain.faucetKey, 42) + require.EqualValues(t, 42, storage.retrieve()) + require.EqualValues(t, 0, evmChain.getBlockNumber()) + + res, err := storage.store(43) + require.NoError(t, err) + require.Equal(t, types.ReceiptStatusSuccessful, res.receipt.Status) + + require.EqualValues(t, 43, storage.retrieve()) + require.EqualValues(t, 0, evmChain.getBlockNumber()) + + // there is 1 timelocked request + mempoolInfo := evmChain.soloChain.MempoolInfo() + require.EqualValues(t, 1, mempoolInfo.InBufCounter-mempoolInfo.OutPoolCounter) + + // first block gets minted + evmChain.solo.AdvanceClockBy(61 * time.Second) + evmChain.soloChain.WaitUntil(func(mstats chain.MempoolInfo) bool { + return mstats.OutPoolCounter == mempoolInfo.InBufCounter + }) + require.EqualValues(t, 1, evmChain.getBlockNumber()) + block := evmChain.getBlockByNumber(1) + require.EqualValues(t, 2, len(block.Transactions())) + + // there is 1 timelocked request + mempoolInfo = evmChain.soloChain.MempoolInfo() + require.EqualValues(t, 1, mempoolInfo.InBufCounter-mempoolInfo.OutPoolCounter) + + // second (empty) block gets minted + evmChain.solo.AdvanceClockBy(61 * time.Second) + evmChain.soloChain.WaitUntil(func(mstats chain.MempoolInfo) bool { + return mstats.OutPoolCounter == mempoolInfo.InBufCounter + }) + require.EqualValues(t, 2, evmChain.getBlockNumber()) + block = evmChain.getBlockByNumber(2) + require.EqualValues(t, 0, len(block.Transactions())) +} + func initBenchmark(b *testing.B, evmFlavor *coreutil.ContractInfo) (*solo.Chain, []*solo.CallParams) { // setup: deploy the EVM chain log := testlogger.NewSilentLogger(b.Name(), true) @@ -466,8 +512,8 @@ func initBenchmark(b *testing.B, evmFlavor *coreutil.ContractInfo) (*solo.Chain, // run benchmarks with: go test -benchmem -cpu=1 -run=' ' -bench='Bench.*' func doBenchmark(b *testing.B, evmFlavor *coreutil.ContractInfo, f solobench.Func) { - chain, reqs := initBenchmark(b, evmFlavor) - f(b, chain, reqs, nil) + ch, reqs := initBenchmark(b, evmFlavor) + f(b, ch, reqs, nil) } func BenchmarkEVMChainSync(b *testing.B) { diff --git a/contracts/native/evm/evmtest/utils_test.go b/contracts/native/evm/evmtest/utils_test.go index f079f775f1..efa08dd119 100644 --- a/contracts/native/evm/evmtest/utils_test.go +++ b/contracts/native/evm/evmtest/utils_test.go @@ -141,6 +141,25 @@ func (e *evmChainInstance) callView(funName string, params ...interface{}) (dict return e.soloChain.CallView(e.evmFlavor.Name, funName, params...) } +func (e *evmChainInstance) setBlockTime(t uint32) { + _, err := e.postRequest(nil, evm.FuncSetBlockTime.Name, evm.FieldBlockTime, codec.EncodeUint32(t)) + require.NoError(e.t, err) +} + +func (e *evmChainInstance) getBlockNumber() uint64 { + ret, err := e.callView(evm.FuncGetBlockNumber.Name) + require.NoError(e.t, err) + return new(big.Int).SetBytes(ret.MustGet(evm.FieldResult)).Uint64() +} + +func (e *evmChainInstance) getBlockByNumber(n uint64) *types.Block { + ret, err := e.callView(evm.FuncGetBlockByNumber.Name, evm.FieldBlockNumber, new(big.Int).SetUint64(n).Bytes()) + require.NoError(e.t, err) + block, err := evmtypes.DecodeBlock(ret.MustGet(evm.FieldResult)) + require.NoError(e.t, err) + return block +} + func (e *evmChainInstance) getCode(addr common.Address) []byte { ret, err := e.callView(evm.FuncGetCode.Name, evm.FieldAddress, addr.Bytes()) require.NoError(e.t, err) @@ -369,7 +388,7 @@ func (e *evmContractInstance) callFn(opts []ethCallOptions, fnName string, args res.receipt, err = evmtypes.DecodeReceiptFull(receiptResult.MustGet(evm.FieldResult)) require.NoError(e.chain.t, err) - require.LessOrEqual(e.chain.t, res.receipt.GasUsed, gasUsed) + require.EqualValues(e.chain.t, res.receipt.GasUsed, gasUsed) return } diff --git a/contracts/native/evm/interface.go b/contracts/native/evm/interface.go index 58ff731689..2ae60496e2 100644 --- a/contracts/native/evm/interface.go +++ b/contracts/native/evm/interface.go @@ -36,6 +36,8 @@ var ( FuncSetGasPerIota = coreutil.Func("setGasPerIota") FuncGetGasPerIota = coreutil.ViewFunc("getGasPerIota") FuncWithdrawGasFees = coreutil.Func("withdrawGasFees") + FuncSetBlockTime = coreutil.Func("setBlockTime") // only implemented by evmlight + FuncMintBlock = coreutil.Func("mintBlock") // only implemented by evmlight ) const ( @@ -58,7 +60,13 @@ const ( FieldGasPerIota = "w" FieldGasFee = "f" FieldGasUsed = "gu" + FieldGasLimit = "gl" FieldFilterQuery = "fq" + + // evmlight only: + + FieldBlockTime = "bt" // uint32, avg block time in seconds + FieldBlockKeepAmount = "bk" // int32 ) const ( @@ -66,6 +74,9 @@ const ( DefaultGasPerIota uint64 = 1000 GasLimitDefault = uint64(15000000) + + BlockKeepAll = -1 + BlockKeepAmountDefault = BlockKeepAll ) var GasPrice = big.NewInt(0) diff --git a/contracts/wasm/Cargo.lock b/contracts/wasm/Cargo.lock index e8ccdfca85..291995c168 100644 --- a/contracts/wasm/Cargo.lock +++ b/contracts/wasm/Cargo.lock @@ -58,6 +58,16 @@ dependencies = [ "wee_alloc", ] +[[package]] +name = "erc721" +version = "0.1.0" +dependencies = [ + "console_error_panic_hook", + "wasm-bindgen-test", + "wasmlib", + "wee_alloc", +] + [[package]] name = "fairauction" version = "0.1.0" @@ -189,6 +199,16 @@ dependencies = [ "wee_alloc", ] +[[package]] +name = "timestamp" +version = "0.1.0" +dependencies = [ + "console_error_panic_hook", + "wasm-bindgen-test", + "wasmlib", + "wee_alloc", +] + [[package]] name = "tokenregistry" version = "0.1.0" diff --git a/contracts/wasm/Cargo.toml b/contracts/wasm/Cargo.toml index 3c67490556..08c3d6d18b 100644 --- a/contracts/wasm/Cargo.toml +++ b/contracts/wasm/Cargo.toml @@ -6,12 +6,14 @@ members = [ "dividend", "donatewithfeedback", "erc20", + "erc721", "fairauction", "fairroulette", "helloworld", "inccounter", "testcore", "testwasmlib", + "timestamp", "tokenregistry", ] diff --git a/contracts/wasm/all_build.cmd b/contracts/wasm/all_build.cmd new file mode 100644 index 0000000000..5bd52b3beb --- /dev/null +++ b/contracts/wasm/all_build.cmd @@ -0,0 +1,6 @@ +@echo off +call core_build.cmd +call go_all.cmd -force +call ts_all.cmd -force +call rust_all.cmd -force +call update_hardcoded.cmd diff --git a/contracts/wasm/cleanup.cmd b/contracts/wasm/cleanup.cmd index 60650bbb4d..794b584bfc 100644 --- a/contracts/wasm/cleanup.cmd +++ b/contracts/wasm/cleanup.cmd @@ -8,10 +8,12 @@ del /s state.* del /s typedefs.* del /s types.* del /s main.go -del /s index.ts -del /s tsconfig.json del /s /q *.wasm -for /d %%f in (*.) do del /s /q %%f\go\pkg\*.* + +rem careful, this could fuck up fairroulette frontend +for /d %%f in (*.) do del %%f\ts\%%f\index.ts +for /d %%f in (*.) do del %%f\ts\%%f\tsconfig.json + for /d %%f in (*.) do del /s /q %%f\pkg\*.* for /d %%f in (*.) do del /s /q %%f\ts\pkg\*.* del /s /q target\*.* diff --git a/contracts/wasm/dividend/go/dividend/consts.go b/contracts/wasm/dividend/go/dividend/consts.go index c6ef2283ad..2e90e341e5 100644 --- a/contracts/wasm/dividend/go/dividend/consts.go +++ b/contracts/wasm/dividend/go/dividend/consts.go @@ -16,21 +16,21 @@ const ( ) const ( - ParamAddress = wasmlib.Key("address") - ParamFactor = wasmlib.Key("factor") - ParamOwner = wasmlib.Key("owner") + ParamAddress = "address" + ParamFactor = "factor" + ParamOwner = "owner" ) const ( - ResultFactor = wasmlib.Key("factor") - ResultOwner = wasmlib.Key("owner") + ResultFactor = "factor" + ResultOwner = "owner" ) const ( - StateMemberList = wasmlib.Key("memberList") - StateMembers = wasmlib.Key("members") - StateOwner = wasmlib.Key("owner") - StateTotalFactor = wasmlib.Key("totalFactor") + StateMemberList = "memberList" + StateMembers = "members" + StateOwner = "owner" + StateTotalFactor = "totalFactor" ) const ( diff --git a/contracts/wasm/dividend/go/dividend/keys.go b/contracts/wasm/dividend/go/dividend/keys.go index aa3708f338..d195ce5296 100644 --- a/contracts/wasm/dividend/go/dividend/keys.go +++ b/contracts/wasm/dividend/go/dividend/keys.go @@ -10,11 +10,13 @@ package dividend import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" const ( - IdxParamAddress = 0 - IdxParamFactor = 1 - IdxParamOwner = 2 - IdxResultFactor = 3 - IdxResultOwner = 4 + IdxParamAddress = 0 + IdxParamFactor = 1 + IdxParamOwner = 2 + + IdxResultFactor = 3 + IdxResultOwner = 4 + IdxStateMemberList = 5 IdxStateMembers = 6 IdxStateOwner = 7 diff --git a/contracts/wasm/dividend/go/dividend/lib.go b/contracts/wasm/dividend/go/dividend/lib.go index 141fd7ad4c..ea83c8abb5 100644 --- a/contracts/wasm/dividend/go/dividend/lib.go +++ b/contracts/wasm/dividend/go/dividend/lib.go @@ -64,6 +64,7 @@ type MemberContext struct { func funcMemberThunk(ctx wasmlib.ScFuncContext) { ctx.Log("dividend.funcMember") + // only defined owner of contract can add members access := ctx.State().GetAgentID(wasmlib.Key("owner")) ctx.Require(access.Exists(), "access not set: owner") @@ -90,6 +91,7 @@ type SetOwnerContext struct { func funcSetOwnerThunk(ctx wasmlib.ScFuncContext) { ctx.Log("dividend.funcSetOwner") + // only defined owner of contract can change owner access := ctx.State().GetAgentID(wasmlib.Key("owner")) ctx.Require(access.Exists(), "access not set: owner") diff --git a/contracts/wasm/dividend/src/consts.rs b/contracts/wasm/dividend/src/consts.rs index 9223c37771..5d0faa11c5 100644 --- a/contracts/wasm/dividend/src/consts.rs +++ b/contracts/wasm/dividend/src/consts.rs @@ -5,40 +5,36 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; -pub const SC_NAME: &str = "dividend"; -pub const SC_DESCRIPTION: &str = "Simple dividend smart contract"; -pub const HSC_NAME: ScHname = ScHname(0xcce2e239); - -pub const PARAM_ADDRESS: &str = "address"; -pub const PARAM_FACTOR: &str = "factor"; -pub const PARAM_OWNER: &str = "owner"; - -pub const RESULT_FACTOR: &str = "factor"; -pub const RESULT_OWNER: &str = "owner"; - -pub const STATE_MEMBER_LIST: &str = "memberList"; -pub const STATE_MEMBERS: &str = "members"; -pub const STATE_OWNER: &str = "owner"; -pub const STATE_TOTAL_FACTOR: &str = "totalFactor"; - -pub const FUNC_DIVIDE: &str = "divide"; -pub const FUNC_INIT: &str = "init"; -pub const FUNC_MEMBER: &str = "member"; -pub const FUNC_SET_OWNER: &str = "setOwner"; -pub const VIEW_GET_FACTOR: &str = "getFactor"; -pub const VIEW_GET_OWNER: &str = "getOwner"; - -pub const HFUNC_DIVIDE: ScHname = ScHname(0xc7878107); -pub const HFUNC_INIT: ScHname = ScHname(0x1f44d644); -pub const HFUNC_MEMBER: ScHname = ScHname(0xc07da2cb); -pub const HFUNC_SET_OWNER: ScHname = ScHname(0x2a15fe7b); -pub const HVIEW_GET_FACTOR: ScHname = ScHname(0x0ee668fe); -pub const HVIEW_GET_OWNER: ScHname = ScHname(0x137107a6); - -// @formatter:on +pub const SC_NAME : &str = "dividend"; +pub const SC_DESCRIPTION : &str = "Simple dividend smart contract"; +pub const HSC_NAME : ScHname = ScHname(0xcce2e239); + +pub const PARAM_ADDRESS : &str = "address"; +pub const PARAM_FACTOR : &str = "factor"; +pub const PARAM_OWNER : &str = "owner"; + +pub const RESULT_FACTOR : &str = "factor"; +pub const RESULT_OWNER : &str = "owner"; + +pub const STATE_MEMBER_LIST : &str = "memberList"; +pub const STATE_MEMBERS : &str = "members"; +pub const STATE_OWNER : &str = "owner"; +pub const STATE_TOTAL_FACTOR : &str = "totalFactor"; + +pub const FUNC_DIVIDE : &str = "divide"; +pub const FUNC_INIT : &str = "init"; +pub const FUNC_MEMBER : &str = "member"; +pub const FUNC_SET_OWNER : &str = "setOwner"; +pub const VIEW_GET_FACTOR : &str = "getFactor"; +pub const VIEW_GET_OWNER : &str = "getOwner"; + +pub const HFUNC_DIVIDE : ScHname = ScHname(0xc7878107); +pub const HFUNC_INIT : ScHname = ScHname(0x1f44d644); +pub const HFUNC_MEMBER : ScHname = ScHname(0xc07da2cb); +pub const HFUNC_SET_OWNER : ScHname = ScHname(0x2a15fe7b); +pub const HVIEW_GET_FACTOR : ScHname = ScHname(0x0ee668fe); +pub const HVIEW_GET_OWNER : ScHname = ScHname(0x137107a6); diff --git a/contracts/wasm/dividend/src/contract.rs b/contracts/wasm/dividend/src/contract.rs index fdc997da3d..794ea5c465 100644 --- a/contracts/wasm/dividend/src/contract.rs +++ b/contracts/wasm/dividend/src/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -18,33 +16,33 @@ use crate::params::*; use crate::results::*; pub struct DivideCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct InitCall { - pub func: ScInitFunc, - pub params: MutableInitParams, + pub func: ScInitFunc, + pub params: MutableInitParams, } pub struct MemberCall { - pub func: ScFunc, - pub params: MutableMemberParams, + pub func: ScFunc, + pub params: MutableMemberParams, } pub struct SetOwnerCall { - pub func: ScFunc, - pub params: MutableSetOwnerParams, + pub func: ScFunc, + pub params: MutableSetOwnerParams, } pub struct GetFactorCall { - pub func: ScView, - pub params: MutableGetFactorParams, - pub results: ImmutableGetFactorResults, + pub func: ScView, + pub params: MutableGetFactorParams, + pub results: ImmutableGetFactorResults, } pub struct GetOwnerCall { - pub func: ScView, - pub results: ImmutableGetOwnerResults, + pub func: ScView, + pub results: ImmutableGetOwnerResults, } pub struct ScFuncs { @@ -56,47 +54,50 @@ impl ScFuncs { func: ScFunc::new(HSC_NAME, HFUNC_DIVIDE), } } + pub fn init(_ctx: & dyn ScFuncCallContext) -> InitCall { let mut f = InitCall { - func: ScInitFunc::new(HSC_NAME, HFUNC_INIT), + func: ScInitFunc::new(HSC_NAME, HFUNC_INIT), params: MutableInitParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn member(_ctx: & dyn ScFuncCallContext) -> MemberCall { let mut f = MemberCall { - func: ScFunc::new(HSC_NAME, HFUNC_MEMBER), + func: ScFunc::new(HSC_NAME, HFUNC_MEMBER), params: MutableMemberParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn set_owner(_ctx: & dyn ScFuncCallContext) -> SetOwnerCall { let mut f = SetOwnerCall { - func: ScFunc::new(HSC_NAME, HFUNC_SET_OWNER), + func: ScFunc::new(HSC_NAME, HFUNC_SET_OWNER), params: MutableSetOwnerParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn get_factor(_ctx: & dyn ScViewCallContext) -> GetFactorCall { let mut f = GetFactorCall { - func: ScView::new(HSC_NAME, HVIEW_GET_FACTOR), - params: MutableGetFactorParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_FACTOR), + params: MutableGetFactorParams { id: 0 }, results: ImmutableGetFactorResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_owner(_ctx: & dyn ScViewCallContext) -> GetOwnerCall { let mut f = GetOwnerCall { - func: ScView::new(HSC_NAME, HVIEW_GET_OWNER), + func: ScView::new(HSC_NAME, HVIEW_GET_OWNER), results: ImmutableGetOwnerResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/contracts/wasm/dividend/src/keys.rs b/contracts/wasm/dividend/src/keys.rs index 2f9c2814aa..f15d21bcd6 100644 --- a/contracts/wasm/dividend/src/keys.rs +++ b/contracts/wasm/dividend/src/keys.rs @@ -5,36 +5,36 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use crate::*; -pub(crate) const IDX_PARAM_ADDRESS: usize = 0; -pub(crate) const IDX_PARAM_FACTOR: usize = 1; -pub(crate) const IDX_PARAM_OWNER: usize = 2; -pub(crate) const IDX_RESULT_FACTOR: usize = 3; -pub(crate) const IDX_RESULT_OWNER: usize = 4; -pub(crate) const IDX_STATE_MEMBER_LIST: usize = 5; -pub(crate) const IDX_STATE_MEMBERS: usize = 6; -pub(crate) const IDX_STATE_OWNER: usize = 7; -pub(crate) const IDX_STATE_TOTAL_FACTOR: usize = 8; +pub(crate) const IDX_PARAM_ADDRESS : usize = 0; +pub(crate) const IDX_PARAM_FACTOR : usize = 1; +pub(crate) const IDX_PARAM_OWNER : usize = 2; + +pub(crate) const IDX_RESULT_FACTOR : usize = 3; +pub(crate) const IDX_RESULT_OWNER : usize = 4; + +pub(crate) const IDX_STATE_MEMBER_LIST : usize = 5; +pub(crate) const IDX_STATE_MEMBERS : usize = 6; +pub(crate) const IDX_STATE_OWNER : usize = 7; +pub(crate) const IDX_STATE_TOTAL_FACTOR : usize = 8; pub const KEY_MAP_LEN: usize = 9; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ - PARAM_ADDRESS, - PARAM_FACTOR, - PARAM_OWNER, - RESULT_FACTOR, - RESULT_OWNER, - STATE_MEMBER_LIST, - STATE_MEMBERS, - STATE_OWNER, - STATE_TOTAL_FACTOR, + PARAM_ADDRESS, + PARAM_FACTOR, + PARAM_OWNER, + RESULT_FACTOR, + RESULT_OWNER, + STATE_MEMBER_LIST, + STATE_MEMBERS, + STATE_OWNER, + STATE_TOTAL_FACTOR, ]; pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; @@ -44,5 +44,3 @@ pub fn idx_map(idx: usize) -> Key32 { IDX_MAP[idx] } } - -// @formatter:on diff --git a/contracts/wasm/dividend/src/lib.rs b/contracts/wasm/dividend/src/lib.rs index ef70c94781..58f053d384 100644 --- a/contracts/wasm/dividend/src/lib.rs +++ b/contracts/wasm/dividend/src/lib.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] #![allow(unused_imports)] @@ -31,12 +29,12 @@ mod dividend; #[no_mangle] fn on_load() { let exports = ScExports::new(); - exports.add_func(FUNC_DIVIDE, func_divide_thunk); - exports.add_func(FUNC_INIT, func_init_thunk); - exports.add_func(FUNC_MEMBER, func_member_thunk); - exports.add_func(FUNC_SET_OWNER, func_set_owner_thunk); + exports.add_func(FUNC_DIVIDE, func_divide_thunk); + exports.add_func(FUNC_INIT, func_init_thunk); + exports.add_func(FUNC_MEMBER, func_member_thunk); + exports.add_func(FUNC_SET_OWNER, func_set_owner_thunk); exports.add_view(VIEW_GET_FACTOR, view_get_factor_thunk); - exports.add_view(VIEW_GET_OWNER, view_get_owner_thunk); + exports.add_view(VIEW_GET_OWNER, view_get_owner_thunk); unsafe { for i in 0..KEY_MAP_LEN { @@ -46,131 +44,131 @@ fn on_load() { } pub struct DivideContext { - state: MutableDividendState, + state: MutableDividendState, } fn func_divide_thunk(ctx: &ScFuncContext) { - ctx.log("dividend.funcDivide"); - let f = DivideContext { - state: MutableDividendState { - id: OBJ_ID_STATE, - }, - }; - func_divide(ctx, &f); - ctx.log("dividend.funcDivide ok"); + ctx.log("dividend.funcDivide"); + let f = DivideContext { + state: MutableDividendState { + id: OBJ_ID_STATE, + }, + }; + func_divide(ctx, &f); + ctx.log("dividend.funcDivide ok"); } pub struct InitContext { - params: ImmutableInitParams, - state: MutableDividendState, + params: ImmutableInitParams, + state: MutableDividendState, } fn func_init_thunk(ctx: &ScFuncContext) { - ctx.log("dividend.funcInit"); - let f = InitContext { - params: ImmutableInitParams { - id: OBJ_ID_PARAMS, - }, - state: MutableDividendState { - id: OBJ_ID_STATE, - }, - }; - func_init(ctx, &f); - ctx.log("dividend.funcInit ok"); + ctx.log("dividend.funcInit"); + let f = InitContext { + params: ImmutableInitParams { + id: OBJ_ID_PARAMS, + }, + state: MutableDividendState { + id: OBJ_ID_STATE, + }, + }; + func_init(ctx, &f); + ctx.log("dividend.funcInit ok"); } pub struct MemberContext { - params: ImmutableMemberParams, - state: MutableDividendState, + params: ImmutableMemberParams, + state: MutableDividendState, } fn func_member_thunk(ctx: &ScFuncContext) { - ctx.log("dividend.funcMember"); - // only defined owner of contract can add members - let access = ctx.state().get_agent_id("owner"); - ctx.require(access.exists(), "access not set: owner"); - ctx.require(ctx.caller() == access.value(), "no permission"); - - let f = MemberContext { - params: ImmutableMemberParams { - id: OBJ_ID_PARAMS, - }, - state: MutableDividendState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.address().exists(), "missing mandatory address"); - ctx.require(f.params.factor().exists(), "missing mandatory factor"); - func_member(ctx, &f); - ctx.log("dividend.funcMember ok"); + ctx.log("dividend.funcMember"); + + // only defined owner of contract can add members + let access = ctx.state().get_agent_id("owner"); + ctx.require(access.exists(), "access not set: owner"); + ctx.require(ctx.caller() == access.value(), "no permission"); + + let f = MemberContext { + params: ImmutableMemberParams { + id: OBJ_ID_PARAMS, + }, + state: MutableDividendState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.address().exists(), "missing mandatory address"); + ctx.require(f.params.factor().exists(), "missing mandatory factor"); + func_member(ctx, &f); + ctx.log("dividend.funcMember ok"); } pub struct SetOwnerContext { - params: ImmutableSetOwnerParams, - state: MutableDividendState, + params: ImmutableSetOwnerParams, + state: MutableDividendState, } fn func_set_owner_thunk(ctx: &ScFuncContext) { - ctx.log("dividend.funcSetOwner"); - // only defined owner of contract can change owner - let access = ctx.state().get_agent_id("owner"); - ctx.require(access.exists(), "access not set: owner"); - ctx.require(ctx.caller() == access.value(), "no permission"); - - let f = SetOwnerContext { - params: ImmutableSetOwnerParams { - id: OBJ_ID_PARAMS, - }, - state: MutableDividendState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.owner().exists(), "missing mandatory owner"); - func_set_owner(ctx, &f); - ctx.log("dividend.funcSetOwner ok"); + ctx.log("dividend.funcSetOwner"); + + // only defined owner of contract can change owner + let access = ctx.state().get_agent_id("owner"); + ctx.require(access.exists(), "access not set: owner"); + ctx.require(ctx.caller() == access.value(), "no permission"); + + let f = SetOwnerContext { + params: ImmutableSetOwnerParams { + id: OBJ_ID_PARAMS, + }, + state: MutableDividendState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.owner().exists(), "missing mandatory owner"); + func_set_owner(ctx, &f); + ctx.log("dividend.funcSetOwner ok"); } pub struct GetFactorContext { - params: ImmutableGetFactorParams, - results: MutableGetFactorResults, - state: ImmutableDividendState, + params: ImmutableGetFactorParams, + results: MutableGetFactorResults, + state: ImmutableDividendState, } fn view_get_factor_thunk(ctx: &ScViewContext) { - ctx.log("dividend.viewGetFactor"); - let f = GetFactorContext { - params: ImmutableGetFactorParams { - id: OBJ_ID_PARAMS, - }, - results: MutableGetFactorResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableDividendState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.address().exists(), "missing mandatory address"); - view_get_factor(ctx, &f); - ctx.log("dividend.viewGetFactor ok"); + ctx.log("dividend.viewGetFactor"); + let f = GetFactorContext { + params: ImmutableGetFactorParams { + id: OBJ_ID_PARAMS, + }, + results: MutableGetFactorResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableDividendState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.address().exists(), "missing mandatory address"); + view_get_factor(ctx, &f); + ctx.log("dividend.viewGetFactor ok"); } pub struct GetOwnerContext { - results: MutableGetOwnerResults, - state: ImmutableDividendState, + results: MutableGetOwnerResults, + state: ImmutableDividendState, } fn view_get_owner_thunk(ctx: &ScViewContext) { - ctx.log("dividend.viewGetOwner"); - let f = GetOwnerContext { - results: MutableGetOwnerResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableDividendState { - id: OBJ_ID_STATE, - }, - }; - view_get_owner(ctx, &f); - ctx.log("dividend.viewGetOwner ok"); + ctx.log("dividend.viewGetOwner"); + let f = GetOwnerContext { + results: MutableGetOwnerResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableDividendState { + id: OBJ_ID_STATE, + }, + }; + view_get_owner(ctx, &f); + ctx.log("dividend.viewGetOwner ok"); } - -// @formatter:on diff --git a/contracts/wasm/dividend/src/params.rs b/contracts/wasm/dividend/src/params.rs index 1de499db04..a8ddbef09f 100644 --- a/contracts/wasm/dividend/src/params.rs +++ b/contracts/wasm/dividend/src/params.rs @@ -21,8 +21,8 @@ pub struct ImmutableInitParams { impl ImmutableInitParams { pub fn owner(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + } } #[derive(Clone, Copy)] @@ -32,8 +32,8 @@ pub struct MutableInitParams { impl MutableInitParams { pub fn owner(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + } } #[derive(Clone, Copy)] @@ -43,12 +43,12 @@ pub struct ImmutableMemberParams { impl ImmutableMemberParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) - } + ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + } pub fn factor(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_FACTOR)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_FACTOR)) + } } #[derive(Clone, Copy)] @@ -58,12 +58,12 @@ pub struct MutableMemberParams { impl MutableMemberParams { pub fn address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) - } + ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + } pub fn factor(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_FACTOR)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_FACTOR)) + } } #[derive(Clone, Copy)] @@ -73,8 +73,8 @@ pub struct ImmutableSetOwnerParams { impl ImmutableSetOwnerParams { pub fn owner(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + } } #[derive(Clone, Copy)] @@ -84,8 +84,8 @@ pub struct MutableSetOwnerParams { impl MutableSetOwnerParams { pub fn owner(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + } } #[derive(Clone, Copy)] @@ -95,8 +95,8 @@ pub struct ImmutableGetFactorParams { impl ImmutableGetFactorParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) - } + ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + } } #[derive(Clone, Copy)] @@ -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, idx_map(IDX_PARAM_ADDRESS)) + } } diff --git a/contracts/wasm/dividend/src/results.rs b/contracts/wasm/dividend/src/results.rs index 69e7db1ff7..373e293a53 100644 --- a/contracts/wasm/dividend/src/results.rs +++ b/contracts/wasm/dividend/src/results.rs @@ -21,8 +21,8 @@ pub struct ImmutableGetFactorResults { impl ImmutableGetFactorResults { pub fn factor(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_FACTOR)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_FACTOR)) + } } #[derive(Clone, Copy)] @@ -32,8 +32,8 @@ pub struct MutableGetFactorResults { impl MutableGetFactorResults { pub fn factor(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_FACTOR)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_FACTOR)) + } } #[derive(Clone, Copy)] @@ -43,8 +43,8 @@ pub struct ImmutableGetOwnerResults { impl ImmutableGetOwnerResults { pub fn owner(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_OWNER)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_OWNER)) + } } #[derive(Clone, Copy)] @@ -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, idx_map(IDX_RESULT_OWNER)) + } } diff --git a/contracts/wasm/dividend/src/state.rs b/contracts/wasm/dividend/src/state.rs index b2334301a0..1181e0fd48 100644 --- a/contracts/wasm/dividend/src/state.rs +++ b/contracts/wasm/dividend/src/state.rs @@ -15,7 +15,7 @@ use crate::*; use crate::keys::*; pub struct ArrayOfImmutableAddress { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfImmutableAddress { @@ -29,7 +29,7 @@ impl ArrayOfImmutableAddress { } pub struct MapAddressToImmutableInt64 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapAddressToImmutableInt64 { @@ -45,26 +45,26 @@ 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); - ArrayOfImmutableAddress { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, idx_map(IDX_STATE_MEMBER_LIST), 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); - MapAddressToImmutableInt64 { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_MEMBERS), 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, idx_map(IDX_STATE_OWNER)) + } pub fn total_factor(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_FACTOR)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_FACTOR)) + } } pub struct ArrayOfMutableAddress { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfMutableAddress { @@ -82,12 +82,12 @@ impl ArrayOfMutableAddress { } pub struct MapAddressToMutableInt64 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapAddressToMutableInt64 { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_int64(&self, key: &ScAddress) -> ScMutableInt64 { @@ -102,20 +102,20 @@ pub struct MutableDividendState { impl MutableDividendState { pub fn member_list(&self) -> ArrayOfMutableAddress { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_MEMBER_LIST), TYPE_ARRAY | TYPE_ADDRESS); - ArrayOfMutableAddress { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, idx_map(IDX_STATE_MEMBER_LIST), 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); - MapAddressToMutableInt64 { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_MEMBERS), 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, idx_map(IDX_STATE_OWNER)) + } pub fn total_factor(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_FACTOR)) - } + ScMutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_FACTOR)) + } } diff --git a/contracts/wasm/dividend/test/dividend_bg.wasm b/contracts/wasm/dividend/test/dividend_bg.wasm index 5680a3756c..b80b9d3f38 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/test/dividend_test.go b/contracts/wasm/dividend/test/dividend_test.go index 3432ccc528..919a41df64 100644 --- a/contracts/wasm/dividend/test/dividend_test.go +++ b/contracts/wasm/dividend/test/dividend_test.go @@ -25,9 +25,9 @@ func dividendDivide(ctx *wasmsolo.SoloContext, amount int64) { divide.Func.TransferIotas(amount).Post() } -func dividendGetFactor(ctx *wasmsolo.SoloContext, member3 *wasmsolo.SoloAgent) int64 { +func dividendGetFactor(ctx *wasmsolo.SoloContext, member *wasmsolo.SoloAgent) int64 { getFactor := dividend.ScFuncs.GetFactor(ctx) - getFactor.Params.Address().SetValue(member3.ScAddress()) + getFactor.Params.Address().SetValue(member.ScAddress()) getFactor.Func.Call() value := getFactor.Results.Factor().Value() return value diff --git a/contracts/wasm/dividend/ts/dividend/consts.ts b/contracts/wasm/dividend/ts/dividend/consts.ts index 3972e9b7ca..4368c1405e 100644 --- a/contracts/wasm/dividend/ts/dividend/consts.ts +++ b/contracts/wasm/dividend/ts/dividend/consts.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export const ScName = "dividend"; export const ScDescription = "Simple dividend smart contract"; diff --git a/contracts/wasm/dividend/ts/dividend/contract.ts b/contracts/wasm/dividend/ts/dividend/contract.ts index e53fae2a2c..929d85e4ac 100644 --- a/contracts/wasm/dividend/ts/dividend/contract.ts +++ b/contracts/wasm/dividend/ts/dividend/contract.ts @@ -5,74 +5,72 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class DivideCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDivide); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDivide); } export class DivideContext { - state: sc.MutableDividendState = new sc.MutableDividendState(); + state: sc.MutableDividendState = new sc.MutableDividendState(); } export class InitCall { - func: wasmlib.ScInitFunc = new wasmlib.ScInitFunc(sc.HScName, sc.HFuncInit); - params: sc.MutableInitParams = new sc.MutableInitParams(); + func: wasmlib.ScInitFunc = new wasmlib.ScInitFunc(sc.HScName, sc.HFuncInit); + params: sc.MutableInitParams = new sc.MutableInitParams(); } export class InitContext { - params: sc.ImmutableInitParams = new sc.ImmutableInitParams(); - state: sc.MutableDividendState = new sc.MutableDividendState(); + params: sc.ImmutableInitParams = new sc.ImmutableInitParams(); + state: sc.MutableDividendState = new sc.MutableDividendState(); } export class MemberCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncMember); - params: sc.MutableMemberParams = new sc.MutableMemberParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncMember); + params: sc.MutableMemberParams = new sc.MutableMemberParams(); } export class MemberContext { - params: sc.ImmutableMemberParams = new sc.ImmutableMemberParams(); - state: sc.MutableDividendState = new sc.MutableDividendState(); + params: sc.ImmutableMemberParams = new sc.ImmutableMemberParams(); + state: sc.MutableDividendState = new sc.MutableDividendState(); } export class SetOwnerCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetOwner); - params: sc.MutableSetOwnerParams = new sc.MutableSetOwnerParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetOwner); + params: sc.MutableSetOwnerParams = new sc.MutableSetOwnerParams(); } export class SetOwnerContext { - params: sc.ImmutableSetOwnerParams = new sc.ImmutableSetOwnerParams(); - state: sc.MutableDividendState = new sc.MutableDividendState(); + params: sc.ImmutableSetOwnerParams = new sc.ImmutableSetOwnerParams(); + state: sc.MutableDividendState = new sc.MutableDividendState(); } export class GetFactorCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetFactor); - params: sc.MutableGetFactorParams = new sc.MutableGetFactorParams(); - results: sc.ImmutableGetFactorResults = new sc.ImmutableGetFactorResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetFactor); + params: sc.MutableGetFactorParams = new sc.MutableGetFactorParams(); + results: sc.ImmutableGetFactorResults = new sc.ImmutableGetFactorResults(); } export class GetFactorContext { - params: sc.ImmutableGetFactorParams = new sc.ImmutableGetFactorParams(); - results: sc.MutableGetFactorResults = new sc.MutableGetFactorResults(); - state: sc.ImmutableDividendState = new sc.ImmutableDividendState(); + params: sc.ImmutableGetFactorParams = new sc.ImmutableGetFactorParams(); + results: sc.MutableGetFactorResults = new sc.MutableGetFactorResults(); + state: sc.ImmutableDividendState = new sc.ImmutableDividendState(); } export class GetOwnerCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetOwner); - results: sc.ImmutableGetOwnerResults = new sc.ImmutableGetOwnerResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetOwner); + results: sc.ImmutableGetOwnerResults = new sc.ImmutableGetOwnerResults(); } export class GetOwnerContext { - results: sc.MutableGetOwnerResults = new sc.MutableGetOwnerResults(); - state: sc.ImmutableDividendState = new sc.ImmutableDividendState(); + results: sc.MutableGetOwnerResults = new sc.MutableGetOwnerResults(); + state: sc.ImmutableDividendState = new sc.ImmutableDividendState(); } export class ScFuncs { - static divide(ctx: wasmlib.ScFuncCallContext): DivideCall { - let f = new DivideCall(); - return f; + return new DivideCall(); } static init(ctx: wasmlib.ScFuncCallContext): InitCall { diff --git a/contracts/wasm/dividend/ts/dividend/keys.ts b/contracts/wasm/dividend/ts/dividend/keys.ts index d63c0823de..8f3a026043 100644 --- a/contracts/wasm/dividend/ts/dividend/keys.ts +++ b/contracts/wasm/dividend/ts/dividend/keys.ts @@ -5,29 +5,31 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; -export const IdxParamAddress = 0; -export const IdxParamFactor = 1; -export const IdxParamOwner = 2; -export const IdxResultFactor = 3; -export const IdxResultOwner = 4; +export const IdxParamAddress = 0; +export const IdxParamFactor = 1; +export const IdxParamOwner = 2; + +export const IdxResultFactor = 3; +export const IdxResultOwner = 4; + export const IdxStateMemberList = 5; export const IdxStateMembers = 6; export const IdxStateOwner = 7; export const IdxStateTotalFactor = 8; export let keyMap: string[] = [ - sc.ParamAddress, - sc.ParamFactor, - sc.ParamOwner, - sc.ResultFactor, - sc.ResultOwner, - sc.StateMemberList, - sc.StateMembers, - sc.StateOwner, - sc.StateTotalFactor, + sc.ParamAddress, + sc.ParamFactor, + sc.ParamOwner, + sc.ResultFactor, + sc.ResultOwner, + sc.StateMemberList, + sc.StateMembers, + sc.StateOwner, + sc.StateTotalFactor, ]; export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/dividend/ts/dividend/lib.ts b/contracts/wasm/dividend/ts/dividend/lib.ts index a34a6d8586..6d2710649e 100644 --- a/contracts/wasm/dividend/ts/dividend/lib.ts +++ b/contracts/wasm/dividend/ts/dividend/lib.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export function on_call(index: i32): void { @@ -14,12 +14,12 @@ export function on_call(index: i32): void { export function on_load(): void { let exports = new wasmlib.ScExports(); - exports.addFunc(sc.FuncDivide, funcDivideThunk); - exports.addFunc(sc.FuncInit, funcInitThunk); - exports.addFunc(sc.FuncMember, funcMemberThunk); - exports.addFunc(sc.FuncSetOwner, funcSetOwnerThunk); + exports.addFunc(sc.FuncDivide, funcDivideThunk); + exports.addFunc(sc.FuncInit, funcInitThunk); + exports.addFunc(sc.FuncMember, funcMemberThunk); + exports.addFunc(sc.FuncSetOwner, funcSetOwnerThunk); exports.addView(sc.ViewGetFactor, viewGetFactorThunk); - exports.addView(sc.ViewGetOwner, viewGetOwnerThunk); + exports.addView(sc.ViewGetOwner, viewGetOwnerThunk); for (let i = 0; i < sc.keyMap.length; i++) { sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); @@ -27,69 +27,71 @@ export function on_load(): void { } function funcDivideThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("dividend.funcDivide"); - let f = new sc.DivideContext(); + ctx.log("dividend.funcDivide"); + let f = new sc.DivideContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcDivide(ctx, f); - ctx.log("dividend.funcDivide ok"); + sc.funcDivide(ctx, f); + ctx.log("dividend.funcDivide ok"); } function funcInitThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("dividend.funcInit"); - let f = new sc.InitContext(); + ctx.log("dividend.funcInit"); + let f = new sc.InitContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcInit(ctx, f); - ctx.log("dividend.funcInit ok"); + sc.funcInit(ctx, f); + ctx.log("dividend.funcInit ok"); } function funcMemberThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("dividend.funcMember"); - // only defined owner of contract can add members - let access = ctx.state().getAgentID(wasmlib.Key32.fromString("owner")); - ctx.require(access.exists(), "access not set: owner"); - ctx.require(ctx.caller().equals(access.value()), "no permission"); + ctx.log("dividend.funcMember"); - let f = new sc.MemberContext(); + // only defined owner of contract can add members + let access = ctx.state().getAgentID(wasmlib.Key32.fromString("owner")); + ctx.require(access.exists(), "access not set: owner"); + ctx.require(ctx.caller().equals(access.value()), "no permission"); + + let f = new sc.MemberContext(); 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.factor().exists(), "missing mandatory factor") - sc.funcMember(ctx, f); - ctx.log("dividend.funcMember ok"); + ctx.require(f.params.address().exists(), "missing mandatory address"); + ctx.require(f.params.factor().exists(), "missing mandatory factor"); + sc.funcMember(ctx, f); + ctx.log("dividend.funcMember ok"); } function funcSetOwnerThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("dividend.funcSetOwner"); - // only defined owner of contract can change owner - let access = ctx.state().getAgentID(wasmlib.Key32.fromString("owner")); - ctx.require(access.exists(), "access not set: owner"); - ctx.require(ctx.caller().equals(access.value()), "no permission"); + ctx.log("dividend.funcSetOwner"); + + // only defined owner of contract can change owner + let access = ctx.state().getAgentID(wasmlib.Key32.fromString("owner")); + ctx.require(access.exists(), "access not set: owner"); + ctx.require(ctx.caller().equals(access.value()), "no permission"); - let f = new sc.SetOwnerContext(); + let f = new sc.SetOwnerContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.owner().exists(), "missing mandatory owner") - sc.funcSetOwner(ctx, f); - ctx.log("dividend.funcSetOwner ok"); + ctx.require(f.params.owner().exists(), "missing mandatory owner"); + sc.funcSetOwner(ctx, f); + ctx.log("dividend.funcSetOwner ok"); } function viewGetFactorThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("dividend.viewGetFactor"); - let f = new sc.GetFactorContext(); + ctx.log("dividend.viewGetFactor"); + let f = new sc.GetFactorContext(); 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.address().exists(), "missing mandatory address") - sc.viewGetFactor(ctx, f); - ctx.log("dividend.viewGetFactor ok"); + ctx.require(f.params.address().exists(), "missing mandatory address"); + sc.viewGetFactor(ctx, f); + ctx.log("dividend.viewGetFactor ok"); } function viewGetOwnerThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("dividend.viewGetOwner"); - let f = new sc.GetOwnerContext(); + ctx.log("dividend.viewGetOwner"); + let f = new sc.GetOwnerContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewGetOwner(ctx, f); - ctx.log("dividend.viewGetOwner ok"); + sc.viewGetOwner(ctx, f); + ctx.log("dividend.viewGetOwner ok"); } diff --git a/contracts/wasm/dividend/ts/dividend/params.ts b/contracts/wasm/dividend/ts/dividend/params.ts index e02167e7a0..9182269073 100644 --- a/contracts/wasm/dividend/ts/dividend/params.ts +++ b/contracts/wasm/dividend/ts/dividend/params.ts @@ -5,69 +5,61 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ImmutableInitParams extends wasmlib.ScMapID { - owner(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + } } export class MutableInitParams extends wasmlib.ScMapID { - owner(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + } } 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, sc.idxMap[sc.IdxParamAddress]); + } factor(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamFactor]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamFactor]); + } } 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, sc.idxMap[sc.IdxParamAddress]); + } factor(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamFactor]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamFactor]); + } } 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, sc.idxMap[sc.IdxParamOwner]); + } } 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, sc.idxMap[sc.IdxParamOwner]); + } } 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, sc.idxMap[sc.IdxParamAddress]); + } } 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, sc.idxMap[sc.IdxParamAddress]); + } } diff --git a/contracts/wasm/dividend/ts/dividend/results.ts b/contracts/wasm/dividend/ts/dividend/results.ts index 0a0ac5af3d..3bac84f77e 100644 --- a/contracts/wasm/dividend/ts/dividend/results.ts +++ b/contracts/wasm/dividend/ts/dividend/results.ts @@ -5,33 +5,29 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxResultFactor]); + } } 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, sc.idxMap[sc.IdxResultFactor]); + } } 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, sc.idxMap[sc.IdxResultOwner]); + } } 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, sc.idxMap[sc.IdxResultOwner]); + } } diff --git a/contracts/wasm/dividend/ts/dividend/state.ts b/contracts/wasm/dividend/ts/dividend/state.ts index 60be5bad30..b7a24f7015 100644 --- a/contracts/wasm/dividend/ts/dividend/state.ts +++ b/contracts/wasm/dividend/ts/dividend/state.ts @@ -5,11 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ArrayOfImmutableAddress { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -25,7 +25,7 @@ export class ArrayOfImmutableAddress { } export class MapAddressToImmutableInt64 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -37,28 +37,27 @@ 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); - return new sc.ArrayOfImmutableAddress(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateMemberList], 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); - return new sc.MapAddressToImmutableInt64(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateMembers], 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, sc.idxMap[sc.IdxStateOwner]); + } totalFactor(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalFactor]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalFactor]); + } } export class ArrayOfMutableAddress { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -78,14 +77,14 @@ export class ArrayOfMutableAddress { } export class MapAddressToMutableInt64 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getInt64(key: wasmlib.ScAddress): wasmlib.ScMutableInt64 { @@ -94,22 +93,21 @@ export class MapAddressToMutableInt64 { } export class MutableDividendState extends wasmlib.ScMapID { - memberList(): sc.ArrayOfMutableAddress { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateMemberList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_ADDRESS); - return new sc.ArrayOfMutableAddress(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateMemberList], 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); - return new sc.MapAddressToMutableInt64(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateMembers], 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, sc.idxMap[sc.IdxStateOwner]); + } totalFactor(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalFactor]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalFactor]); + } } diff --git a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/consts.go b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/consts.go index e15c8bd7a1..d6c691a71e 100644 --- a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/consts.go +++ b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/consts.go @@ -10,31 +10,32 @@ package donatewithfeedback import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" const ( - ScName = "donatewithfeedback" - HScName = wasmlib.ScHname(0x696d7f66) + ScName = "donatewithfeedback" + ScDescription = "" + HScName = wasmlib.ScHname(0x696d7f66) ) const ( - ParamAmount = wasmlib.Key("amount") - ParamFeedback = wasmlib.Key("feedback") - ParamNr = wasmlib.Key("nr") + ParamAmount = "amount" + ParamFeedback = "feedback" + ParamNr = "nr" ) const ( - ResultAmount = wasmlib.Key("amount") - ResultCount = wasmlib.Key("count") - ResultDonator = wasmlib.Key("donator") - ResultError = wasmlib.Key("error") - ResultFeedback = wasmlib.Key("feedback") - ResultMaxDonation = wasmlib.Key("maxDonation") - ResultTimestamp = wasmlib.Key("timestamp") - ResultTotalDonation = wasmlib.Key("totalDonation") + ResultAmount = "amount" + ResultCount = "count" + ResultDonator = "donator" + ResultError = "error" + ResultFeedback = "feedback" + ResultMaxDonation = "maxDonation" + ResultTimestamp = "timestamp" + ResultTotalDonation = "totalDonation" ) const ( - StateLog = wasmlib.Key("log") - StateMaxDonation = wasmlib.Key("maxDonation") - StateTotalDonation = wasmlib.Key("totalDonation") + StateLog = "log" + StateMaxDonation = "maxDonation" + StateTotalDonation = "totalDonation" ) const ( diff --git a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/keys.go b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/keys.go index 3d99eb879e..a6939d46b7 100644 --- a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/keys.go +++ b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/keys.go @@ -10,9 +10,10 @@ package donatewithfeedback import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" const ( - IdxParamAmount = 0 - IdxParamFeedback = 1 - IdxParamNr = 2 + IdxParamAmount = 0 + IdxParamFeedback = 1 + IdxParamNr = 2 + IdxResultAmount = 3 IdxResultCount = 4 IdxResultDonator = 5 @@ -21,9 +22,10 @@ const ( IdxResultMaxDonation = 8 IdxResultTimestamp = 9 IdxResultTotalDonation = 10 - IdxStateLog = 11 - IdxStateMaxDonation = 12 - IdxStateTotalDonation = 13 + + IdxStateLog = 11 + IdxStateMaxDonation = 12 + IdxStateTotalDonation = 13 ) const keyMapLen = 14 diff --git a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/lib.go b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/lib.go index 1e9d2da3ce..e24d6693b9 100644 --- a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/lib.go +++ b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/lib.go @@ -47,6 +47,7 @@ type WithdrawContext struct { func funcWithdrawThunk(ctx wasmlib.ScFuncContext) { ctx.Log("donatewithfeedback.funcWithdraw") + // only SC creator can withdraw donated funds ctx.Require(ctx.Caller() == ctx.ContractCreator(), "no permission") diff --git a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/structs.go b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/structs.go index ba28b32d44..40d6b63f13 100644 --- a/contracts/wasm/donatewithfeedback/go/donatewithfeedback/structs.go +++ b/contracts/wasm/donatewithfeedback/go/donatewithfeedback/structs.go @@ -57,6 +57,10 @@ type MutableDonation struct { keyID wasmlib.Key32 } +func (o MutableDonation) Delete() { + wasmlib.DelKey(o.objID, o.keyID, wasmlib.TYPE_BYTES) +} + func (o MutableDonation) Exists() bool { return wasmlib.Exists(o.objID, o.keyID, wasmlib.TYPE_BYTES) } diff --git a/contracts/wasm/donatewithfeedback/src/consts.rs b/contracts/wasm/donatewithfeedback/src/consts.rs index 635b8117f7..1088c26437 100644 --- a/contracts/wasm/donatewithfeedback/src/consts.rs +++ b/contracts/wasm/donatewithfeedback/src/consts.rs @@ -5,40 +5,37 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; -pub const SC_NAME: &str = "donatewithfeedback"; -pub const HSC_NAME: ScHname = ScHname(0x696d7f66); - -pub const PARAM_AMOUNT: &str = "amount"; -pub const PARAM_FEEDBACK: &str = "feedback"; -pub const PARAM_NR: &str = "nr"; - -pub const RESULT_AMOUNT: &str = "amount"; -pub const RESULT_COUNT: &str = "count"; -pub const RESULT_DONATOR: &str = "donator"; -pub const RESULT_ERROR: &str = "error"; -pub const RESULT_FEEDBACK: &str = "feedback"; -pub const RESULT_MAX_DONATION: &str = "maxDonation"; -pub const RESULT_TIMESTAMP: &str = "timestamp"; -pub const RESULT_TOTAL_DONATION: &str = "totalDonation"; - -pub const STATE_LOG: &str = "log"; -pub const STATE_MAX_DONATION: &str = "maxDonation"; -pub const STATE_TOTAL_DONATION: &str = "totalDonation"; - -pub const FUNC_DONATE: &str = "donate"; -pub const FUNC_WITHDRAW: &str = "withdraw"; -pub const VIEW_DONATION: &str = "donation"; -pub const VIEW_DONATION_INFO: &str = "donationInfo"; - -pub const HFUNC_DONATE: ScHname = ScHname(0xdc9b133a); -pub const HFUNC_WITHDRAW: ScHname = ScHname(0x9dcc0f41); -pub const HVIEW_DONATION: ScHname = ScHname(0xbdb245ba); -pub const HVIEW_DONATION_INFO: ScHname = ScHname(0xc8f7c726); - -// @formatter:on +pub const SC_NAME : &str = "donatewithfeedback"; +pub const SC_DESCRIPTION : &str = ""; +pub const HSC_NAME : ScHname = ScHname(0x696d7f66); + +pub const PARAM_AMOUNT : &str = "amount"; +pub const PARAM_FEEDBACK : &str = "feedback"; +pub const PARAM_NR : &str = "nr"; + +pub const RESULT_AMOUNT : &str = "amount"; +pub const RESULT_COUNT : &str = "count"; +pub const RESULT_DONATOR : &str = "donator"; +pub const RESULT_ERROR : &str = "error"; +pub const RESULT_FEEDBACK : &str = "feedback"; +pub const RESULT_MAX_DONATION : &str = "maxDonation"; +pub const RESULT_TIMESTAMP : &str = "timestamp"; +pub const RESULT_TOTAL_DONATION : &str = "totalDonation"; + +pub const STATE_LOG : &str = "log"; +pub const STATE_MAX_DONATION : &str = "maxDonation"; +pub const STATE_TOTAL_DONATION : &str = "totalDonation"; + +pub const FUNC_DONATE : &str = "donate"; +pub const FUNC_WITHDRAW : &str = "withdraw"; +pub const VIEW_DONATION : &str = "donation"; +pub const VIEW_DONATION_INFO : &str = "donationInfo"; + +pub const HFUNC_DONATE : ScHname = ScHname(0xdc9b133a); +pub const HFUNC_WITHDRAW : ScHname = ScHname(0x9dcc0f41); +pub const HVIEW_DONATION : ScHname = ScHname(0xbdb245ba); +pub const HVIEW_DONATION_INFO : ScHname = ScHname(0xc8f7c726); diff --git a/contracts/wasm/donatewithfeedback/src/contract.rs b/contracts/wasm/donatewithfeedback/src/contract.rs index dac9b03941..d726d153ca 100644 --- a/contracts/wasm/donatewithfeedback/src/contract.rs +++ b/contracts/wasm/donatewithfeedback/src/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -18,24 +16,24 @@ use crate::params::*; use crate::results::*; pub struct DonateCall { - pub func: ScFunc, - pub params: MutableDonateParams, + pub func: ScFunc, + pub params: MutableDonateParams, } pub struct WithdrawCall { - pub func: ScFunc, - pub params: MutableWithdrawParams, + pub func: ScFunc, + pub params: MutableWithdrawParams, } pub struct DonationCall { - pub func: ScView, - pub params: MutableDonationParams, - pub results: ImmutableDonationResults, + pub func: ScView, + pub params: MutableDonationParams, + pub results: ImmutableDonationResults, } pub struct DonationInfoCall { - pub func: ScView, - pub results: ImmutableDonationInfoResults, + pub func: ScView, + pub results: ImmutableDonationInfoResults, } pub struct ScFuncs { @@ -44,37 +42,38 @@ pub struct ScFuncs { impl ScFuncs { pub fn donate(_ctx: & dyn ScFuncCallContext) -> DonateCall { let mut f = DonateCall { - func: ScFunc::new(HSC_NAME, HFUNC_DONATE), + func: ScFunc::new(HSC_NAME, HFUNC_DONATE), params: MutableDonateParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn withdraw(_ctx: & dyn ScFuncCallContext) -> WithdrawCall { let mut f = WithdrawCall { - func: ScFunc::new(HSC_NAME, HFUNC_WITHDRAW), + func: ScFunc::new(HSC_NAME, HFUNC_WITHDRAW), params: MutableWithdrawParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn donation(_ctx: & dyn ScViewCallContext) -> DonationCall { let mut f = DonationCall { - func: ScView::new(HSC_NAME, HVIEW_DONATION), - params: MutableDonationParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_DONATION), + params: MutableDonationParams { id: 0 }, results: ImmutableDonationResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn donation_info(_ctx: & dyn ScViewCallContext) -> DonationInfoCall { let mut f = DonationInfoCall { - func: ScView::new(HSC_NAME, HVIEW_DONATION_INFO), + func: ScView::new(HSC_NAME, HVIEW_DONATION_INFO), results: ImmutableDonationInfoResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/contracts/wasm/donatewithfeedback/src/keys.rs b/contracts/wasm/donatewithfeedback/src/keys.rs index 116236ae1f..15946701bc 100644 --- a/contracts/wasm/donatewithfeedback/src/keys.rs +++ b/contracts/wasm/donatewithfeedback/src/keys.rs @@ -5,46 +5,46 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use crate::*; -pub(crate) const IDX_PARAM_AMOUNT: usize = 0; -pub(crate) const IDX_PARAM_FEEDBACK: usize = 1; -pub(crate) const IDX_PARAM_NR: usize = 2; -pub(crate) const IDX_RESULT_AMOUNT: usize = 3; -pub(crate) const IDX_RESULT_COUNT: usize = 4; -pub(crate) const IDX_RESULT_DONATOR: usize = 5; -pub(crate) const IDX_RESULT_ERROR: usize = 6; -pub(crate) const IDX_RESULT_FEEDBACK: usize = 7; -pub(crate) const IDX_RESULT_MAX_DONATION: usize = 8; -pub(crate) const IDX_RESULT_TIMESTAMP: usize = 9; -pub(crate) const IDX_RESULT_TOTAL_DONATION: usize = 10; -pub(crate) const IDX_STATE_LOG: usize = 11; -pub(crate) const IDX_STATE_MAX_DONATION: usize = 12; -pub(crate) const IDX_STATE_TOTAL_DONATION: usize = 13; +pub(crate) const IDX_PARAM_AMOUNT : usize = 0; +pub(crate) const IDX_PARAM_FEEDBACK : usize = 1; +pub(crate) const IDX_PARAM_NR : usize = 2; + +pub(crate) const IDX_RESULT_AMOUNT : usize = 3; +pub(crate) const IDX_RESULT_COUNT : usize = 4; +pub(crate) const IDX_RESULT_DONATOR : usize = 5; +pub(crate) const IDX_RESULT_ERROR : usize = 6; +pub(crate) const IDX_RESULT_FEEDBACK : usize = 7; +pub(crate) const IDX_RESULT_MAX_DONATION : usize = 8; +pub(crate) const IDX_RESULT_TIMESTAMP : usize = 9; +pub(crate) const IDX_RESULT_TOTAL_DONATION : usize = 10; + +pub(crate) const IDX_STATE_LOG : usize = 11; +pub(crate) const IDX_STATE_MAX_DONATION : usize = 12; +pub(crate) const IDX_STATE_TOTAL_DONATION : usize = 13; pub const KEY_MAP_LEN: usize = 14; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ - PARAM_AMOUNT, - PARAM_FEEDBACK, - PARAM_NR, - RESULT_AMOUNT, - RESULT_COUNT, - RESULT_DONATOR, - RESULT_ERROR, - RESULT_FEEDBACK, - RESULT_MAX_DONATION, - RESULT_TIMESTAMP, - RESULT_TOTAL_DONATION, - STATE_LOG, - STATE_MAX_DONATION, - STATE_TOTAL_DONATION, + PARAM_AMOUNT, + PARAM_FEEDBACK, + PARAM_NR, + RESULT_AMOUNT, + RESULT_COUNT, + RESULT_DONATOR, + RESULT_ERROR, + RESULT_FEEDBACK, + RESULT_MAX_DONATION, + RESULT_TIMESTAMP, + RESULT_TOTAL_DONATION, + STATE_LOG, + STATE_MAX_DONATION, + STATE_TOTAL_DONATION, ]; pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; @@ -54,5 +54,3 @@ pub fn idx_map(idx: usize) -> Key32 { IDX_MAP[idx] } } - -// @formatter:on diff --git a/contracts/wasm/donatewithfeedback/src/lib.rs b/contracts/wasm/donatewithfeedback/src/lib.rs index bad98e5096..feb50f1542 100644 --- a/contracts/wasm/donatewithfeedback/src/lib.rs +++ b/contracts/wasm/donatewithfeedback/src/lib.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] #![allow(unused_imports)] @@ -32,9 +30,9 @@ mod donatewithfeedback; #[no_mangle] fn on_load() { let exports = ScExports::new(); - exports.add_func(FUNC_DONATE, func_donate_thunk); - exports.add_func(FUNC_WITHDRAW, func_withdraw_thunk); - exports.add_view(VIEW_DONATION, view_donation_thunk); + exports.add_func(FUNC_DONATE, func_donate_thunk); + exports.add_func(FUNC_WITHDRAW, func_withdraw_thunk); + exports.add_view(VIEW_DONATION, view_donation_thunk); exports.add_view(VIEW_DONATION_INFO, view_donation_info_thunk); unsafe { @@ -45,87 +43,86 @@ fn on_load() { } pub struct DonateContext { - params: ImmutableDonateParams, - state: MutableDonateWithFeedbackState, + params: ImmutableDonateParams, + state: MutableDonateWithFeedbackState, } fn func_donate_thunk(ctx: &ScFuncContext) { - ctx.log("donatewithfeedback.funcDonate"); - let f = DonateContext { - params: ImmutableDonateParams { - id: OBJ_ID_PARAMS, - }, - state: MutableDonateWithFeedbackState { - id: OBJ_ID_STATE, - }, - }; - func_donate(ctx, &f); - ctx.log("donatewithfeedback.funcDonate ok"); + ctx.log("donatewithfeedback.funcDonate"); + let f = DonateContext { + params: ImmutableDonateParams { + id: OBJ_ID_PARAMS, + }, + state: MutableDonateWithFeedbackState { + id: OBJ_ID_STATE, + }, + }; + func_donate(ctx, &f); + ctx.log("donatewithfeedback.funcDonate ok"); } pub struct WithdrawContext { - params: ImmutableWithdrawParams, - state: MutableDonateWithFeedbackState, + params: ImmutableWithdrawParams, + state: MutableDonateWithFeedbackState, } fn func_withdraw_thunk(ctx: &ScFuncContext) { - ctx.log("donatewithfeedback.funcWithdraw"); - // only SC creator can withdraw donated funds - ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); - - let f = WithdrawContext { - params: ImmutableWithdrawParams { - id: OBJ_ID_PARAMS, - }, - state: MutableDonateWithFeedbackState { - id: OBJ_ID_STATE, - }, - }; - func_withdraw(ctx, &f); - ctx.log("donatewithfeedback.funcWithdraw ok"); + ctx.log("donatewithfeedback.funcWithdraw"); + + // only SC creator can withdraw donated funds + ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); + + let f = WithdrawContext { + params: ImmutableWithdrawParams { + id: OBJ_ID_PARAMS, + }, + state: MutableDonateWithFeedbackState { + id: OBJ_ID_STATE, + }, + }; + func_withdraw(ctx, &f); + ctx.log("donatewithfeedback.funcWithdraw ok"); } pub struct DonationContext { - params: ImmutableDonationParams, - results: MutableDonationResults, - state: ImmutableDonateWithFeedbackState, + params: ImmutableDonationParams, + results: MutableDonationResults, + state: ImmutableDonateWithFeedbackState, } fn view_donation_thunk(ctx: &ScViewContext) { - ctx.log("donatewithfeedback.viewDonation"); - let f = DonationContext { - params: ImmutableDonationParams { - id: OBJ_ID_PARAMS, - }, - results: MutableDonationResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableDonateWithFeedbackState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.nr().exists(), "missing mandatory nr"); - view_donation(ctx, &f); - ctx.log("donatewithfeedback.viewDonation ok"); + ctx.log("donatewithfeedback.viewDonation"); + let f = DonationContext { + params: ImmutableDonationParams { + id: OBJ_ID_PARAMS, + }, + results: MutableDonationResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableDonateWithFeedbackState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.nr().exists(), "missing mandatory nr"); + view_donation(ctx, &f); + ctx.log("donatewithfeedback.viewDonation ok"); } pub struct DonationInfoContext { - results: MutableDonationInfoResults, - state: ImmutableDonateWithFeedbackState, + results: MutableDonationInfoResults, + state: ImmutableDonateWithFeedbackState, } fn view_donation_info_thunk(ctx: &ScViewContext) { - ctx.log("donatewithfeedback.viewDonationInfo"); - let f = DonationInfoContext { - results: MutableDonationInfoResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableDonateWithFeedbackState { - id: OBJ_ID_STATE, - }, - }; - view_donation_info(ctx, &f); - ctx.log("donatewithfeedback.viewDonationInfo ok"); + ctx.log("donatewithfeedback.viewDonationInfo"); + let f = DonationInfoContext { + results: MutableDonationInfoResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableDonateWithFeedbackState { + id: OBJ_ID_STATE, + }, + }; + view_donation_info(ctx, &f); + ctx.log("donatewithfeedback.viewDonationInfo ok"); } - -// @formatter:on diff --git a/contracts/wasm/donatewithfeedback/src/params.rs b/contracts/wasm/donatewithfeedback/src/params.rs index a9aab5e8ee..44fa12eb5b 100644 --- a/contracts/wasm/donatewithfeedback/src/params.rs +++ b/contracts/wasm/donatewithfeedback/src/params.rs @@ -13,6 +13,7 @@ use wasmlib::host::*; use crate::*; use crate::keys::*; +use crate::structs::*; #[derive(Clone, Copy)] pub struct ImmutableDonateParams { @@ -21,8 +22,8 @@ pub struct ImmutableDonateParams { impl ImmutableDonateParams { pub fn feedback(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_FEEDBACK)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_FEEDBACK)) + } } #[derive(Clone, Copy)] @@ -32,8 +33,8 @@ pub struct MutableDonateParams { impl MutableDonateParams { pub fn feedback(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_FEEDBACK)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_FEEDBACK)) + } } #[derive(Clone, Copy)] @@ -43,8 +44,8 @@ pub struct ImmutableWithdrawParams { impl ImmutableWithdrawParams { pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + } } #[derive(Clone, Copy)] @@ -54,8 +55,8 @@ pub struct MutableWithdrawParams { impl MutableWithdrawParams { pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + } } #[derive(Clone, Copy)] @@ -65,8 +66,8 @@ pub struct ImmutableDonationParams { impl ImmutableDonationParams { pub fn nr(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_NR)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_NR)) + } } #[derive(Clone, Copy)] @@ -76,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, idx_map(IDX_PARAM_NR)) + } } diff --git a/contracts/wasm/donatewithfeedback/src/results.rs b/contracts/wasm/donatewithfeedback/src/results.rs index 2f65fcdb4b..6d3b0ad322 100644 --- a/contracts/wasm/donatewithfeedback/src/results.rs +++ b/contracts/wasm/donatewithfeedback/src/results.rs @@ -22,24 +22,24 @@ pub struct ImmutableDonationResults { impl ImmutableDonationResults { pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + } pub fn donator(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_DONATOR)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_DONATOR)) + } pub fn error(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_ERROR)) - } + ScImmutableString::new(self.id, idx_map(IDX_RESULT_ERROR)) + } pub fn feedback(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_FEEDBACK)) - } + ScImmutableString::new(self.id, idx_map(IDX_RESULT_FEEDBACK)) + } pub fn timestamp(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_TIMESTAMP)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_TIMESTAMP)) + } } #[derive(Clone, Copy)] @@ -49,24 +49,24 @@ pub struct MutableDonationResults { impl MutableDonationResults { pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + } pub fn donator(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_DONATOR)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_DONATOR)) + } pub fn error(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_ERROR)) - } + ScMutableString::new(self.id, idx_map(IDX_RESULT_ERROR)) + } pub fn feedback(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_FEEDBACK)) - } + ScMutableString::new(self.id, idx_map(IDX_RESULT_FEEDBACK)) + } pub fn timestamp(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_TIMESTAMP)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_TIMESTAMP)) + } } #[derive(Clone, Copy)] @@ -76,16 +76,16 @@ pub struct ImmutableDonationInfoResults { impl ImmutableDonationInfoResults { pub fn count(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_COUNT)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_COUNT)) + } pub fn max_donation(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_MAX_DONATION)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_MAX_DONATION)) + } pub fn total_donation(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_TOTAL_DONATION)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_TOTAL_DONATION)) + } } #[derive(Clone, Copy)] @@ -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, idx_map(IDX_RESULT_COUNT)) + } pub fn max_donation(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_MAX_DONATION)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_MAX_DONATION)) + } pub fn total_donation(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_TOTAL_DONATION)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_TOTAL_DONATION)) + } } diff --git a/contracts/wasm/donatewithfeedback/src/state.rs b/contracts/wasm/donatewithfeedback/src/state.rs index f424d24c95..9fc1c32e0f 100644 --- a/contracts/wasm/donatewithfeedback/src/state.rs +++ b/contracts/wasm/donatewithfeedback/src/state.rs @@ -16,7 +16,7 @@ use crate::keys::*; use crate::structs::*; pub struct ArrayOfImmutableDonation { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfImmutableDonation { @@ -24,9 +24,9 @@ impl ArrayOfImmutableDonation { get_length(self.obj_id) } - pub fn get_donation(&self, index: i32) -> ImmutableDonation { - ImmutableDonation { obj_id: self.obj_id, key_id: Key32(index) } - } + pub fn get_donation(&self, index: i32) -> ImmutableDonation { + ImmutableDonation { obj_id: self.obj_id, key_id: Key32(index) } + } } #[derive(Clone, Copy)] @@ -36,21 +36,21 @@ 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); - ArrayOfImmutableDonation { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, idx_map(IDX_STATE_LOG), 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, idx_map(IDX_STATE_MAX_DONATION)) + } pub fn total_donation(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_DONATION)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_DONATION)) + } } pub struct ArrayOfMutableDonation { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfMutableDonation { @@ -62,9 +62,9 @@ impl ArrayOfMutableDonation { get_length(self.obj_id) } - pub fn get_donation(&self, index: i32) -> MutableDonation { - MutableDonation { obj_id: self.obj_id, key_id: Key32(index) } - } + pub fn get_donation(&self, index: i32) -> MutableDonation { + MutableDonation { obj_id: self.obj_id, key_id: Key32(index) } + } } #[derive(Clone, Copy)] @@ -74,15 +74,15 @@ pub struct MutableDonateWithFeedbackState { impl MutableDonateWithFeedbackState { pub fn log(&self) -> ArrayOfMutableDonation { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_LOG), TYPE_ARRAY | TYPE_BYTES); - ArrayOfMutableDonation { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, idx_map(IDX_STATE_LOG), 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, idx_map(IDX_STATE_MAX_DONATION)) + } pub fn total_donation(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_DONATION)) - } + ScMutableInt64::new(self.id, idx_map(IDX_STATE_TOTAL_DONATION)) + } } diff --git a/contracts/wasm/donatewithfeedback/src/structs.rs b/contracts/wasm/donatewithfeedback/src/structs.rs index b4944aad21..8a15175075 100644 --- a/contracts/wasm/donatewithfeedback/src/structs.rs +++ b/contracts/wasm/donatewithfeedback/src/structs.rs @@ -5,40 +5,39 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] +#![allow(unused_imports)] use wasmlib::*; use wasmlib::host::*; pub struct Donation { - pub amount: i64, // amount donated - pub donator: ScAgentID, // who donated - pub error: String, // error to be reported to donator if anything goes wrong - pub feedback: String, // the feedback for the person donated to - pub timestamp: i64, // when the donation took place + pub amount : i64, // amount donated + pub donator : ScAgentID, // who donated + pub error : String, // error to be reported to donator if anything goes wrong + pub feedback : String, // the feedback for the person donated to + pub timestamp : i64, // when the donation took place } impl Donation { pub fn from_bytes(bytes: &[u8]) -> Donation { let mut decode = BytesDecoder::new(bytes); Donation { - amount: decode.int64(), - donator: decode.agent_id(), - error: decode.string(), - feedback: decode.string(), - timestamp: decode.int64(), + amount : decode.int64(), + donator : decode.agent_id(), + error : decode.string(), + feedback : decode.string(), + timestamp : decode.int64(), } } pub fn to_bytes(&self) -> Vec { let mut encode = BytesEncoder::new(); - encode.int64(self.amount); - encode.agent_id(&self.donator); - encode.string(&self.error); - encode.string(&self.feedback); - encode.int64(self.timestamp); + encode.int64(self.amount); + encode.agent_id(&self.donator); + encode.string(&self.error); + encode.string(&self.feedback); + encode.int64(self.timestamp); return encode.data(); } } @@ -64,6 +63,10 @@ pub struct MutableDonation { } impl MutableDonation { + 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) } @@ -76,5 +79,3 @@ impl MutableDonation { Donation::from_bytes(&get_bytes(self.obj_id, self.key_id, TYPE_BYTES)) } } - -// @formatter:on diff --git a/contracts/wasm/donatewithfeedback/test/donatewithfeedback_bg.wasm b/contracts/wasm/donatewithfeedback/test/donatewithfeedback_bg.wasm index 909efc2899..7f50ea8a95 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/consts.ts b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/consts.ts index 0fd579aa81..c95c4a93f6 100644 --- a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/consts.ts +++ b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/consts.ts @@ -5,10 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; -export const ScName = "donatewithfeedback"; -export const HScName = new wasmlib.ScHname(0x696d7f66); +export const ScName = "donatewithfeedback"; +export const ScDescription = ""; +export const HScName = new wasmlib.ScHname(0x696d7f66); export const ParamAmount = "amount"; export const ParamFeedback = "feedback"; diff --git a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/contract.ts b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/contract.ts index 10b82740b5..c3d9d5a0eb 100644 --- a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/contract.ts +++ b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/contract.ts @@ -5,53 +5,52 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class DonateCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDonate); - params: sc.MutableDonateParams = new sc.MutableDonateParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDonate); + params: sc.MutableDonateParams = new sc.MutableDonateParams(); } export class DonateContext { - params: sc.ImmutableDonateParams = new sc.ImmutableDonateParams(); - state: sc.MutableDonateWithFeedbackState = new sc.MutableDonateWithFeedbackState(); + params: sc.ImmutableDonateParams = new sc.ImmutableDonateParams(); + state: sc.MutableDonateWithFeedbackState = new sc.MutableDonateWithFeedbackState(); } export class WithdrawCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncWithdraw); - params: sc.MutableWithdrawParams = new sc.MutableWithdrawParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncWithdraw); + params: sc.MutableWithdrawParams = new sc.MutableWithdrawParams(); } export class WithdrawContext { - params: sc.ImmutableWithdrawParams = new sc.ImmutableWithdrawParams(); - state: sc.MutableDonateWithFeedbackState = new sc.MutableDonateWithFeedbackState(); + params: sc.ImmutableWithdrawParams = new sc.ImmutableWithdrawParams(); + state: sc.MutableDonateWithFeedbackState = new sc.MutableDonateWithFeedbackState(); } export class DonationCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewDonation); - params: sc.MutableDonationParams = new sc.MutableDonationParams(); - results: sc.ImmutableDonationResults = new sc.ImmutableDonationResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewDonation); + params: sc.MutableDonationParams = new sc.MutableDonationParams(); + results: sc.ImmutableDonationResults = new sc.ImmutableDonationResults(); } export class DonationContext { - params: sc.ImmutableDonationParams = new sc.ImmutableDonationParams(); - results: sc.MutableDonationResults = new sc.MutableDonationResults(); - state: sc.ImmutableDonateWithFeedbackState = new sc.ImmutableDonateWithFeedbackState(); + params: sc.ImmutableDonationParams = new sc.ImmutableDonationParams(); + results: sc.MutableDonationResults = new sc.MutableDonationResults(); + state: sc.ImmutableDonateWithFeedbackState = new sc.ImmutableDonateWithFeedbackState(); } export class DonationInfoCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewDonationInfo); - results: sc.ImmutableDonationInfoResults = new sc.ImmutableDonationInfoResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewDonationInfo); + results: sc.ImmutableDonationInfoResults = new sc.ImmutableDonationInfoResults(); } export class DonationInfoContext { - results: sc.MutableDonationInfoResults = new sc.MutableDonationInfoResults(); - state: sc.ImmutableDonateWithFeedbackState = new sc.ImmutableDonateWithFeedbackState(); + results: sc.MutableDonationInfoResults = new sc.MutableDonationInfoResults(); + state: sc.ImmutableDonateWithFeedbackState = new sc.ImmutableDonateWithFeedbackState(); } export class ScFuncs { - static donate(ctx: wasmlib.ScFuncCallContext): DonateCall { let f = new DonateCall(); f.func.setPtrs(f.params, null); diff --git a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/keys.ts b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/keys.ts index 897c2d1de2..16ce9ceed1 100644 --- a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/keys.ts +++ b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/keys.ts @@ -5,12 +5,13 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; -export const IdxParamAmount = 0; -export const IdxParamFeedback = 1; -export const IdxParamNr = 2; +export const IdxParamAmount = 0; +export const IdxParamFeedback = 1; +export const IdxParamNr = 2; + export const IdxResultAmount = 3; export const IdxResultCount = 4; export const IdxResultDonator = 5; @@ -19,25 +20,26 @@ export const IdxResultFeedback = 7; export const IdxResultMaxDonation = 8; export const IdxResultTimestamp = 9; export const IdxResultTotalDonation = 10; -export const IdxStateLog = 11; -export const IdxStateMaxDonation = 12; -export const IdxStateTotalDonation = 13; + +export const IdxStateLog = 11; +export const IdxStateMaxDonation = 12; +export const IdxStateTotalDonation = 13; export let keyMap: string[] = [ - sc.ParamAmount, - sc.ParamFeedback, - sc.ParamNr, - sc.ResultAmount, - sc.ResultCount, - sc.ResultDonator, - sc.ResultError, - sc.ResultFeedback, - sc.ResultMaxDonation, - sc.ResultTimestamp, - sc.ResultTotalDonation, - sc.StateLog, - sc.StateMaxDonation, - sc.StateTotalDonation, + sc.ParamAmount, + sc.ParamFeedback, + sc.ParamNr, + sc.ResultAmount, + sc.ResultCount, + sc.ResultDonator, + sc.ResultError, + sc.ResultFeedback, + sc.ResultMaxDonation, + sc.ResultTimestamp, + sc.ResultTotalDonation, + sc.StateLog, + sc.StateMaxDonation, + sc.StateTotalDonation, ]; export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/lib.ts b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/lib.ts index 28dca4c343..ea6080bb30 100644 --- a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/lib.ts +++ b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/lib.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export function on_call(index: i32): void { @@ -14,9 +14,9 @@ export function on_call(index: i32): void { export function on_load(): void { let exports = new wasmlib.ScExports(); - exports.addFunc(sc.FuncDonate, funcDonateThunk); - exports.addFunc(sc.FuncWithdraw, funcWithdrawThunk); - exports.addView(sc.ViewDonation, viewDonationThunk); + exports.addFunc(sc.FuncDonate, funcDonateThunk); + exports.addFunc(sc.FuncWithdraw, funcWithdrawThunk); + exports.addView(sc.ViewDonation, viewDonationThunk); exports.addView(sc.ViewDonationInfo, viewDonationInfoThunk); for (let i = 0; i < sc.keyMap.length; i++) { @@ -25,42 +25,43 @@ export function on_load(): void { } function funcDonateThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("donatewithfeedback.funcDonate"); - let f = new sc.DonateContext(); + ctx.log("donatewithfeedback.funcDonate"); + let f = new sc.DonateContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcDonate(ctx, f); - ctx.log("donatewithfeedback.funcDonate ok"); + sc.funcDonate(ctx, f); + ctx.log("donatewithfeedback.funcDonate ok"); } function funcWithdrawThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("donatewithfeedback.funcWithdraw"); - // only SC creator can withdraw donated funds - ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + ctx.log("donatewithfeedback.funcWithdraw"); - let f = new sc.WithdrawContext(); + // only SC creator can withdraw donated funds + ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + + let f = new sc.WithdrawContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcWithdraw(ctx, f); - ctx.log("donatewithfeedback.funcWithdraw ok"); + sc.funcWithdraw(ctx, f); + ctx.log("donatewithfeedback.funcWithdraw ok"); } function viewDonationThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("donatewithfeedback.viewDonation"); - let f = new sc.DonationContext(); + ctx.log("donatewithfeedback.viewDonation"); + let f = new sc.DonationContext(); 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.nr().exists(), "missing mandatory nr") - sc.viewDonation(ctx, f); - ctx.log("donatewithfeedback.viewDonation ok"); + ctx.require(f.params.nr().exists(), "missing mandatory nr"); + sc.viewDonation(ctx, f); + ctx.log("donatewithfeedback.viewDonation ok"); } function viewDonationInfoThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("donatewithfeedback.viewDonationInfo"); - let f = new sc.DonationInfoContext(); + ctx.log("donatewithfeedback.viewDonationInfo"); + let f = new sc.DonationInfoContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewDonationInfo(ctx, f); - ctx.log("donatewithfeedback.viewDonationInfo ok"); + sc.viewDonationInfo(ctx, f); + ctx.log("donatewithfeedback.viewDonationInfo ok"); } diff --git a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/params.ts b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/params.ts index 355aa8dca4..81558202a8 100644 --- a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/params.ts +++ b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/params.ts @@ -5,47 +5,41 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxParamFeedback]); + } } 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, sc.idxMap[sc.IdxParamFeedback]); + } } 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, sc.idxMap[sc.IdxParamAmount]); + } } 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, sc.idxMap[sc.IdxParamAmount]); + } } 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, sc.idxMap[sc.IdxParamNr]); + } } 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, sc.idxMap[sc.IdxParamNr]); + } } diff --git a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/results.ts b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/results.ts index e85ff09046..2d9329bd9d 100644 --- a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/results.ts +++ b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/results.ts @@ -5,81 +5,77 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxResultAmount]); + } donator(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultDonator]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultDonator]); + } error(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultError]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultError]); + } feedback(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultFeedback]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultFeedback]); + } timestamp(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultTimestamp]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultTimestamp]); + } } 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, sc.idxMap[sc.IdxResultAmount]); + } donator(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultDonator]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultDonator]); + } error(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultError]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultError]); + } feedback(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultFeedback]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultFeedback]); + } timestamp(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultTimestamp]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultTimestamp]); + } } 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, sc.idxMap[sc.IdxResultCount]); + } maxDonation(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultMaxDonation]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultMaxDonation]); + } totalDonation(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultTotalDonation]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultTotalDonation]); + } } 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, sc.idxMap[sc.IdxResultCount]); + } maxDonation(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultMaxDonation]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultMaxDonation]); + } totalDonation(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultTotalDonation]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultTotalDonation]); + } } diff --git a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/state.ts b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/state.ts index aac74b4133..0a946bfcf1 100644 --- a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/state.ts +++ b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/state.ts @@ -5,11 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ArrayOfImmutableDonation { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -19,29 +19,28 @@ export class ArrayOfImmutableDonation { return wasmlib.getLength(this.objID); } - getDonation(index: i32): sc.ImmutableDonation { - return new sc.ImmutableDonation(this.objID, new wasmlib.Key32(index)); - } + getDonation(index: i32): sc.ImmutableDonation { + return new sc.ImmutableDonation(this.objID, new wasmlib.Key32(index)); + } } 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); - return new sc.ArrayOfImmutableDonation(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateLog], 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, sc.idxMap[sc.IdxStateMaxDonation]); + } totalDonation(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalDonation]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalDonation]); + } } export class ArrayOfMutableDonation { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -55,23 +54,22 @@ export class ArrayOfMutableDonation { return wasmlib.getLength(this.objID); } - getDonation(index: i32): sc.MutableDonation { - return new sc.MutableDonation(this.objID, new wasmlib.Key32(index)); - } + getDonation(index: i32): sc.MutableDonation { + return new sc.MutableDonation(this.objID, new wasmlib.Key32(index)); + } } export class MutableDonateWithFeedbackState extends wasmlib.ScMapID { - log(): sc.ArrayOfMutableDonation { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateLog], wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES); - return new sc.ArrayOfMutableDonation(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateLog], 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, sc.idxMap[sc.IdxStateMaxDonation]); + } totalDonation(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalDonation]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateTotalDonation]); + } } diff --git a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/structs.ts b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/structs.ts index 76419ec3df..91ecb4b41c 100644 --- a/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/structs.ts +++ b/contracts/wasm/donatewithfeedback/ts/donatewithfeedback/structs.ts @@ -5,22 +5,22 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export class Donation { - amount : i64 = 0; // amount donated - donator : wasmlib.ScAgentID = new wasmlib.ScAgentID(); // who donated - error : string = ""; // error to be reported to donator if anything goes wrong - feedback : string = ""; // the feedback for the person donated to - timestamp: i64 = 0; // when the donation took place + amount : i64 = 0; // amount donated + donator : wasmlib.ScAgentID = new wasmlib.ScAgentID(); // who donated + error : string = ""; // error to be reported to donator if anything goes wrong + feedback : string = ""; // the feedback for the person donated to + timestamp : i64 = 0; // when the donation took place static fromBytes(bytes: u8[]): Donation { let decode = new wasmlib.BytesDecoder(bytes); let data = new Donation(); - data.amount = decode.int64(); - data.donator = decode.agentID(); - data.error = decode.string(); - data.feedback = decode.string(); + data.amount = decode.int64(); + data.donator = decode.agentID(); + data.error = decode.string(); + data.feedback = decode.string(); data.timestamp = decode.int64(); decode.close(); return data; @@ -28,11 +28,11 @@ export class Donation { bytes(): u8[] { return new wasmlib.BytesEncoder(). - int64(this.amount). - agentID(this.donator). - string(this.error). - string(this.feedback). - int64(this.timestamp). + int64(this.amount). + agentID(this.donator). + string(this.error). + string(this.feedback). + int64(this.timestamp). data(); } } @@ -51,7 +51,7 @@ export class ImmutableDonation { } value(): Donation { - return Donation.fromBytes(wasmlib.getBytes(this.objID, this.keyID,wasmlib. TYPE_BYTES)); + return Donation.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); } } @@ -64,6 +64,10 @@ export class MutableDonation { 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); } @@ -73,6 +77,6 @@ export class MutableDonation { } value(): Donation { - return Donation.fromBytes(wasmlib.getBytes(this.objID, this.keyID,wasmlib. TYPE_BYTES)); + return Donation.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); } } diff --git a/contracts/wasm/erc20/go/erc20/consts.go b/contracts/wasm/erc20/go/erc20/consts.go index 21ffa48e92..b958c9f6e4 100644 --- a/contracts/wasm/erc20/go/erc20/consts.go +++ b/contracts/wasm/erc20/go/erc20/consts.go @@ -16,23 +16,23 @@ const ( ) const ( - ParamAccount = wasmlib.Key("ac") - ParamAmount = wasmlib.Key("am") - ParamCreator = wasmlib.Key("c") - ParamDelegation = wasmlib.Key("d") - ParamRecipient = wasmlib.Key("r") - ParamSupply = wasmlib.Key("s") + ParamAccount = "ac" + ParamAmount = "am" + ParamCreator = "c" + ParamDelegation = "d" + ParamRecipient = "r" + ParamSupply = "s" ) const ( - ResultAmount = wasmlib.Key("am") - ResultSupply = wasmlib.Key("s") + ResultAmount = "am" + ResultSupply = "s" ) const ( - StateAllAllowances = wasmlib.Key("a") - StateBalances = wasmlib.Key("b") - StateSupply = wasmlib.Key("s") + StateAllAllowances = "a" + StateBalances = "b" + StateSupply = "s" ) const ( diff --git a/contracts/wasm/erc20/go/erc20/erc20.go b/contracts/wasm/erc20/go/erc20/erc20.go index cb17321793..fb6ef50a97 100644 --- a/contracts/wasm/erc20/go/erc20/erc20.go +++ b/contracts/wasm/erc20/go/erc20/erc20.go @@ -17,11 +17,12 @@ import ( func funcApprove(ctx wasmlib.ScFuncContext, f *ApproveContext) { delegation := f.Params.Delegation().Value() amount := f.Params.Amount().Value() - ctx.Require(amount > 0, "erc20.approve.fail: wrong 'amount' parameter") + ctx.Require(amount >= 0, "erc20.approve.fail: wrong 'amount' parameter") // all allowances are in the map under the name of he owner allowances := f.State.AllAllowances().GetAllowancesForAgent(ctx.Caller()) allowances.GetInt64(delegation).SetValue(amount) + f.Events.Approval(amount, ctx.Caller(), delegation) } // on_init is a constructor entry point. It initializes the smart contract with the @@ -46,55 +47,62 @@ func funcInit(ctx wasmlib.ScFuncContext, f *InitContext) { } // transfer moves tokens from caller's account to target account +// This function emits the Transfer event. // Input: // - PARAM_ACCOUNT: agentID // - PARAM_AMOUNT: i64 func funcTransfer(ctx wasmlib.ScFuncContext, f *TransferContext) { amount := f.Params.Amount().Value() - ctx.Require(amount > 0, "erc20.transfer.fail: wrong 'amount' parameter") + ctx.Require(amount >= 0, "erc20.transfer.fail: wrong 'amount' parameter") balances := f.State.Balances() - sourceBalance := balances.GetInt64(ctx.Caller()) + sourceAgent := ctx.Caller() + sourceBalance := balances.GetInt64(sourceAgent) ctx.Require(sourceBalance.Value() >= amount, "erc20.transfer.fail: not enough funds") - targetAddr := f.Params.Account().Value() - targetBalance := balances.GetInt64(targetAddr) + targetAgent := f.Params.Account().Value() + targetBalance := balances.GetInt64(targetAgent) result := targetBalance.Value() + amount - ctx.Require(result > 0, "erc20.transfer.fail: overflow") + ctx.Require(result >= 0, "erc20.transfer.fail: overflow") sourceBalance.SetValue(sourceBalance.Value() - amount) targetBalance.SetValue(targetBalance.Value() + amount) + + f.Events.Transfer(amount, sourceAgent, targetAgent) } // Moves the amount of tokens from sender to recipient using the allowance mechanism. -// Amount is then deducted from the caller’s allowance. This function emits the Transfer event. +// Amount is then deducted from the caller’s allowance. +// This function emits the Transfer event. // Input: // - PARAM_ACCOUNT: agentID the spender // - PARAM_RECIPIENT: agentID the target // - PARAM_AMOUNT: i64 func funcTransferFrom(ctx wasmlib.ScFuncContext, f *TransferFromContext) { // validate parameters - account := f.Params.Account().Value() - recipient := f.Params.Recipient().Value() amount := f.Params.Amount().Value() - ctx.Require(amount > 0, "erc20.transfer_from.fail: wrong 'amount' parameter") + ctx.Require(amount >= 0, "erc20.transfer_from.fail: wrong 'amount' parameter") // allowances are in the map under the name of the account - allowances := f.State.AllAllowances().GetAllowancesForAgent(account) - allowance := allowances.GetInt64(recipient) + sourceAgent := f.Params.Account().Value() + allowances := f.State.AllAllowances().GetAllowancesForAgent(sourceAgent) + allowance := allowances.GetInt64(ctx.Caller()) ctx.Require(allowance.Value() >= amount, "erc20.transfer_from.fail: not enough allowance") balances := f.State.Balances() - sourceBalance := balances.GetInt64(account) + sourceBalance := balances.GetInt64(sourceAgent) ctx.Require(sourceBalance.Value() >= amount, "erc20.transfer_from.fail: not enough funds") - recipientBalance := balances.GetInt64(recipient) - result := recipientBalance.Value() + amount - ctx.Require(result > 0, "erc20.transfer_from.fail: overflow") + targetAgent := f.Params.Recipient().Value() + targetBalance := balances.GetInt64(targetAgent) + result := targetBalance.Value() + amount + ctx.Require(result >= 0, "erc20.transfer_from.fail: overflow") sourceBalance.SetValue(sourceBalance.Value() - amount) - recipientBalance.SetValue(recipientBalance.Value() + amount) + targetBalance.SetValue(targetBalance.Value() + amount) allowance.SetValue(allowance.Value() - amount) + + f.Events.Transfer(amount, sourceAgent, targetAgent) } // the view returns max number of tokens the owner PARAM_ACCOUNT of the account diff --git a/contracts/wasm/erc20/go/erc20/events.go b/contracts/wasm/erc20/go/erc20/events.go new file mode 100644 index 0000000000..7de35ec0a2 --- /dev/null +++ b/contracts/wasm/erc20/go/erc20/events.go @@ -0,0 +1,29 @@ +// 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 + +//nolint:gocritic +package erc20 + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type Erc20Events struct{} + +func (e Erc20Events) Approval(amount int64, owner wasmlib.ScAgentID, spender wasmlib.ScAgentID) { + wasmlib.NewEventEncoder("erc20.approval"). + Int64(amount). + AgentID(owner). + AgentID(spender). + Emit() +} + +func (e Erc20Events) Transfer(amount int64, from wasmlib.ScAgentID, to wasmlib.ScAgentID) { + wasmlib.NewEventEncoder("erc20.transfer"). + Int64(amount). + AgentID(from). + AgentID(to). + Emit() +} diff --git a/contracts/wasm/erc20/go/erc20/keys.go b/contracts/wasm/erc20/go/erc20/keys.go index 5ab67393c5..d23df24110 100644 --- a/contracts/wasm/erc20/go/erc20/keys.go +++ b/contracts/wasm/erc20/go/erc20/keys.go @@ -10,14 +10,16 @@ package erc20 import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" const ( - IdxParamAccount = 0 - IdxParamAmount = 1 - IdxParamCreator = 2 - IdxParamDelegation = 3 - IdxParamRecipient = 4 - IdxParamSupply = 5 - IdxResultAmount = 6 - IdxResultSupply = 7 + IdxParamAccount = 0 + IdxParamAmount = 1 + IdxParamCreator = 2 + IdxParamDelegation = 3 + IdxParamRecipient = 4 + IdxParamSupply = 5 + + IdxResultAmount = 6 + IdxResultSupply = 7 + IdxStateAllAllowances = 8 IdxStateBalances = 9 IdxStateSupply = 10 diff --git a/contracts/wasm/erc20/go/erc20/lib.go b/contracts/wasm/erc20/go/erc20/lib.go index d4948bdbf6..5970c162bd 100644 --- a/contracts/wasm/erc20/go/erc20/lib.go +++ b/contracts/wasm/erc20/go/erc20/lib.go @@ -25,6 +25,7 @@ func OnLoad() { } type ApproveContext struct { + Events Erc20Events Params ImmutableApproveParams State MutableErc20State } @@ -46,6 +47,7 @@ func funcApproveThunk(ctx wasmlib.ScFuncContext) { } type InitContext struct { + Events Erc20Events Params ImmutableInitParams State MutableErc20State } @@ -67,6 +69,7 @@ func funcInitThunk(ctx wasmlib.ScFuncContext) { } type TransferContext struct { + Events Erc20Events Params ImmutableTransferParams State MutableErc20State } @@ -88,6 +91,7 @@ func funcTransferThunk(ctx wasmlib.ScFuncContext) { } type TransferFromContext struct { + Events Erc20Events Params ImmutableTransferFromParams State MutableErc20State } diff --git a/contracts/wasm/erc20/schema.yaml b/contracts/wasm/erc20/schema.yaml index 31d9cc2147..dc54a60a38 100644 --- a/contracts/wasm/erc20/schema.yaml +++ b/contracts/wasm/erc20/schema.yaml @@ -1,5 +1,14 @@ name: Erc20 description: ERC-20 PoC for IOTA Smart Contracts +events: + approval: + amount: Int64 + owner: AgentID + spender: AgentID + transfer: + amount: Int64 + from: AgentID + to: AgentID structs: {} typedefs: AllowancesForAgent: map[AgentID]Int64 diff --git a/contracts/wasm/erc20/src/consts.rs b/contracts/wasm/erc20/src/consts.rs index f6d645cef5..3c644e36a4 100644 --- a/contracts/wasm/erc20/src/consts.rs +++ b/contracts/wasm/erc20/src/consts.rs @@ -5,44 +5,40 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; -pub const SC_NAME: &str = "erc20"; -pub const SC_DESCRIPTION: &str = "ERC-20 PoC for IOTA Smart Contracts"; -pub const HSC_NAME: ScHname = ScHname(0x200e3733); - -pub const PARAM_ACCOUNT: &str = "ac"; -pub const PARAM_AMOUNT: &str = "am"; -pub const PARAM_CREATOR: &str = "c"; -pub const PARAM_DELEGATION: &str = "d"; -pub const PARAM_RECIPIENT: &str = "r"; -pub const PARAM_SUPPLY: &str = "s"; - -pub const RESULT_AMOUNT: &str = "am"; -pub const RESULT_SUPPLY: &str = "s"; - -pub const STATE_ALL_ALLOWANCES: &str = "a"; -pub const STATE_BALANCES: &str = "b"; -pub const STATE_SUPPLY: &str = "s"; - -pub const FUNC_APPROVE: &str = "approve"; -pub const FUNC_INIT: &str = "init"; -pub const FUNC_TRANSFER: &str = "transfer"; -pub const FUNC_TRANSFER_FROM: &str = "transferFrom"; -pub const VIEW_ALLOWANCE: &str = "allowance"; -pub const VIEW_BALANCE_OF: &str = "balanceOf"; -pub const VIEW_TOTAL_SUPPLY: &str = "totalSupply"; - -pub const HFUNC_APPROVE: ScHname = ScHname(0xa0661268); -pub const HFUNC_INIT: ScHname = ScHname(0x1f44d644); -pub const HFUNC_TRANSFER: ScHname = ScHname(0xa15da184); -pub const HFUNC_TRANSFER_FROM: ScHname = ScHname(0xd5e0a602); -pub const HVIEW_ALLOWANCE: ScHname = ScHname(0x5e16006a); -pub const HVIEW_BALANCE_OF: ScHname = ScHname(0x67ef8df4); -pub const HVIEW_TOTAL_SUPPLY: ScHname = ScHname(0x9505e6ca); - -// @formatter:on +pub const SC_NAME : &str = "erc20"; +pub const SC_DESCRIPTION : &str = "ERC-20 PoC for IOTA Smart Contracts"; +pub const HSC_NAME : ScHname = ScHname(0x200e3733); + +pub const PARAM_ACCOUNT : &str = "ac"; +pub const PARAM_AMOUNT : &str = "am"; +pub const PARAM_CREATOR : &str = "c"; +pub const PARAM_DELEGATION : &str = "d"; +pub const PARAM_RECIPIENT : &str = "r"; +pub const PARAM_SUPPLY : &str = "s"; + +pub const RESULT_AMOUNT : &str = "am"; +pub const RESULT_SUPPLY : &str = "s"; + +pub const STATE_ALL_ALLOWANCES : &str = "a"; +pub const STATE_BALANCES : &str = "b"; +pub const STATE_SUPPLY : &str = "s"; + +pub const FUNC_APPROVE : &str = "approve"; +pub const FUNC_INIT : &str = "init"; +pub const FUNC_TRANSFER : &str = "transfer"; +pub const FUNC_TRANSFER_FROM : &str = "transferFrom"; +pub const VIEW_ALLOWANCE : &str = "allowance"; +pub const VIEW_BALANCE_OF : &str = "balanceOf"; +pub const VIEW_TOTAL_SUPPLY : &str = "totalSupply"; + +pub const HFUNC_APPROVE : ScHname = ScHname(0xa0661268); +pub const HFUNC_INIT : ScHname = ScHname(0x1f44d644); +pub const HFUNC_TRANSFER : ScHname = ScHname(0xa15da184); +pub const HFUNC_TRANSFER_FROM : ScHname = ScHname(0xd5e0a602); +pub const HVIEW_ALLOWANCE : ScHname = ScHname(0x5e16006a); +pub const HVIEW_BALANCE_OF : ScHname = ScHname(0x67ef8df4); +pub const HVIEW_TOTAL_SUPPLY : ScHname = ScHname(0x9505e6ca); diff --git a/contracts/wasm/erc20/src/contract.rs b/contracts/wasm/erc20/src/contract.rs index 4d3d30f540..cc412c413d 100644 --- a/contracts/wasm/erc20/src/contract.rs +++ b/contracts/wasm/erc20/src/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -18,40 +16,40 @@ use crate::params::*; use crate::results::*; pub struct ApproveCall { - pub func: ScFunc, - pub params: MutableApproveParams, + pub func: ScFunc, + pub params: MutableApproveParams, } pub struct InitCall { - pub func: ScInitFunc, - pub params: MutableInitParams, + pub func: ScInitFunc, + pub params: MutableInitParams, } pub struct TransferCall { - pub func: ScFunc, - pub params: MutableTransferParams, + pub func: ScFunc, + pub params: MutableTransferParams, } pub struct TransferFromCall { - pub func: ScFunc, - pub params: MutableTransferFromParams, + pub func: ScFunc, + pub params: MutableTransferFromParams, } pub struct AllowanceCall { - pub func: ScView, - pub params: MutableAllowanceParams, - pub results: ImmutableAllowanceResults, + pub func: ScView, + pub params: MutableAllowanceParams, + pub results: ImmutableAllowanceResults, } pub struct BalanceOfCall { - pub func: ScView, - pub params: MutableBalanceOfParams, - pub results: ImmutableBalanceOfResults, + pub func: ScView, + pub params: MutableBalanceOfParams, + pub results: ImmutableBalanceOfResults, } pub struct TotalSupplyCall { - pub func: ScView, - pub results: ImmutableTotalSupplyResults, + pub func: ScView, + pub results: ImmutableTotalSupplyResults, } pub struct ScFuncs { @@ -60,62 +58,66 @@ pub struct ScFuncs { impl ScFuncs { pub fn approve(_ctx: & dyn ScFuncCallContext) -> ApproveCall { let mut f = ApproveCall { - func: ScFunc::new(HSC_NAME, HFUNC_APPROVE), + func: ScFunc::new(HSC_NAME, HFUNC_APPROVE), params: MutableApproveParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn init(_ctx: & dyn ScFuncCallContext) -> InitCall { let mut f = InitCall { - func: ScInitFunc::new(HSC_NAME, HFUNC_INIT), + func: ScInitFunc::new(HSC_NAME, HFUNC_INIT), params: MutableInitParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn transfer(_ctx: & dyn ScFuncCallContext) -> TransferCall { let mut f = TransferCall { - func: ScFunc::new(HSC_NAME, HFUNC_TRANSFER), + func: ScFunc::new(HSC_NAME, HFUNC_TRANSFER), params: MutableTransferParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn transfer_from(_ctx: & dyn ScFuncCallContext) -> TransferFromCall { let mut f = TransferFromCall { - func: ScFunc::new(HSC_NAME, HFUNC_TRANSFER_FROM), + func: ScFunc::new(HSC_NAME, HFUNC_TRANSFER_FROM), params: MutableTransferFromParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn allowance(_ctx: & dyn ScViewCallContext) -> AllowanceCall { let mut f = AllowanceCall { - func: ScView::new(HSC_NAME, HVIEW_ALLOWANCE), - params: MutableAllowanceParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_ALLOWANCE), + params: MutableAllowanceParams { id: 0 }, results: ImmutableAllowanceResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn balance_of(_ctx: & dyn ScViewCallContext) -> BalanceOfCall { let mut f = BalanceOfCall { - func: ScView::new(HSC_NAME, HVIEW_BALANCE_OF), - params: MutableBalanceOfParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_BALANCE_OF), + params: MutableBalanceOfParams { id: 0 }, results: ImmutableBalanceOfResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn total_supply(_ctx: & dyn ScViewCallContext) -> TotalSupplyCall { let mut f = TotalSupplyCall { - func: ScView::new(HSC_NAME, HVIEW_TOTAL_SUPPLY), + func: ScView::new(HSC_NAME, HVIEW_TOTAL_SUPPLY), results: ImmutableTotalSupplyResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/contracts/wasm/erc20/src/erc20.rs b/contracts/wasm/erc20/src/erc20.rs index fd3ac86a1b..f056e80706 100644 --- a/contracts/wasm/erc20/src/erc20.rs +++ b/contracts/wasm/erc20/src/erc20.rs @@ -15,11 +15,12 @@ use crate::*; pub fn func_approve(ctx: &ScFuncContext, f: &ApproveContext) { let delegation = f.params.delegation().value(); let amount = f.params.amount().value(); - ctx.require(amount > 0, "erc20.approve.fail: wrong 'amount' parameter"); + ctx.require(amount >= 0, "erc20.approve.fail: wrong 'amount' parameter"); // all allowances are in the map under the name of he owner let allowances = f.state.all_allowances().get_allowances_for_agent(&ctx.caller()); allowances.get_int64(&delegation).set_value(amount); + f.events.approval(amount, &ctx.caller(), &delegation); } // on_init is a constructor entry point. It initializes the smart contract with the @@ -44,55 +45,62 @@ pub fn func_init(ctx: &ScFuncContext, f: &InitContext) { } // transfer moves tokens from caller's account to target account +// This function emits the Transfer event. // Input: // - PARAM_ACCOUNT: agentID // - PARAM_AMOUNT: i64 pub fn func_transfer(ctx: &ScFuncContext, f: &TransferContext) { let amount = f.params.amount().value(); - ctx.require(amount > 0, "erc20.transfer.fail: wrong 'amount' parameter"); + ctx.require(amount >= 0, "erc20.transfer.fail: wrong 'amount' parameter"); let balances = f.state.balances(); - let source_balance = balances.get_int64(&ctx.caller()); + let source_agent = ctx.caller(); + let source_balance = balances.get_int64(&source_agent); ctx.require(source_balance.value() >= amount, "erc20.transfer.fail: not enough funds"); - let target_addr = f.params.account().value(); - let target_balance = balances.get_int64(&target_addr); + let target_agent = f.params.account().value(); + let target_balance = balances.get_int64(&target_agent); let result = target_balance.value() + amount; - ctx.require(result > 0, "erc20.transfer.fail: overflow"); + ctx.require(result >= 0, "erc20.transfer.fail: overflow"); source_balance.set_value(source_balance.value() - amount); target_balance.set_value(target_balance.value() + amount); + + f.events.transfer(amount, &source_agent, &target_agent); } // Moves the amount of tokens from sender to recipient using the allowance mechanism. -// Amount is then deducted from the caller’s allowance. This function emits the Transfer event. +// Amount is then deducted from the caller’s allowance. +// This function emits the Transfer event. // Input: // - PARAM_ACCOUNT: agentID the spender // - PARAM_RECIPIENT: agentID the target // - PARAM_AMOUNT: i64 pub fn func_transfer_from(ctx: &ScFuncContext, f: &TransferFromContext) { // validate parameters - let account = f.params.account().value(); - let recipient = f.params.recipient().value(); let amount = f.params.amount().value(); - ctx.require(amount > 0, "erc20.transfer_from.fail: wrong 'amount' parameter"); + ctx.require(amount >= 0, "erc20.transfer_from.fail: wrong 'amount' parameter"); // allowances are in the map under the name of the account - let allowances = f.state.all_allowances().get_allowances_for_agent(&account); - let allowance = allowances.get_int64(&recipient); + let source_agent = f.params.account().value(); + let allowances = f.state.all_allowances().get_allowances_for_agent(&source_agent); + let allowance = allowances.get_int64(&ctx.caller()); ctx.require(allowance.value() >= amount, "erc20.transfer_from.fail: not enough allowance"); let balances = f.state.balances(); - let source_balance = balances.get_int64(&account); + let source_balance = balances.get_int64(&source_agent); ctx.require(source_balance.value() >= amount, "erc20.transfer_from.fail: not enough funds"); - let recipient_balance = balances.get_int64(&recipient); - let result = recipient_balance.value() + amount; - ctx.require(result > 0, "erc20.transfer_from.fail: overflow"); + let target_agent = f.params.recipient().value(); + let target_balance = balances.get_int64(&target_agent); + let result = target_balance.value() + amount; + ctx.require(result >= 0, "erc20.transfer_from.fail: overflow"); source_balance.set_value(source_balance.value() - amount); - recipient_balance.set_value(recipient_balance.value() + amount); + target_balance.set_value(target_balance.value() + amount); allowance.set_value(allowance.value() - amount); + + f.events.transfer(amount, &source_agent, &target_agent); } // the view returns max number of tokens the owner PARAM_ACCOUNT of the account diff --git a/contracts/wasm/erc20/src/events.rs b/contracts/wasm/erc20/src/events.rs new file mode 100644 index 0000000000..74bf775813 --- /dev/null +++ b/contracts/wasm/erc20/src/events.rs @@ -0,0 +1,32 @@ +// 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 Erc20Events { +} + +impl Erc20Events { + + pub fn approval(&self, amount: i64, owner: &ScAgentID, spender: &ScAgentID) { + let mut encoder = EventEncoder::new("erc20.approval"); + encoder.int64(amount); + encoder.agent_id(&owner); + encoder.agent_id(&spender); + encoder.emit(); + } + + pub fn transfer(&self, amount: i64, from: &ScAgentID, to: &ScAgentID) { + let mut encoder = EventEncoder::new("erc20.transfer"); + encoder.int64(amount); + encoder.agent_id(&from); + encoder.agent_id(&to); + encoder.emit(); + } +} diff --git a/contracts/wasm/erc20/src/keys.rs b/contracts/wasm/erc20/src/keys.rs index a10438202e..44095bd456 100644 --- a/contracts/wasm/erc20/src/keys.rs +++ b/contracts/wasm/erc20/src/keys.rs @@ -5,40 +5,40 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use crate::*; -pub(crate) const IDX_PARAM_ACCOUNT: usize = 0; -pub(crate) const IDX_PARAM_AMOUNT: usize = 1; -pub(crate) const IDX_PARAM_CREATOR: usize = 2; -pub(crate) const IDX_PARAM_DELEGATION: usize = 3; -pub(crate) const IDX_PARAM_RECIPIENT: usize = 4; -pub(crate) const IDX_PARAM_SUPPLY: usize = 5; -pub(crate) const IDX_RESULT_AMOUNT: usize = 6; -pub(crate) const IDX_RESULT_SUPPLY: usize = 7; -pub(crate) const IDX_STATE_ALL_ALLOWANCES: usize = 8; -pub(crate) const IDX_STATE_BALANCES: usize = 9; -pub(crate) const IDX_STATE_SUPPLY: usize = 10; +pub(crate) const IDX_PARAM_ACCOUNT : usize = 0; +pub(crate) const IDX_PARAM_AMOUNT : usize = 1; +pub(crate) const IDX_PARAM_CREATOR : usize = 2; +pub(crate) const IDX_PARAM_DELEGATION : usize = 3; +pub(crate) const IDX_PARAM_RECIPIENT : usize = 4; +pub(crate) const IDX_PARAM_SUPPLY : usize = 5; + +pub(crate) const IDX_RESULT_AMOUNT : usize = 6; +pub(crate) const IDX_RESULT_SUPPLY : usize = 7; + +pub(crate) const IDX_STATE_ALL_ALLOWANCES : usize = 8; +pub(crate) const IDX_STATE_BALANCES : usize = 9; +pub(crate) const IDX_STATE_SUPPLY : usize = 10; pub const KEY_MAP_LEN: usize = 11; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ - PARAM_ACCOUNT, - PARAM_AMOUNT, - PARAM_CREATOR, - PARAM_DELEGATION, - PARAM_RECIPIENT, - PARAM_SUPPLY, - RESULT_AMOUNT, - RESULT_SUPPLY, - STATE_ALL_ALLOWANCES, - STATE_BALANCES, - STATE_SUPPLY, + PARAM_ACCOUNT, + PARAM_AMOUNT, + PARAM_CREATOR, + PARAM_DELEGATION, + PARAM_RECIPIENT, + PARAM_SUPPLY, + RESULT_AMOUNT, + RESULT_SUPPLY, + STATE_ALL_ALLOWANCES, + STATE_BALANCES, + STATE_SUPPLY, ]; pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; @@ -48,5 +48,3 @@ pub fn idx_map(idx: usize) -> Key32 { IDX_MAP[idx] } } - -// @formatter:on diff --git a/contracts/wasm/erc20/src/lib.rs b/contracts/wasm/erc20/src/lib.rs index 6aacad2b4a..e3bc083c0b 100644 --- a/contracts/wasm/erc20/src/lib.rs +++ b/contracts/wasm/erc20/src/lib.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] #![allow(unused_imports)] @@ -15,6 +13,7 @@ use wasmlib::*; use wasmlib::host::*; use crate::consts::*; +use crate::events::*; use crate::keys::*; use crate::params::*; use crate::results::*; @@ -22,6 +21,7 @@ use crate::state::*; mod consts; mod contract; +mod events; mod keys; mod params; mod results; @@ -32,13 +32,13 @@ mod erc20; #[no_mangle] fn on_load() { let exports = ScExports::new(); - exports.add_func(FUNC_APPROVE, func_approve_thunk); - exports.add_func(FUNC_INIT, func_init_thunk); - exports.add_func(FUNC_TRANSFER, func_transfer_thunk); + exports.add_func(FUNC_APPROVE, func_approve_thunk); + exports.add_func(FUNC_INIT, func_init_thunk); + exports.add_func(FUNC_TRANSFER, func_transfer_thunk); exports.add_func(FUNC_TRANSFER_FROM, func_transfer_from_thunk); - exports.add_view(VIEW_ALLOWANCE, view_allowance_thunk); - exports.add_view(VIEW_BALANCE_OF, view_balance_of_thunk); - exports.add_view(VIEW_TOTAL_SUPPLY, view_total_supply_thunk); + exports.add_view(VIEW_ALLOWANCE, view_allowance_thunk); + exports.add_view(VIEW_BALANCE_OF, view_balance_of_thunk); + exports.add_view(VIEW_TOTAL_SUPPLY, view_total_supply_thunk); unsafe { for i in 0..KEY_MAP_LEN { @@ -48,156 +48,162 @@ fn on_load() { } pub struct ApproveContext { - params: ImmutableApproveParams, - state: MutableErc20State, + events: Erc20Events, + params: ImmutableApproveParams, + state: MutableErc20State, } fn func_approve_thunk(ctx: &ScFuncContext) { - ctx.log("erc20.funcApprove"); - let f = ApproveContext { - params: ImmutableApproveParams { - id: OBJ_ID_PARAMS, - }, - state: MutableErc20State { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.amount().exists(), "missing mandatory amount"); - ctx.require(f.params.delegation().exists(), "missing mandatory delegation"); - func_approve(ctx, &f); - ctx.log("erc20.funcApprove ok"); + ctx.log("erc20.funcApprove"); + let f = ApproveContext { + events: Erc20Events {}, + params: ImmutableApproveParams { + id: OBJ_ID_PARAMS, + }, + state: MutableErc20State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.amount().exists(), "missing mandatory amount"); + ctx.require(f.params.delegation().exists(), "missing mandatory delegation"); + func_approve(ctx, &f); + ctx.log("erc20.funcApprove ok"); } pub struct InitContext { - params: ImmutableInitParams, - state: MutableErc20State, + events: Erc20Events, + params: ImmutableInitParams, + state: MutableErc20State, } fn func_init_thunk(ctx: &ScFuncContext) { - ctx.log("erc20.funcInit"); - let f = InitContext { - params: ImmutableInitParams { - id: OBJ_ID_PARAMS, - }, - state: MutableErc20State { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.creator().exists(), "missing mandatory creator"); - ctx.require(f.params.supply().exists(), "missing mandatory supply"); - func_init(ctx, &f); - ctx.log("erc20.funcInit ok"); + ctx.log("erc20.funcInit"); + let f = InitContext { + events: Erc20Events {}, + params: ImmutableInitParams { + id: OBJ_ID_PARAMS, + }, + state: MutableErc20State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.creator().exists(), "missing mandatory creator"); + ctx.require(f.params.supply().exists(), "missing mandatory supply"); + func_init(ctx, &f); + ctx.log("erc20.funcInit ok"); } pub struct TransferContext { - params: ImmutableTransferParams, - state: MutableErc20State, + events: Erc20Events, + params: ImmutableTransferParams, + state: MutableErc20State, } fn func_transfer_thunk(ctx: &ScFuncContext) { - ctx.log("erc20.funcTransfer"); - let f = TransferContext { - params: ImmutableTransferParams { - id: OBJ_ID_PARAMS, - }, - state: MutableErc20State { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.account().exists(), "missing mandatory account"); - ctx.require(f.params.amount().exists(), "missing mandatory amount"); - func_transfer(ctx, &f); - ctx.log("erc20.funcTransfer ok"); + ctx.log("erc20.funcTransfer"); + let f = TransferContext { + events: Erc20Events {}, + params: ImmutableTransferParams { + id: OBJ_ID_PARAMS, + }, + state: MutableErc20State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.account().exists(), "missing mandatory account"); + ctx.require(f.params.amount().exists(), "missing mandatory amount"); + func_transfer(ctx, &f); + ctx.log("erc20.funcTransfer ok"); } pub struct TransferFromContext { - params: ImmutableTransferFromParams, - state: MutableErc20State, + events: Erc20Events, + params: ImmutableTransferFromParams, + state: MutableErc20State, } fn func_transfer_from_thunk(ctx: &ScFuncContext) { - ctx.log("erc20.funcTransferFrom"); - let f = TransferFromContext { - params: ImmutableTransferFromParams { - id: OBJ_ID_PARAMS, - }, - state: MutableErc20State { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.account().exists(), "missing mandatory account"); - ctx.require(f.params.amount().exists(), "missing mandatory amount"); - ctx.require(f.params.recipient().exists(), "missing mandatory recipient"); - func_transfer_from(ctx, &f); - ctx.log("erc20.funcTransferFrom ok"); + ctx.log("erc20.funcTransferFrom"); + let f = TransferFromContext { + events: Erc20Events {}, + params: ImmutableTransferFromParams { + id: OBJ_ID_PARAMS, + }, + state: MutableErc20State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.account().exists(), "missing mandatory account"); + ctx.require(f.params.amount().exists(), "missing mandatory amount"); + ctx.require(f.params.recipient().exists(), "missing mandatory recipient"); + func_transfer_from(ctx, &f); + ctx.log("erc20.funcTransferFrom ok"); } pub struct AllowanceContext { - params: ImmutableAllowanceParams, - results: MutableAllowanceResults, - state: ImmutableErc20State, + params: ImmutableAllowanceParams, + results: MutableAllowanceResults, + state: ImmutableErc20State, } fn view_allowance_thunk(ctx: &ScViewContext) { - ctx.log("erc20.viewAllowance"); - let f = AllowanceContext { - params: ImmutableAllowanceParams { - id: OBJ_ID_PARAMS, - }, - results: MutableAllowanceResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableErc20State { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.account().exists(), "missing mandatory account"); - ctx.require(f.params.delegation().exists(), "missing mandatory delegation"); - view_allowance(ctx, &f); - ctx.log("erc20.viewAllowance ok"); + ctx.log("erc20.viewAllowance"); + let f = AllowanceContext { + params: ImmutableAllowanceParams { + id: OBJ_ID_PARAMS, + }, + results: MutableAllowanceResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableErc20State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.account().exists(), "missing mandatory account"); + ctx.require(f.params.delegation().exists(), "missing mandatory delegation"); + view_allowance(ctx, &f); + ctx.log("erc20.viewAllowance ok"); } pub struct BalanceOfContext { - params: ImmutableBalanceOfParams, - results: MutableBalanceOfResults, - state: ImmutableErc20State, + params: ImmutableBalanceOfParams, + results: MutableBalanceOfResults, + state: ImmutableErc20State, } fn view_balance_of_thunk(ctx: &ScViewContext) { - ctx.log("erc20.viewBalanceOf"); - let f = BalanceOfContext { - params: ImmutableBalanceOfParams { - id: OBJ_ID_PARAMS, - }, - results: MutableBalanceOfResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableErc20State { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.account().exists(), "missing mandatory account"); - view_balance_of(ctx, &f); - ctx.log("erc20.viewBalanceOf ok"); + ctx.log("erc20.viewBalanceOf"); + let f = BalanceOfContext { + params: ImmutableBalanceOfParams { + id: OBJ_ID_PARAMS, + }, + results: MutableBalanceOfResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableErc20State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.account().exists(), "missing mandatory account"); + view_balance_of(ctx, &f); + ctx.log("erc20.viewBalanceOf ok"); } pub struct TotalSupplyContext { - results: MutableTotalSupplyResults, - state: ImmutableErc20State, + results: MutableTotalSupplyResults, + state: ImmutableErc20State, } fn view_total_supply_thunk(ctx: &ScViewContext) { - ctx.log("erc20.viewTotalSupply"); - let f = TotalSupplyContext { - results: MutableTotalSupplyResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableErc20State { - id: OBJ_ID_STATE, - }, - }; - view_total_supply(ctx, &f); - ctx.log("erc20.viewTotalSupply ok"); + ctx.log("erc20.viewTotalSupply"); + let f = TotalSupplyContext { + results: MutableTotalSupplyResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableErc20State { + id: OBJ_ID_STATE, + }, + }; + view_total_supply(ctx, &f); + ctx.log("erc20.viewTotalSupply ok"); } - -// @formatter:on diff --git a/contracts/wasm/erc20/src/params.rs b/contracts/wasm/erc20/src/params.rs index 268522f51b..e57011db0e 100644 --- a/contracts/wasm/erc20/src/params.rs +++ b/contracts/wasm/erc20/src/params.rs @@ -13,6 +13,7 @@ use wasmlib::host::*; use crate::*; use crate::keys::*; +use crate::typedefs::*; #[derive(Clone, Copy)] pub struct ImmutableApproveParams { @@ -21,12 +22,12 @@ pub struct ImmutableApproveParams { impl ImmutableApproveParams { pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + } pub fn delegation(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) + } } #[derive(Clone, Copy)] @@ -36,12 +37,12 @@ pub struct MutableApproveParams { impl MutableApproveParams { pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + } pub fn delegation(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) + } } #[derive(Clone, Copy)] @@ -51,12 +52,12 @@ pub struct ImmutableInitParams { impl ImmutableInitParams { pub fn creator(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CREATOR)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CREATOR)) + } pub fn supply(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_SUPPLY)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_SUPPLY)) + } } #[derive(Clone, Copy)] @@ -66,12 +67,12 @@ pub struct MutableInitParams { impl MutableInitParams { pub fn creator(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CREATOR)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CREATOR)) + } pub fn supply(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_SUPPLY)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_SUPPLY)) + } } #[derive(Clone, Copy)] @@ -81,12 +82,12 @@ pub struct ImmutableTransferParams { impl ImmutableTransferParams { pub fn account(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + } pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + } } #[derive(Clone, Copy)] @@ -96,12 +97,12 @@ pub struct MutableTransferParams { impl MutableTransferParams { pub fn account(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + } pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + } } #[derive(Clone, Copy)] @@ -111,16 +112,16 @@ pub struct ImmutableTransferFromParams { impl ImmutableTransferFromParams { pub fn account(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + } pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + } pub fn recipient(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_RECIPIENT)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_RECIPIENT)) + } } #[derive(Clone, Copy)] @@ -130,16 +131,16 @@ pub struct MutableTransferFromParams { impl MutableTransferFromParams { pub fn account(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + } pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_AMOUNT)) + } pub fn recipient(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_RECIPIENT)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_RECIPIENT)) + } } #[derive(Clone, Copy)] @@ -149,12 +150,12 @@ pub struct ImmutableAllowanceParams { impl ImmutableAllowanceParams { pub fn account(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + } pub fn delegation(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) + } } #[derive(Clone, Copy)] @@ -164,12 +165,12 @@ pub struct MutableAllowanceParams { impl MutableAllowanceParams { pub fn account(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + } pub fn delegation(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_DELEGATION)) + } } #[derive(Clone, Copy)] @@ -179,8 +180,8 @@ pub struct ImmutableBalanceOfParams { impl ImmutableBalanceOfParams { pub fn account(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_ACCOUNT)) + } } #[derive(Clone, Copy)] @@ -190,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, idx_map(IDX_PARAM_ACCOUNT)) + } } diff --git a/contracts/wasm/erc20/src/results.rs b/contracts/wasm/erc20/src/results.rs index 4318c1600e..8d01ae636d 100644 --- a/contracts/wasm/erc20/src/results.rs +++ b/contracts/wasm/erc20/src/results.rs @@ -13,6 +13,7 @@ use wasmlib::host::*; use crate::*; use crate::keys::*; +use crate::typedefs::*; #[derive(Clone, Copy)] pub struct ImmutableAllowanceResults { @@ -21,8 +22,8 @@ pub struct ImmutableAllowanceResults { impl ImmutableAllowanceResults { pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + } } #[derive(Clone, Copy)] @@ -32,8 +33,8 @@ pub struct MutableAllowanceResults { impl MutableAllowanceResults { pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + } } #[derive(Clone, Copy)] @@ -43,8 +44,8 @@ pub struct ImmutableBalanceOfResults { impl ImmutableBalanceOfResults { pub fn amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + } } #[derive(Clone, Copy)] @@ -54,8 +55,8 @@ pub struct MutableBalanceOfResults { impl MutableBalanceOfResults { pub fn amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + } } #[derive(Clone, Copy)] @@ -65,8 +66,8 @@ pub struct ImmutableTotalSupplyResults { impl ImmutableTotalSupplyResults { pub fn supply(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_SUPPLY)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_SUPPLY)) + } } #[derive(Clone, Copy)] @@ -76,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, idx_map(IDX_RESULT_SUPPLY)) + } } diff --git a/contracts/wasm/erc20/src/state.rs b/contracts/wasm/erc20/src/state.rs index 53e02ccc72..c67adb6537 100644 --- a/contracts/wasm/erc20/src/state.rs +++ b/contracts/wasm/erc20/src/state.rs @@ -16,7 +16,7 @@ use crate::keys::*; use crate::typedefs::*; pub struct MapAgentIDToImmutableAllowancesForAgent { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapAgentIDToImmutableAllowancesForAgent { @@ -33,27 +33,27 @@ 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); - MapAgentIDToImmutableAllowancesForAgent { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_ALL_ALLOWANCES), 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); - MapAgentIDToImmutableInt64 { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_BALANCES), 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, idx_map(IDX_STATE_SUPPLY)) + } } pub struct MapAgentIDToMutableAllowancesForAgent { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapAgentIDToMutableAllowancesForAgent { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_allowances_for_agent(&self, key: &ScAgentID) -> MutableAllowancesForAgent { @@ -69,16 +69,16 @@ pub struct MutableErc20State { impl MutableErc20State { pub fn all_allowances(&self) -> MapAgentIDToMutableAllowancesForAgent { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_ALL_ALLOWANCES), TYPE_MAP); - MapAgentIDToMutableAllowancesForAgent { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_ALL_ALLOWANCES), 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); - MapAgentIDToMutableInt64 { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_BALANCES), 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, idx_map(IDX_STATE_SUPPLY)) + } } diff --git a/contracts/wasm/erc20/src/typedefs.rs b/contracts/wasm/erc20/src/typedefs.rs index 406956ec5e..530075de78 100644 --- a/contracts/wasm/erc20/src/typedefs.rs +++ b/contracts/wasm/erc20/src/typedefs.rs @@ -5,15 +5,13 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use wasmlib::host::*; pub struct MapAgentIDToImmutableInt64 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapAgentIDToImmutableInt64 { @@ -25,12 +23,12 @@ impl MapAgentIDToImmutableInt64 { pub type ImmutableAllowancesForAgent = MapAgentIDToImmutableInt64; pub struct MapAgentIDToMutableInt64 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapAgentIDToMutableInt64 { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_int64(&self, key: &ScAgentID) -> ScMutableInt64 { @@ -39,5 +37,3 @@ impl MapAgentIDToMutableInt64 { } pub type MutableAllowancesForAgent = MapAgentIDToMutableInt64; - -// @formatter:on diff --git a/contracts/wasm/erc20/test/erc20_bg.wasm b/contracts/wasm/erc20/test/erc20_bg.wasm index 68e2d7e73c..4ba488aa6c 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/test/erc20_test.go b/contracts/wasm/erc20/test/erc20_test.go index 56a5f82437..4c9737be4b 100644 --- a/contracts/wasm/erc20/test/erc20_test.go +++ b/contracts/wasm/erc20/test/erc20_test.go @@ -80,8 +80,8 @@ func transfer(ctx *wasmsolo.SoloContext, from, to *wasmsolo.SoloAgent, amount ui return ctx.Err } -func transferFrom(ctx *wasmsolo.SoloContext, from, to *wasmsolo.SoloAgent, amount uint64) error { - tx := erc20.ScFuncs.TransferFrom(ctx.Sign(from)) +func transferFrom(ctx *wasmsolo.SoloContext, delegate, from, to *wasmsolo.SoloAgent, amount uint64) error { + tx := erc20.ScFuncs.TransferFrom(ctx.Sign(delegate)) tx.Params.Account().SetValue(from.ScAgentID()) tx.Params.Recipient().SetValue(to.ScAgentID()) tx.Params.Amount().SetValue(int64(amount)) @@ -143,68 +143,87 @@ func TestTransferNotEnoughFunds2(t *testing.T) { func TestNoAllowance(t *testing.T) { ctx := setupErc20(t) - user := ctx.NewSoloAgent() - checkErc20Allowance(ctx, creator, user, 0) + delegate := ctx.NewSoloAgent() + checkErc20Allowance(ctx, creator, delegate, 0) } func TestApprove(t *testing.T) { ctx := setupErc20(t) - user := ctx.NewSoloAgent() + delegate := ctx.NewSoloAgent() - require.NoError(t, approve(ctx, creator, user, 100)) + require.NoError(t, approve(ctx, creator, delegate, 100)) - checkErc20Allowance(ctx, creator, user, 100) + checkErc20Allowance(ctx, creator, delegate, 100) checkErc20Balance(ctx, creator, solo.Saldo) - checkErc20Balance(ctx, user, 0) + checkErc20Balance(ctx, delegate, 0) } func TestTransferFromOk1(t *testing.T) { ctx := setupErc20(t) - user := ctx.NewSoloAgent() + delegate := ctx.NewSoloAgent() - require.NoError(t, approve(ctx, creator, user, 100)) + require.NoError(t, approve(ctx, creator, delegate, 100)) - checkErc20Allowance(ctx, creator, user, 100) + checkErc20Allowance(ctx, creator, delegate, 100) checkErc20Balance(ctx, creator, solo.Saldo) - checkErc20Balance(ctx, user, 0) + checkErc20Balance(ctx, delegate, 0) - require.NoError(t, transferFrom(ctx, creator, user, 50)) + require.NoError(t, transferFrom(ctx, delegate, creator, delegate, 50)) - checkErc20Allowance(ctx, creator, user, 50) + checkErc20Allowance(ctx, creator, delegate, 50) checkErc20Balance(ctx, creator, solo.Saldo-50) - checkErc20Balance(ctx, user, 50) + checkErc20Balance(ctx, delegate, 50) } func TestTransferFromOk2(t *testing.T) { ctx := setupErc20(t) - user := ctx.NewSoloAgent() + delegate := ctx.NewSoloAgent() - require.NoError(t, approve(ctx, creator, user, 100)) + require.NoError(t, approve(ctx, creator, delegate, 100)) - checkErc20Allowance(ctx, creator, user, 100) + checkErc20Allowance(ctx, creator, delegate, 100) checkErc20Balance(ctx, creator, solo.Saldo) - checkErc20Balance(ctx, user, 0) + checkErc20Balance(ctx, delegate, 0) - require.NoError(t, transferFrom(ctx, creator, user, 100)) + require.NoError(t, transferFrom(ctx, delegate, creator, delegate, 100)) - checkErc20Allowance(ctx, creator, user, 0) + checkErc20Allowance(ctx, creator, delegate, 0) checkErc20Balance(ctx, creator, solo.Saldo-100) - checkErc20Balance(ctx, user, 100) + checkErc20Balance(ctx, delegate, 100) } -func TestTransferFromFail(t *testing.T) { +func TestTransferFromFailNoDelegate(t *testing.T) { ctx := setupErc20(t) - user := ctx.NewSoloAgent() + delegate := ctx.NewSoloAgent() - require.NoError(t, approve(ctx, creator, user, 100)) + require.NoError(t, approve(ctx, creator, delegate, 100)) - checkErc20Allowance(ctx, creator, user, 100) + checkErc20Allowance(ctx, creator, delegate, 100) checkErc20Balance(ctx, creator, solo.Saldo) - checkErc20Balance(ctx, user, 0) + checkErc20Balance(ctx, delegate, 0) - require.Error(t, transferFrom(ctx, creator, user, 101)) + noDelegate := ctx.NewSoloAgent() + require.Error(t, transferFrom(ctx, noDelegate, creator, delegate, 100)) - checkErc20Allowance(ctx, creator, user, 100) + checkErc20Allowance(ctx, creator, delegate, 100) checkErc20Balance(ctx, creator, solo.Saldo) - checkErc20Balance(ctx, user, 0) + checkErc20Balance(ctx, delegate, 0) + checkErc20Balance(ctx, noDelegate, 0) +} + +func TestTransferFromFailTooMuch(t *testing.T) { + ctx := setupErc20(t) + delegate := ctx.NewSoloAgent() + + require.NoError(t, approve(ctx, creator, delegate, 100)) + + checkErc20Allowance(ctx, creator, delegate, 100) + checkErc20Balance(ctx, creator, solo.Saldo) + checkErc20Balance(ctx, delegate, 0) + + require.Error(t, transferFrom(ctx, delegate, creator, delegate, 101)) + + checkErc20Allowance(ctx, creator, delegate, 100) + checkErc20Balance(ctx, creator, solo.Saldo) + checkErc20Balance(ctx, delegate, 0) } diff --git a/contracts/wasm/erc20/ts/erc20/consts.ts b/contracts/wasm/erc20/ts/erc20/consts.ts index 46fac336fb..6912a924b5 100644 --- a/contracts/wasm/erc20/ts/erc20/consts.ts +++ b/contracts/wasm/erc20/ts/erc20/consts.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export const ScName = "erc20"; export const ScDescription = "ERC-20 PoC for IOTA Smart Contracts"; diff --git a/contracts/wasm/erc20/ts/erc20/contract.ts b/contracts/wasm/erc20/ts/erc20/contract.ts index edfb4700c2..111b9e6733 100644 --- a/contracts/wasm/erc20/ts/erc20/contract.ts +++ b/contracts/wasm/erc20/ts/erc20/contract.ts @@ -5,85 +5,88 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ApproveCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncApprove); - params: sc.MutableApproveParams = new sc.MutableApproveParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncApprove); + params: sc.MutableApproveParams = new sc.MutableApproveParams(); } export class ApproveContext { - params: sc.ImmutableApproveParams = new sc.ImmutableApproveParams(); - state: sc.MutableErc20State = new sc.MutableErc20State(); + events: sc.Erc20Events = new sc.Erc20Events(); + params: sc.ImmutableApproveParams = new sc.ImmutableApproveParams(); + state: sc.MutableErc20State = new sc.MutableErc20State(); } export class InitCall { - func: wasmlib.ScInitFunc = new wasmlib.ScInitFunc(sc.HScName, sc.HFuncInit); - params: sc.MutableInitParams = new sc.MutableInitParams(); + func: wasmlib.ScInitFunc = new wasmlib.ScInitFunc(sc.HScName, sc.HFuncInit); + params: sc.MutableInitParams = new sc.MutableInitParams(); } export class InitContext { - params: sc.ImmutableInitParams = new sc.ImmutableInitParams(); - state: sc.MutableErc20State = new sc.MutableErc20State(); + events: sc.Erc20Events = new sc.Erc20Events(); + params: sc.ImmutableInitParams = new sc.ImmutableInitParams(); + state: sc.MutableErc20State = new sc.MutableErc20State(); } export class TransferCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTransfer); - params: sc.MutableTransferParams = new sc.MutableTransferParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTransfer); + params: sc.MutableTransferParams = new sc.MutableTransferParams(); } export class TransferContext { - params: sc.ImmutableTransferParams = new sc.ImmutableTransferParams(); - state: sc.MutableErc20State = new sc.MutableErc20State(); + events: sc.Erc20Events = new sc.Erc20Events(); + params: sc.ImmutableTransferParams = new sc.ImmutableTransferParams(); + state: sc.MutableErc20State = new sc.MutableErc20State(); } export class TransferFromCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTransferFrom); - params: sc.MutableTransferFromParams = new sc.MutableTransferFromParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTransferFrom); + params: sc.MutableTransferFromParams = new sc.MutableTransferFromParams(); } export class TransferFromContext { - params: sc.ImmutableTransferFromParams = new sc.ImmutableTransferFromParams(); - state: sc.MutableErc20State = new sc.MutableErc20State(); + events: sc.Erc20Events = new sc.Erc20Events(); + params: sc.ImmutableTransferFromParams = new sc.ImmutableTransferFromParams(); + state: sc.MutableErc20State = new sc.MutableErc20State(); } export class AllowanceCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewAllowance); - params: sc.MutableAllowanceParams = new sc.MutableAllowanceParams(); - results: sc.ImmutableAllowanceResults = new sc.ImmutableAllowanceResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewAllowance); + params: sc.MutableAllowanceParams = new sc.MutableAllowanceParams(); + results: sc.ImmutableAllowanceResults = new sc.ImmutableAllowanceResults(); } export class AllowanceContext { - params: sc.ImmutableAllowanceParams = new sc.ImmutableAllowanceParams(); - results: sc.MutableAllowanceResults = new sc.MutableAllowanceResults(); - state: sc.ImmutableErc20State = new sc.ImmutableErc20State(); + params: sc.ImmutableAllowanceParams = new sc.ImmutableAllowanceParams(); + results: sc.MutableAllowanceResults = new sc.MutableAllowanceResults(); + state: sc.ImmutableErc20State = new sc.ImmutableErc20State(); } export class BalanceOfCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewBalanceOf); - params: sc.MutableBalanceOfParams = new sc.MutableBalanceOfParams(); - results: sc.ImmutableBalanceOfResults = new sc.ImmutableBalanceOfResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewBalanceOf); + params: sc.MutableBalanceOfParams = new sc.MutableBalanceOfParams(); + results: sc.ImmutableBalanceOfResults = new sc.ImmutableBalanceOfResults(); } export class BalanceOfContext { - params: sc.ImmutableBalanceOfParams = new sc.ImmutableBalanceOfParams(); - results: sc.MutableBalanceOfResults = new sc.MutableBalanceOfResults(); - state: sc.ImmutableErc20State = new sc.ImmutableErc20State(); + params: sc.ImmutableBalanceOfParams = new sc.ImmutableBalanceOfParams(); + results: sc.MutableBalanceOfResults = new sc.MutableBalanceOfResults(); + state: sc.ImmutableErc20State = new sc.ImmutableErc20State(); } export class TotalSupplyCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTotalSupply); - results: sc.ImmutableTotalSupplyResults = new sc.ImmutableTotalSupplyResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTotalSupply); + results: sc.ImmutableTotalSupplyResults = new sc.ImmutableTotalSupplyResults(); } export class TotalSupplyContext { - results: sc.MutableTotalSupplyResults = new sc.MutableTotalSupplyResults(); - state: sc.ImmutableErc20State = new sc.ImmutableErc20State(); + results: sc.MutableTotalSupplyResults = new sc.MutableTotalSupplyResults(); + state: sc.ImmutableErc20State = new sc.ImmutableErc20State(); } export class ScFuncs { - static approve(ctx: wasmlib.ScFuncCallContext): ApproveCall { let f = new ApproveCall(); f.func.setPtrs(f.params, null); diff --git a/contracts/wasm/erc20/ts/erc20/erc20.ts b/contracts/wasm/erc20/ts/erc20/erc20.ts index ce0b7f6f2e..fbd3d19d3f 100644 --- a/contracts/wasm/erc20/ts/erc20/erc20.ts +++ b/contracts/wasm/erc20/ts/erc20/erc20.ts @@ -14,11 +14,12 @@ import * as sc from "./index"; export function funcApprove(ctx: wasmlib.ScFuncContext, f: sc.ApproveContext): void { let delegation = f.params.delegation().value(); let amount = f.params.amount().value(); - ctx.require(amount > 0, "erc20.approve.fail: wrong 'amount' parameter"); + ctx.require(amount >= 0, "erc20.approve.fail: wrong 'amount' parameter"); // all allowances are in the map under the name of he owner let allowances = f.state.allAllowances().getAllowancesForAgent(ctx.caller()); allowances.getInt64(delegation).setValue(amount); + f.events.approval(amount, ctx.caller(), delegation) } // onInit is a constructor entry point. It initializes the smart contract with the @@ -43,55 +44,62 @@ export function funcInit(ctx: wasmlib.ScFuncContext, f: sc.InitContext): void { } // transfer moves tokens from caller's account to target account +// This function emits the Transfer event. // Input: // - PARAM_ACCOUNT: agentID // - PARAM_AMOUNT: i64 export function funcTransfer(ctx: wasmlib.ScFuncContext, f: sc.TransferContext): void { let amount = f.params.amount().value(); - ctx.require(amount > 0, "erc20.transfer.fail: wrong 'amount' parameter"); + ctx.require(amount >= 0, "erc20.transfer.fail: wrong 'amount' parameter"); let balances = f.state.balances(); - let sourceBalance = balances.getInt64(ctx.caller()); + let sourceAgent = ctx.caller(); + let sourceBalance = balances.getInt64(sourceAgent); ctx.require(sourceBalance.value() >= amount, "erc20.transfer.fail: not enough funds"); - let targetAddr = f.params.account().value(); - let targetBalance = balances.getInt64(targetAddr); + let targetAgent = f.params.account().value(); + let targetBalance = balances.getInt64(targetAgent); let result = targetBalance.value() + amount; - ctx.require(result > 0, "erc20.transfer.fail: overflow"); + ctx.require(result >= 0, "erc20.transfer.fail: overflow"); sourceBalance.setValue(sourceBalance.value() - amount); targetBalance.setValue(targetBalance.value() + amount); + + f.events.transfer(amount, sourceAgent, targetAgent) } // Moves the amount of tokens from sender to recipient using the allowance mechanism. -// Amount is then deducted from the caller’s allowance. This function emits the Transfer event. +// Amount is then deducted from the caller’s allowance. +// This function emits the Transfer event. // Input: // - PARAM_ACCOUNT: agentID the spender // - PARAM_RECIPIENT: agentID the target // - PARAM_AMOUNT: i64 export function funcTransferFrom(ctx: wasmlib.ScFuncContext, f: sc.TransferFromContext): void { // validate parameters - let account = f.params.account().value(); - let recipient = f.params.recipient().value(); let amount = f.params.amount().value(); - ctx.require(amount > 0, "erc20.transferFrom.fail: wrong 'amount' parameter"); + ctx.require(amount >= 0, "erc20.transferFrom.fail: wrong 'amount' parameter"); // allowances are in the map under the name of the account - let allowances = f.state.allAllowances().getAllowancesForAgent(account); - let allowance = allowances.getInt64(recipient); + let sourceAgent = f.params.account().value(); + let allowances = f.state.allAllowances().getAllowancesForAgent(sourceAgent); + let allowance = allowances.getInt64(ctx.caller()); ctx.require(allowance.value() >= amount, "erc20.transferFrom.fail: not enough allowance"); let balances = f.state.balances(); - let sourceBalance = balances.getInt64(account); + let sourceBalance = balances.getInt64(sourceAgent); ctx.require(sourceBalance.value() >= amount, "erc20.transferFrom.fail: not enough funds"); - let recipientBalance = balances.getInt64(recipient); + let targetAgent = f.params.recipient().value(); + let recipientBalance = balances.getInt64(targetAgent); let result = recipientBalance.value() + amount; - ctx.require(result > 0, "erc20.transferFrom.fail: overflow"); + ctx.require(result >= 0, "erc20.transferFrom.fail: overflow"); sourceBalance.setValue(sourceBalance.value() - amount); recipientBalance.setValue(recipientBalance.value() + amount); allowance.setValue(allowance.value() - amount); + + f.events.transfer(amount, sourceAgent, targetAgent) } // the view returns max number of tokens the owner PARAM_ACCOUNT of the account diff --git a/contracts/wasm/erc20/ts/erc20/events.ts b/contracts/wasm/erc20/ts/erc20/events.ts new file mode 100644 index 0000000000..a8dd067940 --- /dev/null +++ b/contracts/wasm/erc20/ts/erc20/events.ts @@ -0,0 +1,27 @@ +// 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 Erc20Events { + + approval(amount: i64, owner: wasmlib.ScAgentID, spender: wasmlib.ScAgentID): void { + new wasmlib.EventEncoder("erc20.approval"). + int64(amount). + agentID(owner). + agentID(spender). + emit(); + } + + transfer(amount: i64, from: wasmlib.ScAgentID, to: wasmlib.ScAgentID): void { + new wasmlib.EventEncoder("erc20.transfer"). + int64(amount). + agentID(from). + agentID(to). + emit(); + } +} diff --git a/contracts/wasm/erc20/ts/erc20/index.ts b/contracts/wasm/erc20/ts/erc20/index.ts index 602bcc4fe7..9411e9de15 100644 --- a/contracts/wasm/erc20/ts/erc20/index.ts +++ b/contracts/wasm/erc20/ts/erc20/index.ts @@ -9,6 +9,7 @@ export * from "./erc20"; export * from "./consts"; export * from "./contract"; +export * from "./events"; export * from "./keys"; export * from "./lib"; export * from "./params"; diff --git a/contracts/wasm/erc20/ts/erc20/keys.ts b/contracts/wasm/erc20/ts/erc20/keys.ts index 94bbb87373..217222f5ce 100644 --- a/contracts/wasm/erc20/ts/erc20/keys.ts +++ b/contracts/wasm/erc20/ts/erc20/keys.ts @@ -5,33 +5,35 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; -export const IdxParamAccount = 0; -export const IdxParamAmount = 1; -export const IdxParamCreator = 2; -export const IdxParamDelegation = 3; -export const IdxParamRecipient = 4; -export const IdxParamSupply = 5; -export const IdxResultAmount = 6; -export const IdxResultSupply = 7; +export const IdxParamAccount = 0; +export const IdxParamAmount = 1; +export const IdxParamCreator = 2; +export const IdxParamDelegation = 3; +export const IdxParamRecipient = 4; +export const IdxParamSupply = 5; + +export const IdxResultAmount = 6; +export const IdxResultSupply = 7; + export const IdxStateAllAllowances = 8; export const IdxStateBalances = 9; export const IdxStateSupply = 10; export let keyMap: string[] = [ - sc.ParamAccount, - sc.ParamAmount, - sc.ParamCreator, - sc.ParamDelegation, - sc.ParamRecipient, - sc.ParamSupply, - sc.ResultAmount, - sc.ResultSupply, - sc.StateAllAllowances, - sc.StateBalances, - sc.StateSupply, + sc.ParamAccount, + sc.ParamAmount, + sc.ParamCreator, + sc.ParamDelegation, + sc.ParamRecipient, + sc.ParamSupply, + sc.ResultAmount, + sc.ResultSupply, + sc.StateAllAllowances, + sc.StateBalances, + sc.StateSupply, ]; export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/erc20/ts/erc20/lib.ts b/contracts/wasm/erc20/ts/erc20/lib.ts index 02027a3e21..7b15f7fde9 100644 --- a/contracts/wasm/erc20/ts/erc20/lib.ts +++ b/contracts/wasm/erc20/ts/erc20/lib.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export function on_call(index: i32): void { @@ -14,13 +14,13 @@ export function on_call(index: i32): void { export function on_load(): void { let exports = new wasmlib.ScExports(); - exports.addFunc(sc.FuncApprove, funcApproveThunk); - exports.addFunc(sc.FuncInit, funcInitThunk); - exports.addFunc(sc.FuncTransfer, funcTransferThunk); + exports.addFunc(sc.FuncApprove, funcApproveThunk); + exports.addFunc(sc.FuncInit, funcInitThunk); + exports.addFunc(sc.FuncTransfer, funcTransferThunk); exports.addFunc(sc.FuncTransferFrom, funcTransferFromThunk); - exports.addView(sc.ViewAllowance, viewAllowanceThunk); - exports.addView(sc.ViewBalanceOf, viewBalanceOfThunk); - exports.addView(sc.ViewTotalSupply, viewTotalSupplyThunk); + exports.addView(sc.ViewAllowance, viewAllowanceThunk); + exports.addView(sc.ViewBalanceOf, viewBalanceOfThunk); + exports.addView(sc.ViewTotalSupply, viewTotalSupplyThunk); for (let i = 0; i < sc.keyMap.length; i++) { sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); @@ -28,78 +28,78 @@ export function on_load(): void { } function funcApproveThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("erc20.funcApprove"); - let f = new sc.ApproveContext(); + ctx.log("erc20.funcApprove"); + let f = new sc.ApproveContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.amount().exists(), "missing mandatory amount") - ctx.require(f.params.delegation().exists(), "missing mandatory delegation") - sc.funcApprove(ctx, f); - ctx.log("erc20.funcApprove ok"); + ctx.require(f.params.amount().exists(), "missing mandatory amount"); + ctx.require(f.params.delegation().exists(), "missing mandatory delegation"); + sc.funcApprove(ctx, f); + ctx.log("erc20.funcApprove ok"); } function funcInitThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("erc20.funcInit"); - let f = new sc.InitContext(); + ctx.log("erc20.funcInit"); + let f = new sc.InitContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.creator().exists(), "missing mandatory creator") - ctx.require(f.params.supply().exists(), "missing mandatory supply") - sc.funcInit(ctx, f); - ctx.log("erc20.funcInit ok"); + ctx.require(f.params.creator().exists(), "missing mandatory creator"); + ctx.require(f.params.supply().exists(), "missing mandatory supply"); + sc.funcInit(ctx, f); + ctx.log("erc20.funcInit ok"); } function funcTransferThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("erc20.funcTransfer"); - let f = new sc.TransferContext(); + ctx.log("erc20.funcTransfer"); + let f = new sc.TransferContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.account().exists(), "missing mandatory account") - ctx.require(f.params.amount().exists(), "missing mandatory amount") - sc.funcTransfer(ctx, f); - ctx.log("erc20.funcTransfer ok"); + ctx.require(f.params.account().exists(), "missing mandatory account"); + ctx.require(f.params.amount().exists(), "missing mandatory amount"); + sc.funcTransfer(ctx, f); + ctx.log("erc20.funcTransfer ok"); } function funcTransferFromThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("erc20.funcTransferFrom"); - let f = new sc.TransferFromContext(); + ctx.log("erc20.funcTransferFrom"); + let f = new sc.TransferFromContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.account().exists(), "missing mandatory account") - ctx.require(f.params.amount().exists(), "missing mandatory amount") - ctx.require(f.params.recipient().exists(), "missing mandatory recipient") - sc.funcTransferFrom(ctx, f); - ctx.log("erc20.funcTransferFrom ok"); + ctx.require(f.params.account().exists(), "missing mandatory account"); + ctx.require(f.params.amount().exists(), "missing mandatory amount"); + ctx.require(f.params.recipient().exists(), "missing mandatory recipient"); + sc.funcTransferFrom(ctx, f); + ctx.log("erc20.funcTransferFrom ok"); } function viewAllowanceThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("erc20.viewAllowance"); - let f = new sc.AllowanceContext(); + ctx.log("erc20.viewAllowance"); + let f = new sc.AllowanceContext(); 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.account().exists(), "missing mandatory account") - ctx.require(f.params.delegation().exists(), "missing mandatory delegation") - sc.viewAllowance(ctx, f); - ctx.log("erc20.viewAllowance ok"); + ctx.require(f.params.account().exists(), "missing mandatory account"); + ctx.require(f.params.delegation().exists(), "missing mandatory delegation"); + sc.viewAllowance(ctx, f); + ctx.log("erc20.viewAllowance ok"); } function viewBalanceOfThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("erc20.viewBalanceOf"); - let f = new sc.BalanceOfContext(); + ctx.log("erc20.viewBalanceOf"); + let f = new sc.BalanceOfContext(); 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.account().exists(), "missing mandatory account") - sc.viewBalanceOf(ctx, f); - ctx.log("erc20.viewBalanceOf ok"); + ctx.require(f.params.account().exists(), "missing mandatory account"); + sc.viewBalanceOf(ctx, f); + ctx.log("erc20.viewBalanceOf ok"); } function viewTotalSupplyThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("erc20.viewTotalSupply"); - let f = new sc.TotalSupplyContext(); + ctx.log("erc20.viewTotalSupply"); + let f = new sc.TotalSupplyContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewTotalSupply(ctx, f); - ctx.log("erc20.viewTotalSupply ok"); + sc.viewTotalSupply(ctx, f); + ctx.log("erc20.viewTotalSupply ok"); } diff --git a/contracts/wasm/erc20/ts/erc20/params.ts b/contracts/wasm/erc20/ts/erc20/params.ts index 23c35d10da..0fb5a88612 100644 --- a/contracts/wasm/erc20/ts/erc20/params.ts +++ b/contracts/wasm/erc20/ts/erc20/params.ts @@ -5,137 +5,125 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxParamAmount]); + } delegation(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); + } } 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, sc.idxMap[sc.IdxParamAmount]); + } delegation(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); + } } export class ImmutableInitParams extends wasmlib.ScMapID { - creator(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamCreator]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamCreator]); + } supply(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamSupply]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamSupply]); + } } export class MutableInitParams extends wasmlib.ScMapID { - creator(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamCreator]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamCreator]); + } supply(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamSupply]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamSupply]); + } } 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, sc.idxMap[sc.IdxParamAccount]); + } amount(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + } } 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, sc.idxMap[sc.IdxParamAccount]); + } amount(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + } } 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, sc.idxMap[sc.IdxParamAccount]); + } amount(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + } recipient(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamRecipient]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamRecipient]); + } } 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, sc.idxMap[sc.IdxParamAccount]); + } amount(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamAmount]); + } recipient(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamRecipient]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamRecipient]); + } } 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, sc.idxMap[sc.IdxParamAccount]); + } delegation(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); + } } 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, sc.idxMap[sc.IdxParamAccount]); + } delegation(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamDelegation]); + } } 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, sc.idxMap[sc.IdxParamAccount]); + } } 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, sc.idxMap[sc.IdxParamAccount]); + } } diff --git a/contracts/wasm/erc20/ts/erc20/results.ts b/contracts/wasm/erc20/ts/erc20/results.ts index 26435174d4..ceab965434 100644 --- a/contracts/wasm/erc20/ts/erc20/results.ts +++ b/contracts/wasm/erc20/ts/erc20/results.ts @@ -5,47 +5,41 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxResultAmount]); + } } 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, sc.idxMap[sc.IdxResultAmount]); + } } 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, sc.idxMap[sc.IdxResultAmount]); + } } 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, sc.idxMap[sc.IdxResultAmount]); + } } 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, sc.idxMap[sc.IdxResultSupply]); + } } 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, sc.idxMap[sc.IdxResultSupply]); + } } diff --git a/contracts/wasm/erc20/ts/erc20/state.ts b/contracts/wasm/erc20/ts/erc20/state.ts index abca138678..132fad2c0b 100644 --- a/contracts/wasm/erc20/ts/erc20/state.ts +++ b/contracts/wasm/erc20/ts/erc20/state.ts @@ -5,11 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class MapAgentIDToImmutableAllowancesForAgent { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -22,31 +22,30 @@ 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); - return new sc.MapAgentIDToImmutableAllowancesForAgent(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateAllAllowances], wasmlib.TYPE_MAP); + return new sc.MapAgentIDToImmutableAllowancesForAgent(mapID); + } balances(): sc.MapAgentIDToImmutableInt64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBalances], wasmlib.TYPE_MAP); - return new sc.MapAgentIDToImmutableInt64(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBalances], 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, sc.idxMap[sc.IdxStateSupply]); + } } export class MapAgentIDToMutableAllowancesForAgent { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getAllowancesForAgent(key: wasmlib.ScAgentID): sc.MutableAllowancesForAgent { @@ -56,18 +55,17 @@ export class MapAgentIDToMutableAllowancesForAgent { } export class MutableErc20State extends wasmlib.ScMapID { - allAllowances(): sc.MapAgentIDToMutableAllowancesForAgent { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateAllAllowances], wasmlib.TYPE_MAP); - return new sc.MapAgentIDToMutableAllowancesForAgent(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateAllAllowances], wasmlib.TYPE_MAP); + return new sc.MapAgentIDToMutableAllowancesForAgent(mapID); + } balances(): sc.MapAgentIDToMutableInt64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBalances], wasmlib.TYPE_MAP); - return new sc.MapAgentIDToMutableInt64(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBalances], 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, sc.idxMap[sc.IdxStateSupply]); + } } diff --git a/contracts/wasm/erc20/ts/erc20/typedefs.ts b/contracts/wasm/erc20/ts/erc20/typedefs.ts index 2d2c7ef115..2d09733fac 100644 --- a/contracts/wasm/erc20/ts/erc20/typedefs.ts +++ b/contracts/wasm/erc20/ts/erc20/typedefs.ts @@ -5,11 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class MapAgentIDToImmutableInt64 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -24,14 +24,14 @@ export class ImmutableAllowancesForAgent extends MapAgentIDToImmutableInt64 { }; export class MapAgentIDToMutableInt64 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getInt64(key: wasmlib.ScAgentID): wasmlib.ScMutableInt64 { diff --git a/contracts/wasm/erc721/Cargo.toml b/contracts/wasm/erc721/Cargo.toml new file mode 100644 index 0000000000..8485099a71 --- /dev/null +++ b/contracts/wasm/erc721/Cargo.toml @@ -0,0 +1,26 @@ +# Copyright 2020 IOTA Stiftung +# SPDX-License-Identifier: Apache-2.0 + +[package] +name = "erc721" +description = "ERC-721 NFT PoC for IOTA Smart Contracts" +license = "Apache-2.0" +version = "0.1.0" +authors = ["John Doe "] +edition = "2018" +repository = "https://github.com/iotaledger/wasp" + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +default = ["console_error_panic_hook"] + +[dependencies] +wasmlib = { path = "../../../packages/vm/wasmlib" } +#wasmlib = { git = "https://github.com/iotaledger/wasp", branch = "develop" } +console_error_panic_hook = { version = "0.1.6", optional = true } +wee_alloc = { version = "0.4.5", optional = true } + +[dev-dependencies] +wasm-bindgen-test = "0.3.13" diff --git a/contracts/wasm/erc721/LICENSE b/contracts/wasm/erc721/LICENSE new file mode 100644 index 0000000000..d22c90e122 --- /dev/null +++ b/contracts/wasm/erc721/LICENSE @@ -0,0 +1,216 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2019 IOTA Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +For the errors package: + +Copyright (c) 2015, Dave Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/contracts/wasm/erc721/README.md b/contracts/wasm/erc721/README.md new file mode 100644 index 0000000000..01fbc435e3 --- /dev/null +++ b/contracts/wasm/erc721/README.md @@ -0,0 +1,85 @@ +# ERC721 as IOTA smart contract + +### Deploy new chain (optional) + +```bash +$ ./wasp-cli chain deploy --committee=0 --quorum=1 --chain=wasptest --description="ArgentinaHub" +# You can replace the amount of committees and quorum by your needs +``` + +### Deposit IOTA tokens to the chain +```bash +$ ./wasp-cli chain deposit IOTA:1000 +``` + +### Deploy contract +```bash +./wasp-cli --verbose chain deploy-contract wasmtime erc721 "Argentina Hub" contracts/wasm/erc721/pkg/nft_bg.wasm string n string ArgHub string s string ARH +# n: Name +# s: Symbol +``` + +### Mint new erc721 +```bash +./wasp-cli --verbose chain post-request erc721 mint string tokenid int +string tokenuri string +#Example +# = 73798465 +# = "" +``` + +### Transfer ownership of the erc721 +```bash +./wasp-cli --verbose chain post-request erc721 transferFrom string from agentid string to agentid string tokenid int +# Example +# = A/1urERbzXL1iraoW2jMvkLdFuMmPS711BYtA8u4L6sS53::00000000 +# = A/111111111111111111111111111111111::00000000 +# = 73798465 +``` + +### Approves another agentid to transfer the given token +```bash +./wasp-cli --verbose chain post-request erc721 approve string to agentid string tokenid int +# Example +# = A/1urERbzXL1iraoW2jMvkLdFuMmPS711BYtA8u4L6sS53::00000000 +# = 73798465 +``` + +### Balance Of +```bash +./wasp-cli chain call-view erc721 balanceOf string account agentid | ./wasp-cli decode string amount int +# Example +# = A/1urERbzXL1iraoW2jMvkLdFuMmPS711BYtA8u4L6sS53::00000000 +``` + +### Name of contract +```bash +./wasp-cli chain call-view erc721 name | ./wasp-cli decode string name string +``` + +### Symbol of contract +```bash +./wasp-cli chain call-view erc721 name | ./wasp-cli decode string name string +``` + +### Check agent id if it's approved (1 = true ; 0 = false) +```bash +./wasp-cli chain call-view erc721 isApproved string tokenid int string operator agentid | ./wasp-cli decode string approved int +# Example +# = 73798465 +# = A/12uApMh48Nq9EZGB8idco4W5NpZtyu6vv4sXpZuP5FUKs::00000000 +``` + +### Get token URI +```bash +./wasp-cli chain call-view erc721 tokenURI string tokenid int | ./wasp-cli decode string uri string +# Example +# = 73798465 +``` + +### Set approval for all (1 = true ; 0 = false) +```bash +./wasp-cli --verbose chain post-request erc721 setApprovalForAll string operator agentid string approved int 1 +# Example +# = A/12uApMh48Nq9EZGB8idco4W5NpZtyu6vv4sXpZuP5FUKs::00000000 +``` \ No newline at end of file diff --git a/contracts/wasm/erc721/go/erc721/consts.go b/contracts/wasm/erc721/go/erc721/consts.go new file mode 100644 index 0000000000..f6d90db059 --- /dev/null +++ b/contracts/wasm/erc721/go/erc721/consts.go @@ -0,0 +1,82 @@ +// 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 erc721 + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +const ( + ScName = "erc721" + ScDescription = "ERC-721 NFT PoC for IOTA Smart Contracts" + HScName = wasmlib.ScHname(0xd967c216) +) + +const ( + ParamApproval = "approval" + ParamApproved = "approved" + ParamData = "data" + ParamFrom = "from" + ParamName = "n" + ParamOperator = "operator" + ParamOwner = "owner" + ParamSymbol = "s" + ParamTo = "to" + ParamTokenID = "tokenID" +) + +const ( + ResultAmount = "amount" + ResultApproval = "approval" + ResultApproved = "approved" + ResultName = "name" + ResultOwner = "owner" + ResultSymbol = "symbol" + ResultTokenURI = "tokenURI" +) + +const ( + StateApprovedAccounts = "approvedAccounts" + StateApprovedOperators = "approvedOperators" + StateBalances = "balances" + StateName = "name" + StateOwners = "owners" + StateSymbol = "symbol" +) + +const ( + FuncApprove = "approve" + FuncBurn = "burn" + FuncInit = "init" + FuncMint = "mint" + FuncSafeTransferFrom = "safeTransferFrom" + FuncSetApprovalForAll = "setApprovalForAll" + FuncTransferFrom = "transferFrom" + ViewBalanceOf = "balanceOf" + ViewGetApproved = "getApproved" + ViewIsApprovedForAll = "isApprovedForAll" + ViewName = "name" + ViewOwnerOf = "ownerOf" + ViewSymbol = "symbol" + ViewTokenURI = "tokenURI" +) + +const ( + HFuncApprove = wasmlib.ScHname(0xa0661268) + HFuncBurn = wasmlib.ScHname(0x7bc1efb1) + HFuncInit = wasmlib.ScHname(0x1f44d644) + HFuncMint = wasmlib.ScHname(0xa29addcf) + HFuncSafeTransferFrom = wasmlib.ScHname(0x130ce158) + HFuncSetApprovalForAll = wasmlib.ScHname(0xb8d8c776) + HFuncTransferFrom = wasmlib.ScHname(0xd5e0a602) + HViewBalanceOf = wasmlib.ScHname(0x67ef8df4) + HViewGetApproved = wasmlib.ScHname(0xbe34b6ba) + HViewIsApprovedForAll = wasmlib.ScHname(0x3251b0f0) + HViewName = wasmlib.ScHname(0x0df7da3a) + HViewOwnerOf = wasmlib.ScHname(0x1246f5ad) + HViewSymbol = wasmlib.ScHname(0x3e93d19b) + HViewTokenURI = wasmlib.ScHname(0x4e1a7397) +) diff --git a/contracts/wasm/erc721/go/erc721/contract.go b/contracts/wasm/erc721/go/erc721/contract.go new file mode 100644 index 0000000000..258858e677 --- /dev/null +++ b/contracts/wasm/erc721/go/erc721/contract.go @@ -0,0 +1,173 @@ +// 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 erc721 + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type ApproveCall struct { + Func *wasmlib.ScFunc + Params MutableApproveParams +} + +type BurnCall struct { + Func *wasmlib.ScFunc + Params MutableBurnParams +} + +type InitCall struct { + Func *wasmlib.ScInitFunc + Params MutableInitParams +} + +type MintCall struct { + Func *wasmlib.ScFunc + Params MutableMintParams +} + +type SafeTransferFromCall struct { + Func *wasmlib.ScFunc + Params MutableSafeTransferFromParams +} + +type SetApprovalForAllCall struct { + Func *wasmlib.ScFunc + Params MutableSetApprovalForAllParams +} + +type TransferFromCall struct { + Func *wasmlib.ScFunc + Params MutableTransferFromParams +} + +type BalanceOfCall struct { + Func *wasmlib.ScView + Params MutableBalanceOfParams + Results ImmutableBalanceOfResults +} + +type GetApprovedCall struct { + Func *wasmlib.ScView + Params MutableGetApprovedParams + Results ImmutableGetApprovedResults +} + +type IsApprovedForAllCall struct { + Func *wasmlib.ScView + Params MutableIsApprovedForAllParams + Results ImmutableIsApprovedForAllResults +} + +type NameCall struct { + Func *wasmlib.ScView + Results ImmutableNameResults +} + +type OwnerOfCall struct { + Func *wasmlib.ScView + Params MutableOwnerOfParams + Results ImmutableOwnerOfResults +} + +type SymbolCall struct { + Func *wasmlib.ScView + Results ImmutableSymbolResults +} + +type TokenURICall struct { + Func *wasmlib.ScView + Params MutableTokenURIParams + Results ImmutableTokenURIResults +} + +type Funcs struct{} + +var ScFuncs Funcs + +func (sc Funcs) Approve(ctx wasmlib.ScFuncCallContext) *ApproveCall { + f := &ApproveCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncApprove)} + f.Func.SetPtrs(&f.Params.id, nil) + return f +} + +func (sc Funcs) Burn(ctx wasmlib.ScFuncCallContext) *BurnCall { + f := &BurnCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncBurn)} + f.Func.SetPtrs(&f.Params.id, nil) + return f +} + +func (sc Funcs) Init(ctx wasmlib.ScFuncCallContext) *InitCall { + f := &InitCall{Func: wasmlib.NewScInitFunc(ctx, HScName, HFuncInit, keyMap[:], idxMap[:])} + f.Func.SetPtrs(&f.Params.id, nil) + return f +} + +func (sc Funcs) Mint(ctx wasmlib.ScFuncCallContext) *MintCall { + f := &MintCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncMint)} + f.Func.SetPtrs(&f.Params.id, nil) + return f +} + +func (sc Funcs) SafeTransferFrom(ctx wasmlib.ScFuncCallContext) *SafeTransferFromCall { + f := &SafeTransferFromCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncSafeTransferFrom)} + f.Func.SetPtrs(&f.Params.id, nil) + return f +} + +func (sc Funcs) SetApprovalForAll(ctx wasmlib.ScFuncCallContext) *SetApprovalForAllCall { + f := &SetApprovalForAllCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncSetApprovalForAll)} + f.Func.SetPtrs(&f.Params.id, nil) + return f +} + +func (sc Funcs) TransferFrom(ctx wasmlib.ScFuncCallContext) *TransferFromCall { + f := &TransferFromCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncTransferFrom)} + f.Func.SetPtrs(&f.Params.id, nil) + return f +} + +func (sc Funcs) BalanceOf(ctx wasmlib.ScViewCallContext) *BalanceOfCall { + f := &BalanceOfCall{Func: wasmlib.NewScView(ctx, HScName, HViewBalanceOf)} + f.Func.SetPtrs(&f.Params.id, &f.Results.id) + return f +} + +func (sc Funcs) GetApproved(ctx wasmlib.ScViewCallContext) *GetApprovedCall { + f := &GetApprovedCall{Func: wasmlib.NewScView(ctx, HScName, HViewGetApproved)} + f.Func.SetPtrs(&f.Params.id, &f.Results.id) + return f +} + +func (sc Funcs) IsApprovedForAll(ctx wasmlib.ScViewCallContext) *IsApprovedForAllCall { + f := &IsApprovedForAllCall{Func: wasmlib.NewScView(ctx, HScName, HViewIsApprovedForAll)} + f.Func.SetPtrs(&f.Params.id, &f.Results.id) + return f +} + +func (sc Funcs) Name(ctx wasmlib.ScViewCallContext) *NameCall { + f := &NameCall{Func: wasmlib.NewScView(ctx, HScName, HViewName)} + f.Func.SetPtrs(nil, &f.Results.id) + return f +} + +func (sc Funcs) OwnerOf(ctx wasmlib.ScViewCallContext) *OwnerOfCall { + f := &OwnerOfCall{Func: wasmlib.NewScView(ctx, HScName, HViewOwnerOf)} + f.Func.SetPtrs(&f.Params.id, &f.Results.id) + return f +} + +func (sc Funcs) Symbol(ctx wasmlib.ScViewCallContext) *SymbolCall { + f := &SymbolCall{Func: wasmlib.NewScView(ctx, HScName, HViewSymbol)} + f.Func.SetPtrs(nil, &f.Results.id) + return f +} + +func (sc Funcs) TokenURI(ctx wasmlib.ScViewCallContext) *TokenURICall { + f := &TokenURICall{Func: wasmlib.NewScView(ctx, HScName, HViewTokenURI)} + f.Func.SetPtrs(&f.Params.id, &f.Results.id) + return f +} diff --git a/contracts/wasm/erc721/go/erc721/erc721.go b/contracts/wasm/erc721/go/erc721/erc721.go new file mode 100644 index 0000000000..c77513c27e --- /dev/null +++ b/contracts/wasm/erc721/go/erc721/erc721.go @@ -0,0 +1,244 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package erc721 + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +// Follows ERC-721 standard as closely as possible +// https//eips.Ethereum.Org/EIPS/eip-721 +// Notable changes w.R.T. ERC-721 +// - tokenID is Hash instead of int256 +// - balance amounts are Uint64 instead of int256 +// - all address accounts are replaced with AgentID accounts +// - for consistency and to reduce confusion +// use 'approved' when it is an AgentID +// use 'approval' when it is a Bool + +// set the required base URI, to which the base58 encoded token ID will be concatenated +const baseURI = "my/special/base/uri/" + +var zero = wasmlib.ScAgentID{} + +/////////////////////////// HELPER FUNCTIONS //////////////////////////// + +// checks if caller is owner, or one of its delegated operators +func canOperate(state MutableErc721State, caller, owner wasmlib.ScAgentID) bool { + if caller == owner { + return true + } + + operators := state.ApprovedOperators().GetOperators(owner) + return operators.GetBool(caller).Value() +} + +// checks if caller is owner, or one of its delegated operators, or approved account for tokenID +func canTransfer(state MutableErc721State, caller, owner wasmlib.ScAgentID, tokenID wasmlib.ScHash) bool { + if canOperate(state, caller, owner) { + return true + } + + controller := state.ApprovedAccounts().GetAgentID(tokenID) + return controller.Value() == caller +} + +// common code for safeTransferFrom and transferFrom +func transfer(ctx wasmlib.ScFuncContext, state MutableErc721State, from, to wasmlib.ScAgentID, tokenID wasmlib.ScHash) { + tokenOwner := state.Owners().GetAgentID(tokenID) + ctx.Require(tokenOwner.Exists(), "tokenID does not exist") + + owner := tokenOwner.Value() + ctx.Require(canTransfer(state, ctx.Caller(), owner, tokenID), + "not owner, operator, or approved") + + ctx.Require(owner == from, "from is not owner") + // TODO ctx.Require(to == , "invalid 'to' agentid") + + balanceFrom := state.Balances().GetUint64(from) + balanceTo := state.Balances().GetUint64(to) + + balanceFrom.SetValue(balanceFrom.Value() - 1) + balanceTo.SetValue(balanceTo.Value() + 1) + + tokenOwner.SetValue(to) + + events := Erc721Events{} + // TODO should probably clear this entry, but for now just set to zero + currentApproved := state.ApprovedAccounts().GetAgentID(tokenID) + if currentApproved.Exists() { + currentApproved.Delete() + events.Approval(zero, owner, tokenID) + } + + events.Transfer(from, to, tokenID) +} + +/////////////////////////// SC FUNCS //////////////////////////// + +// Gives permission to to to transfer tokenID token to another account. +// The approval is cleared when optional approval account is omitted. +// The approval will be cleared when the token is transferred. +func funcApprove(ctx wasmlib.ScFuncContext, f *ApproveContext) { + tokenID := f.Params.TokenID().Value() + tokenOwner := f.State.Owners().GetAgentID(tokenID) + ctx.Require(tokenOwner.Exists(), "tokenID does not exist") + owner := tokenOwner.Value() + ctx.Require(canOperate(f.State, ctx.Caller(), owner), "not owner or operator") + + approved := f.Params.Approved() + if !approved.Exists() { + // remove approval if it exists + currentApproved := f.State.ApprovedAccounts().GetAgentID(tokenID) + if currentApproved.Exists() { + currentApproved.Delete() + f.Events.Approval(zero, owner, tokenID) + } + return + } + + account := approved.Value() + ctx.Require(owner != account, "approved account equals owner") + + f.State.ApprovedAccounts().GetAgentID(tokenID).SetValue(account) + f.Events.Approval(account, owner, tokenID) +} + +// Destroys tokenID. The approval is cleared when the token is burned. +func funcBurn(ctx wasmlib.ScFuncContext, f *BurnContext) { + tokenID := f.Params.TokenID().Value() + owner := f.State.Owners().GetAgentID(tokenID).Value() + ctx.Require(owner != zero, "tokenID does not exist") + ctx.Require(ctx.Caller() == owner, "caller is not owner") + + // remove approval if it exists + currentApproved := f.State.ApprovedAccounts().GetAgentID(tokenID) + if currentApproved.Exists() { + currentApproved.Delete() + f.Events.Approval(zero, owner, tokenID) + } + + balance := f.State.Balances().GetUint64(owner) + balance.SetValue(balance.Value() - 1) + + f.State.Owners().GetAgentID(tokenID).Delete() + f.Events.Transfer(owner, zero, tokenID) +} + +// Initializes the contract by setting a name and a symbol to the token collection. +func funcInit(ctx wasmlib.ScFuncContext, f *InitContext) { + name := f.Params.Name().Value() + symbol := f.Params.Symbol().Value() + + f.State.Name().SetValue(name) + f.State.Symbol().SetValue(symbol) + + f.Events.Init(name, symbol) +} + +// Mints tokenID and transfers it to caller as new owner. +func funcMint(ctx wasmlib.ScFuncContext, f *MintContext) { + tokenID := f.Params.TokenID().Value() + tokenOwner := f.State.Owners().GetAgentID(tokenID) + ctx.Require(!tokenOwner.Exists(), "tokenID already minted") + + owner := ctx.Caller() + tokenOwner.SetValue(owner) + balance := f.State.Balances().GetUint64(owner) + balance.SetValue(balance.Value() + 1) + + f.Events.Transfer(zero, owner, tokenID) + //if !owner.IsAddress() { + // // TODO interpret to as SC address and call its onERC721Received() func + //} +} + +// Safely transfers tokenID token from from to to, checking first that contract +// recipients are aware of the ERC721 protocol to prevent tokens from being forever locked. +func funcSafeTransferFrom(ctx wasmlib.ScFuncContext, f *SafeTransferFromContext) { + from := f.Params.From().Value() + to := f.Params.To().Value() + tokenID := f.Params.TokenID().Value() + transfer(ctx, f.State, from, to, tokenID) + //if !to.IsAddress() { + // // TODO interpret to as SC address and call its onERC721Received() func + //} +} + +// Approve or remove operator as an operator for the caller. +func funcSetApprovalForAll(ctx wasmlib.ScFuncContext, f *SetApprovalForAllContext) { + owner := ctx.Caller() + operator := f.Params.Operator().Value() + ctx.Require(owner != operator, "owner equals operator") + + approval := f.Params.Approval().Value() + operatorsForCaller := f.State.ApprovedOperators().GetOperators(owner) + operatorsForCaller.GetBool(operator).SetValue(approval) + + f.Events.ApprovalForAll(approval, operator, owner) +} + +// Transfers tokenID token from from to to. +func funcTransferFrom(ctx wasmlib.ScFuncContext, f *TransferFromContext) { + from := f.Params.From().Value() + to := f.Params.To().Value() + tokenID := f.Params.TokenID().Value() + transfer(ctx, f.State, from, to, tokenID) +} + +/////////////////////////// SC VIEWS //////////////////////////// + +// Returns the number of tokens in owner's account if the owner exists. +func viewBalanceOf(ctx wasmlib.ScViewContext, f *BalanceOfContext) { + owner := f.Params.Owner().Value() + balance := f.State.Balances().GetUint64(owner) + if balance.Exists() { + f.Results.Amount().SetValue(balance.Value()) + } +} + +// Returns the approved account for tokenID token if there is one. +func viewGetApproved(ctx wasmlib.ScViewContext, f *GetApprovedContext) { + tokenID := f.Params.TokenID().Value() + approved := f.State.ApprovedAccounts().GetAgentID(tokenID) + if approved.Exists() { + f.Results.Approved().SetValue(approved.Value()) + } +} + +// Returns if the operator is allowed to manage all the assets of owner. +func viewIsApprovedForAll(ctx wasmlib.ScViewContext, f *IsApprovedForAllContext) { + owner := f.Params.Owner().Value() + operator := f.Params.Operator().Value() + operators := f.State.ApprovedOperators().GetOperators(owner) + approval := operators.GetBool(operator) + if approval.Exists() { + f.Results.Approval().SetValue(approval.Value()) + } +} + +// Returns the token collection name. +func viewName(ctx wasmlib.ScViewContext, f *NameContext) { + f.Results.Name().SetValue(f.State.Name().Value()) +} + +// Returns the owner of the tokenID token if the token exists. +func viewOwnerOf(ctx wasmlib.ScViewContext, f *OwnerOfContext) { + tokenID := f.Params.TokenID().Value() + owner := f.State.Owners().GetAgentID(tokenID) + if owner.Exists() { + f.Results.Owner().SetValue(owner.Value()) + } +} + +// Returns the token collection symbol. +func viewSymbol(ctx wasmlib.ScViewContext, f *SymbolContext) { + f.Results.Symbol().SetValue(f.State.Symbol().Value()) +} + +// Returns the Uniform Resource Identifier (URI) for tokenID token if the token exists. +func viewTokenURI(ctx wasmlib.ScViewContext, f *TokenURIContext) { + tokenID := f.Params.TokenID() + if tokenID.Exists() { + f.Results.TokenURI().SetValue(baseURI + tokenID.String()) + } +} diff --git a/contracts/wasm/erc721/go/erc721/events.go b/contracts/wasm/erc721/go/erc721/events.go new file mode 100644 index 0000000000..ab863646b5 --- /dev/null +++ b/contracts/wasm/erc721/go/erc721/events.go @@ -0,0 +1,52 @@ +// 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 + +//nolint:gocritic +package erc721 + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type Erc721Events struct{} + +func (e Erc721Events) Approval(approved wasmlib.ScAgentID, owner wasmlib.ScAgentID, tokenID wasmlib.ScHash) { + wasmlib.NewEventEncoder("erc721.approval"). + AgentID(approved). + AgentID(owner). + Hash(tokenID). + Emit() +} + +func (e Erc721Events) ApprovalForAll(approval bool, operator wasmlib.ScAgentID, owner wasmlib.ScAgentID) { + wasmlib.NewEventEncoder("erc721.approvalForAll"). + Bool(approval). + AgentID(operator). + AgentID(owner). + Emit() +} + +func (e Erc721Events) Init(name string, symbol string) { + wasmlib.NewEventEncoder("erc721.init"). + String(name). + String(symbol). + Emit() +} + +func (e Erc721Events) Mint(balance uint64, owner wasmlib.ScAgentID, tokenID wasmlib.ScHash) { + wasmlib.NewEventEncoder("erc721.mint"). + Uint64(balance). + AgentID(owner). + Hash(tokenID). + Emit() +} + +func (e Erc721Events) Transfer(from wasmlib.ScAgentID, to wasmlib.ScAgentID, tokenID wasmlib.ScHash) { + wasmlib.NewEventEncoder("erc721.transfer"). + AgentID(from). + AgentID(to). + Hash(tokenID). + Emit() +} diff --git a/contracts/wasm/erc721/go/erc721/keys.go b/contracts/wasm/erc721/go/erc721/keys.go new file mode 100644 index 0000000000..e9a054932e --- /dev/null +++ b/contracts/wasm/erc721/go/erc721/keys.go @@ -0,0 +1,68 @@ +// 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 erc721 + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +const ( + IdxParamApproval = 0 + IdxParamApproved = 1 + IdxParamData = 2 + IdxParamFrom = 3 + IdxParamName = 4 + IdxParamOperator = 5 + IdxParamOwner = 6 + IdxParamSymbol = 7 + IdxParamTo = 8 + IdxParamTokenID = 9 + + IdxResultAmount = 10 + IdxResultApproval = 11 + IdxResultApproved = 12 + IdxResultName = 13 + IdxResultOwner = 14 + IdxResultSymbol = 15 + IdxResultTokenURI = 16 + + IdxStateApprovedAccounts = 17 + IdxStateApprovedOperators = 18 + IdxStateBalances = 19 + IdxStateName = 20 + IdxStateOwners = 21 + IdxStateSymbol = 22 +) + +const keyMapLen = 23 + +var keyMap = [keyMapLen]wasmlib.Key{ + ParamApproval, + ParamApproved, + ParamData, + ParamFrom, + ParamName, + ParamOperator, + ParamOwner, + ParamSymbol, + ParamTo, + ParamTokenID, + ResultAmount, + ResultApproval, + ResultApproved, + ResultName, + ResultOwner, + ResultSymbol, + ResultTokenURI, + StateApprovedAccounts, + StateApprovedOperators, + StateBalances, + StateName, + StateOwners, + StateSymbol, +} + +var idxMap [keyMapLen]wasmlib.Key32 diff --git a/contracts/wasm/erc721/go/erc721/lib.go b/contracts/wasm/erc721/go/erc721/lib.go new file mode 100644 index 0000000000..60498f3a9e --- /dev/null +++ b/contracts/wasm/erc721/go/erc721/lib.go @@ -0,0 +1,344 @@ +// 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 erc721 + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +func OnLoad() { + exports := wasmlib.NewScExports() + exports.AddFunc(FuncApprove, funcApproveThunk) + exports.AddFunc(FuncBurn, funcBurnThunk) + exports.AddFunc(FuncInit, funcInitThunk) + exports.AddFunc(FuncMint, funcMintThunk) + exports.AddFunc(FuncSafeTransferFrom, funcSafeTransferFromThunk) + exports.AddFunc(FuncSetApprovalForAll, funcSetApprovalForAllThunk) + exports.AddFunc(FuncTransferFrom, funcTransferFromThunk) + exports.AddView(ViewBalanceOf, viewBalanceOfThunk) + exports.AddView(ViewGetApproved, viewGetApprovedThunk) + exports.AddView(ViewIsApprovedForAll, viewIsApprovedForAllThunk) + exports.AddView(ViewName, viewNameThunk) + exports.AddView(ViewOwnerOf, viewOwnerOfThunk) + exports.AddView(ViewSymbol, viewSymbolThunk) + exports.AddView(ViewTokenURI, viewTokenURIThunk) + + for i, key := range keyMap { + idxMap[i] = key.KeyID() + } +} + +type ApproveContext struct { + Events Erc721Events + Params ImmutableApproveParams + State MutableErc721State +} + +func funcApproveThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("erc721.funcApprove") + f := &ApproveContext{ + Params: ImmutableApproveParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + State: MutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.TokenID().Exists(), "missing mandatory tokenID") + funcApprove(ctx, f) + ctx.Log("erc721.funcApprove ok") +} + +type BurnContext struct { + Events Erc721Events + Params ImmutableBurnParams + State MutableErc721State +} + +func funcBurnThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("erc721.funcBurn") + f := &BurnContext{ + Params: ImmutableBurnParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + State: MutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.TokenID().Exists(), "missing mandatory tokenID") + funcBurn(ctx, f) + ctx.Log("erc721.funcBurn ok") +} + +type InitContext struct { + Events Erc721Events + Params ImmutableInitParams + State MutableErc721State +} + +func funcInitThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("erc721.funcInit") + f := &InitContext{ + Params: ImmutableInitParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + State: MutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.Name().Exists(), "missing mandatory name") + ctx.Require(f.Params.Symbol().Exists(), "missing mandatory symbol") + funcInit(ctx, f) + ctx.Log("erc721.funcInit ok") +} + +type MintContext struct { + Events Erc721Events + Params ImmutableMintParams + State MutableErc721State +} + +func funcMintThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("erc721.funcMint") + f := &MintContext{ + Params: ImmutableMintParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + State: MutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.TokenID().Exists(), "missing mandatory tokenID") + funcMint(ctx, f) + ctx.Log("erc721.funcMint ok") +} + +type SafeTransferFromContext struct { + Events Erc721Events + Params ImmutableSafeTransferFromParams + State MutableErc721State +} + +func funcSafeTransferFromThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("erc721.funcSafeTransferFrom") + f := &SafeTransferFromContext{ + Params: ImmutableSafeTransferFromParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + State: MutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.From().Exists(), "missing mandatory from") + ctx.Require(f.Params.To().Exists(), "missing mandatory to") + ctx.Require(f.Params.TokenID().Exists(), "missing mandatory tokenID") + funcSafeTransferFrom(ctx, f) + ctx.Log("erc721.funcSafeTransferFrom ok") +} + +type SetApprovalForAllContext struct { + Events Erc721Events + Params ImmutableSetApprovalForAllParams + State MutableErc721State +} + +func funcSetApprovalForAllThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("erc721.funcSetApprovalForAll") + f := &SetApprovalForAllContext{ + Params: ImmutableSetApprovalForAllParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + State: MutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.Approval().Exists(), "missing mandatory approval") + ctx.Require(f.Params.Operator().Exists(), "missing mandatory operator") + funcSetApprovalForAll(ctx, f) + ctx.Log("erc721.funcSetApprovalForAll ok") +} + +type TransferFromContext struct { + Events Erc721Events + Params ImmutableTransferFromParams + State MutableErc721State +} + +func funcTransferFromThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("erc721.funcTransferFrom") + f := &TransferFromContext{ + Params: ImmutableTransferFromParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + State: MutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.From().Exists(), "missing mandatory from") + ctx.Require(f.Params.To().Exists(), "missing mandatory to") + ctx.Require(f.Params.TokenID().Exists(), "missing mandatory tokenID") + funcTransferFrom(ctx, f) + ctx.Log("erc721.funcTransferFrom ok") +} + +type BalanceOfContext struct { + Params ImmutableBalanceOfParams + Results MutableBalanceOfResults + State ImmutableErc721State +} + +func viewBalanceOfThunk(ctx wasmlib.ScViewContext) { + ctx.Log("erc721.viewBalanceOf") + f := &BalanceOfContext{ + Params: ImmutableBalanceOfParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + Results: MutableBalanceOfResults{ + id: wasmlib.OBJ_ID_RESULTS, + }, + State: ImmutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.Owner().Exists(), "missing mandatory owner") + viewBalanceOf(ctx, f) + ctx.Log("erc721.viewBalanceOf ok") +} + +type GetApprovedContext struct { + Params ImmutableGetApprovedParams + Results MutableGetApprovedResults + State ImmutableErc721State +} + +func viewGetApprovedThunk(ctx wasmlib.ScViewContext) { + ctx.Log("erc721.viewGetApproved") + f := &GetApprovedContext{ + Params: ImmutableGetApprovedParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + Results: MutableGetApprovedResults{ + id: wasmlib.OBJ_ID_RESULTS, + }, + State: ImmutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.TokenID().Exists(), "missing mandatory tokenID") + viewGetApproved(ctx, f) + ctx.Log("erc721.viewGetApproved ok") +} + +type IsApprovedForAllContext struct { + Params ImmutableIsApprovedForAllParams + Results MutableIsApprovedForAllResults + State ImmutableErc721State +} + +func viewIsApprovedForAllThunk(ctx wasmlib.ScViewContext) { + ctx.Log("erc721.viewIsApprovedForAll") + f := &IsApprovedForAllContext{ + Params: ImmutableIsApprovedForAllParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + Results: MutableIsApprovedForAllResults{ + id: wasmlib.OBJ_ID_RESULTS, + }, + State: ImmutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.Operator().Exists(), "missing mandatory operator") + ctx.Require(f.Params.Owner().Exists(), "missing mandatory owner") + viewIsApprovedForAll(ctx, f) + ctx.Log("erc721.viewIsApprovedForAll ok") +} + +type NameContext struct { + Results MutableNameResults + State ImmutableErc721State +} + +func viewNameThunk(ctx wasmlib.ScViewContext) { + ctx.Log("erc721.viewName") + f := &NameContext{ + Results: MutableNameResults{ + id: wasmlib.OBJ_ID_RESULTS, + }, + State: ImmutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + viewName(ctx, f) + ctx.Log("erc721.viewName ok") +} + +type OwnerOfContext struct { + Params ImmutableOwnerOfParams + Results MutableOwnerOfResults + State ImmutableErc721State +} + +func viewOwnerOfThunk(ctx wasmlib.ScViewContext) { + ctx.Log("erc721.viewOwnerOf") + f := &OwnerOfContext{ + Params: ImmutableOwnerOfParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + Results: MutableOwnerOfResults{ + id: wasmlib.OBJ_ID_RESULTS, + }, + State: ImmutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.TokenID().Exists(), "missing mandatory tokenID") + viewOwnerOf(ctx, f) + ctx.Log("erc721.viewOwnerOf ok") +} + +type SymbolContext struct { + Results MutableSymbolResults + State ImmutableErc721State +} + +func viewSymbolThunk(ctx wasmlib.ScViewContext) { + ctx.Log("erc721.viewSymbol") + f := &SymbolContext{ + Results: MutableSymbolResults{ + id: wasmlib.OBJ_ID_RESULTS, + }, + State: ImmutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + viewSymbol(ctx, f) + ctx.Log("erc721.viewSymbol ok") +} + +type TokenURIContext struct { + Params ImmutableTokenURIParams + Results MutableTokenURIResults + State ImmutableErc721State +} + +func viewTokenURIThunk(ctx wasmlib.ScViewContext) { + ctx.Log("erc721.viewTokenURI") + f := &TokenURIContext{ + Params: ImmutableTokenURIParams{ + id: wasmlib.OBJ_ID_PARAMS, + }, + Results: MutableTokenURIResults{ + id: wasmlib.OBJ_ID_RESULTS, + }, + State: ImmutableErc721State{ + id: wasmlib.OBJ_ID_STATE, + }, + } + ctx.Require(f.Params.TokenID().Exists(), "missing mandatory tokenID") + viewTokenURI(ctx, f) + ctx.Log("erc721.viewTokenURI ok") +} diff --git a/contracts/wasm/erc721/go/erc721/params.go b/contracts/wasm/erc721/go/erc721/params.go new file mode 100644 index 0000000000..da0baa3669 --- /dev/null +++ b/contracts/wasm/erc721/go/erc721/params.go @@ -0,0 +1,274 @@ +// 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 erc721 + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type ImmutableApproveParams struct { + id int32 +} + +func (s ImmutableApproveParams) Approved() wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamApproved]) +} + +func (s ImmutableApproveParams) TokenID() wasmlib.ScImmutableHash { + return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type MutableApproveParams struct { + id int32 +} + +func (s MutableApproveParams) Approved() wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamApproved]) +} + +func (s MutableApproveParams) TokenID() wasmlib.ScMutableHash { + return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type ImmutableBurnParams struct { + id int32 +} + +func (s ImmutableBurnParams) TokenID() wasmlib.ScImmutableHash { + return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type MutableBurnParams struct { + id int32 +} + +func (s MutableBurnParams) TokenID() wasmlib.ScMutableHash { + return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type ImmutableInitParams struct { + id int32 +} + +func (s ImmutableInitParams) Name() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamName]) +} + +func (s ImmutableInitParams) Symbol() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamSymbol]) +} + +type MutableInitParams struct { + id int32 +} + +func (s MutableInitParams) Name() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, idxMap[IdxParamName]) +} + +func (s MutableInitParams) Symbol() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, idxMap[IdxParamSymbol]) +} + +type ImmutableMintParams struct { + id int32 +} + +func (s ImmutableMintParams) TokenID() wasmlib.ScImmutableHash { + return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type MutableMintParams struct { + id int32 +} + +func (s MutableMintParams) TokenID() wasmlib.ScMutableHash { + return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type ImmutableSafeTransferFromParams struct { + id int32 +} + +func (s ImmutableSafeTransferFromParams) Data() wasmlib.ScImmutableBytes { + return wasmlib.NewScImmutableBytes(s.id, idxMap[IdxParamData]) +} + +func (s ImmutableSafeTransferFromParams) From() wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamFrom]) +} + +func (s ImmutableSafeTransferFromParams) To() wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamTo]) +} + +func (s ImmutableSafeTransferFromParams) TokenID() wasmlib.ScImmutableHash { + return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type MutableSafeTransferFromParams struct { + id int32 +} + +func (s MutableSafeTransferFromParams) Data() wasmlib.ScMutableBytes { + return wasmlib.NewScMutableBytes(s.id, idxMap[IdxParamData]) +} + +func (s MutableSafeTransferFromParams) From() wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamFrom]) +} + +func (s MutableSafeTransferFromParams) To() wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamTo]) +} + +func (s MutableSafeTransferFromParams) TokenID() wasmlib.ScMutableHash { + return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type ImmutableSetApprovalForAllParams struct { + id int32 +} + +func (s ImmutableSetApprovalForAllParams) Approval() wasmlib.ScImmutableBool { + return wasmlib.NewScImmutableBool(s.id, idxMap[IdxParamApproval]) +} + +func (s ImmutableSetApprovalForAllParams) Operator() wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamOperator]) +} + +type MutableSetApprovalForAllParams struct { + id int32 +} + +func (s MutableSetApprovalForAllParams) Approval() wasmlib.ScMutableBool { + return wasmlib.NewScMutableBool(s.id, idxMap[IdxParamApproval]) +} + +func (s MutableSetApprovalForAllParams) Operator() wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamOperator]) +} + +type ImmutableTransferFromParams struct { + id int32 +} + +func (s ImmutableTransferFromParams) From() wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamFrom]) +} + +func (s ImmutableTransferFromParams) To() wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamTo]) +} + +func (s ImmutableTransferFromParams) TokenID() wasmlib.ScImmutableHash { + return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type MutableTransferFromParams struct { + id int32 +} + +func (s MutableTransferFromParams) From() wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamFrom]) +} + +func (s MutableTransferFromParams) To() wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamTo]) +} + +func (s MutableTransferFromParams) TokenID() wasmlib.ScMutableHash { + return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type ImmutableBalanceOfParams struct { + id int32 +} + +func (s ImmutableBalanceOfParams) Owner() wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamOwner]) +} + +type MutableBalanceOfParams struct { + id int32 +} + +func (s MutableBalanceOfParams) Owner() wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamOwner]) +} + +type ImmutableGetApprovedParams struct { + id int32 +} + +func (s ImmutableGetApprovedParams) TokenID() wasmlib.ScImmutableHash { + return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type MutableGetApprovedParams struct { + id int32 +} + +func (s MutableGetApprovedParams) TokenID() wasmlib.ScMutableHash { + return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type ImmutableIsApprovedForAllParams struct { + id int32 +} + +func (s ImmutableIsApprovedForAllParams) Operator() wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamOperator]) +} + +func (s ImmutableIsApprovedForAllParams) Owner() wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamOwner]) +} + +type MutableIsApprovedForAllParams struct { + id int32 +} + +func (s MutableIsApprovedForAllParams) Operator() wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamOperator]) +} + +func (s MutableIsApprovedForAllParams) Owner() wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamOwner]) +} + +type ImmutableOwnerOfParams struct { + id int32 +} + +func (s ImmutableOwnerOfParams) TokenID() wasmlib.ScImmutableHash { + return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type MutableOwnerOfParams struct { + id int32 +} + +func (s MutableOwnerOfParams) TokenID() wasmlib.ScMutableHash { + return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type ImmutableTokenURIParams struct { + id int32 +} + +func (s ImmutableTokenURIParams) TokenID() wasmlib.ScImmutableHash { + return wasmlib.NewScImmutableHash(s.id, idxMap[IdxParamTokenID]) +} + +type MutableTokenURIParams struct { + id int32 +} + +func (s MutableTokenURIParams) TokenID() wasmlib.ScMutableHash { + return wasmlib.NewScMutableHash(s.id, idxMap[IdxParamTokenID]) +} diff --git a/contracts/wasm/erc721/go/erc721/results.go b/contracts/wasm/erc721/go/erc721/results.go new file mode 100644 index 0000000000..ac16050ca7 --- /dev/null +++ b/contracts/wasm/erc721/go/erc721/results.go @@ -0,0 +1,122 @@ +// 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 erc721 + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type ImmutableBalanceOfResults struct { + id int32 +} + +func (s ImmutableBalanceOfResults) Amount() wasmlib.ScImmutableUint64 { + return wasmlib.NewScImmutableUint64(s.id, idxMap[IdxResultAmount]) +} + +type MutableBalanceOfResults struct { + id int32 +} + +func (s MutableBalanceOfResults) Amount() wasmlib.ScMutableUint64 { + return wasmlib.NewScMutableUint64(s.id, idxMap[IdxResultAmount]) +} + +type ImmutableGetApprovedResults struct { + id int32 +} + +func (s ImmutableGetApprovedResults) Approved() wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxResultApproved]) +} + +type MutableGetApprovedResults struct { + id int32 +} + +func (s MutableGetApprovedResults) Approved() wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxResultApproved]) +} + +type ImmutableIsApprovedForAllResults struct { + id int32 +} + +func (s ImmutableIsApprovedForAllResults) Approval() wasmlib.ScImmutableBool { + return wasmlib.NewScImmutableBool(s.id, idxMap[IdxResultApproval]) +} + +type MutableIsApprovedForAllResults struct { + id int32 +} + +func (s MutableIsApprovedForAllResults) Approval() wasmlib.ScMutableBool { + return wasmlib.NewScMutableBool(s.id, idxMap[IdxResultApproval]) +} + +type ImmutableNameResults struct { + id int32 +} + +func (s ImmutableNameResults) Name() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultName]) +} + +type MutableNameResults struct { + id int32 +} + +func (s MutableNameResults) Name() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, idxMap[IdxResultName]) +} + +type ImmutableOwnerOfResults struct { + id int32 +} + +func (s ImmutableOwnerOfResults) Owner() wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxResultOwner]) +} + +type MutableOwnerOfResults struct { + id int32 +} + +func (s MutableOwnerOfResults) Owner() wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxResultOwner]) +} + +type ImmutableSymbolResults struct { + id int32 +} + +func (s ImmutableSymbolResults) Symbol() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultSymbol]) +} + +type MutableSymbolResults struct { + id int32 +} + +func (s MutableSymbolResults) Symbol() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, idxMap[IdxResultSymbol]) +} + +type ImmutableTokenURIResults struct { + id int32 +} + +func (s ImmutableTokenURIResults) TokenURI() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, idxMap[IdxResultTokenURI]) +} + +type MutableTokenURIResults struct { + id int32 +} + +func (s MutableTokenURIResults) TokenURI() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, idxMap[IdxResultTokenURI]) +} diff --git a/contracts/wasm/erc721/go/erc721/state.go b/contracts/wasm/erc721/go/erc721/state.go new file mode 100644 index 0000000000..c3ad62781b --- /dev/null +++ b/contracts/wasm/erc721/go/erc721/state.go @@ -0,0 +1,136 @@ +// 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 erc721 + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type MapHashToImmutableAgentID struct { + objID int32 +} + +func (m MapHashToImmutableAgentID) GetAgentID(key wasmlib.ScHash) wasmlib.ScImmutableAgentID { + return wasmlib.NewScImmutableAgentID(m.objID, key.KeyID()) +} + +type MapAgentIDToImmutableOperators struct { + objID int32 +} + +func (m MapAgentIDToImmutableOperators) GetOperators(key wasmlib.ScAgentID) ImmutableOperators { + subID := wasmlib.GetObjectID(m.objID, key.KeyID(), wasmlib.TYPE_MAP) + return ImmutableOperators{objID: subID} +} + +type MapAgentIDToImmutableUint64 struct { + objID int32 +} + +func (m MapAgentIDToImmutableUint64) GetUint64(key wasmlib.ScAgentID) wasmlib.ScImmutableUint64 { + return wasmlib.NewScImmutableUint64(m.objID, key.KeyID()) +} + +type ImmutableErc721State struct { + id int32 +} + +func (s ImmutableErc721State) ApprovedAccounts() MapHashToImmutableAgentID { + mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateApprovedAccounts], wasmlib.TYPE_MAP) + return MapHashToImmutableAgentID{objID: mapID} +} + +func (s ImmutableErc721State) ApprovedOperators() MapAgentIDToImmutableOperators { + mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateApprovedOperators], wasmlib.TYPE_MAP) + return MapAgentIDToImmutableOperators{objID: mapID} +} + +func (s ImmutableErc721State) Balances() MapAgentIDToImmutableUint64 { + mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBalances], wasmlib.TYPE_MAP) + return MapAgentIDToImmutableUint64{objID: mapID} +} + +func (s ImmutableErc721State) Name() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, idxMap[IdxStateName]) +} + +func (s ImmutableErc721State) Owners() MapHashToImmutableAgentID { + mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateOwners], wasmlib.TYPE_MAP) + return MapHashToImmutableAgentID{objID: mapID} +} + +func (s ImmutableErc721State) Symbol() wasmlib.ScImmutableString { + return wasmlib.NewScImmutableString(s.id, idxMap[IdxStateSymbol]) +} + +type MapHashToMutableAgentID struct { + objID int32 +} + +func (m MapHashToMutableAgentID) Clear() { + wasmlib.Clear(m.objID) +} + +func (m MapHashToMutableAgentID) GetAgentID(key wasmlib.ScHash) wasmlib.ScMutableAgentID { + return wasmlib.NewScMutableAgentID(m.objID, key.KeyID()) +} + +type MapAgentIDToMutableOperators struct { + objID int32 +} + +func (m MapAgentIDToMutableOperators) Clear() { + wasmlib.Clear(m.objID) +} + +func (m MapAgentIDToMutableOperators) GetOperators(key wasmlib.ScAgentID) MutableOperators { + subID := wasmlib.GetObjectID(m.objID, key.KeyID(), wasmlib.TYPE_MAP) + return MutableOperators{objID: subID} +} + +type MapAgentIDToMutableUint64 struct { + objID int32 +} + +func (m MapAgentIDToMutableUint64) Clear() { + wasmlib.Clear(m.objID) +} + +func (m MapAgentIDToMutableUint64) GetUint64(key wasmlib.ScAgentID) wasmlib.ScMutableUint64 { + return wasmlib.NewScMutableUint64(m.objID, key.KeyID()) +} + +type MutableErc721State struct { + id int32 +} + +func (s MutableErc721State) ApprovedAccounts() MapHashToMutableAgentID { + mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateApprovedAccounts], wasmlib.TYPE_MAP) + return MapHashToMutableAgentID{objID: mapID} +} + +func (s MutableErc721State) ApprovedOperators() MapAgentIDToMutableOperators { + mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateApprovedOperators], wasmlib.TYPE_MAP) + return MapAgentIDToMutableOperators{objID: mapID} +} + +func (s MutableErc721State) Balances() MapAgentIDToMutableUint64 { + mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateBalances], wasmlib.TYPE_MAP) + return MapAgentIDToMutableUint64{objID: mapID} +} + +func (s MutableErc721State) Name() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, idxMap[IdxStateName]) +} + +func (s MutableErc721State) Owners() MapHashToMutableAgentID { + mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateOwners], wasmlib.TYPE_MAP) + return MapHashToMutableAgentID{objID: mapID} +} + +func (s MutableErc721State) Symbol() wasmlib.ScMutableString { + return wasmlib.NewScMutableString(s.id, idxMap[IdxStateSymbol]) +} diff --git a/contracts/wasm/erc721/go/erc721/typedefs.go b/contracts/wasm/erc721/go/erc721/typedefs.go new file mode 100644 index 0000000000..b9f771d048 --- /dev/null +++ b/contracts/wasm/erc721/go/erc721/typedefs.go @@ -0,0 +1,34 @@ +// 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 erc721 + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type MapAgentIDToImmutableBool struct { + objID int32 +} + +func (m MapAgentIDToImmutableBool) GetBool(key wasmlib.ScAgentID) wasmlib.ScImmutableBool { + return wasmlib.NewScImmutableBool(m.objID, key.KeyID()) +} + +type ImmutableOperators = MapAgentIDToImmutableBool + +type MapAgentIDToMutableBool struct { + objID int32 +} + +func (m MapAgentIDToMutableBool) Clear() { + wasmlib.Clear(m.objID) +} + +func (m MapAgentIDToMutableBool) GetBool(key wasmlib.ScAgentID) wasmlib.ScMutableBool { + return wasmlib.NewScMutableBool(m.objID, key.KeyID()) +} + +type MutableOperators = MapAgentIDToMutableBool diff --git a/contracts/wasm/erc721/go/main.go b/contracts/wasm/erc721/go/main.go new file mode 100644 index 0000000000..b863c75bb9 --- /dev/null +++ b/contracts/wasm/erc721/go/main.go @@ -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 + +// +build wasm + +package main + +import "github.com/iotaledger/wasp/packages/vm/wasmclient" + +import "github.com/iotaledger/wasp/contracts/wasm/erc721/go/erc721" + +func main() { +} + +//export on_load +func onLoad() { + h := &wasmclient.WasmVMHost{} + h.ConnectWasmHost() + erc721.OnLoad() +} diff --git a/contracts/wasm/erc721/schema.yaml b/contracts/wasm/erc721/schema.yaml new file mode 100644 index 0000000000..450632f03a --- /dev/null +++ b/contracts/wasm/erc721/schema.yaml @@ -0,0 +1,95 @@ +name: Erc721 +description: ERC-721 NFT PoC for IOTA Smart Contracts +events: + init: + name: String + symbol: String + approval: + owner: AgentID + approved: AgentID + tokenID: Hash + approvalForAll: + owner: AgentID + operator: AgentID + approval: Bool + mint: + balance: Uint64 + owner: AgentID + tokenID: Hash + transfer: + from: AgentID + to: AgentID + tokenID: Hash +structs: { } +typedefs: + Operators: map[AgentID]Bool // approval status of each operator +state: + name: String + symbol: String + owners: map[Hash]AgentID // 1:1 mapping of owners to token IDs + 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 +funcs: + approve: + params: + approved: AgentID? // target account, clear approval when not present + tokenID: Hash // token ID + burn: + params: + tokenID: Hash // token ID + init: + params: + name=n: String // creator/owner of the initial supply + symbol=s: String // initial token supply + mint: + params: + tokenID: Hash // New token id + safeTransferFrom: + params: + from: AgentID // from account + to: AgentID // to account, which is SC + tokenID: Hash // token ID + data: Bytes? // extra data to pass to SC + setApprovalForAll: + params: + operator: AgentID // target operator of account + approval: Bool + transferFrom: + params: + from: AgentID // from account + to: AgentID // to account + tokenID: Hash // token ID +views: + balanceOf: + params: + owner: AgentID // account owner + results: + amount: Uint64 //amount of tokens (owner) + getApproved: + params: + tokenID: Hash + results: + approved: AgentID + isApprovedForAll: + params: + owner: AgentID + operator: AgentID + results: + approval: Bool + name: + results: + name: String + ownerOf: + params: + tokenID: Hash + results: + owner: AgentID + symbol: + results: + symbol: String + tokenURI: + params: + tokenID: Hash + results: + tokenURI: String diff --git a/contracts/wasm/erc721/src/consts.rs b/contracts/wasm/erc721/src/consts.rs new file mode 100644 index 0000000000..69c5bce108 --- /dev/null +++ b/contracts/wasm/erc721/src/consts.rs @@ -0,0 +1,70 @@ +// 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 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 RESULT_AMOUNT : &str = "amount"; +pub const RESULT_APPROVAL : &str = "approval"; +pub const RESULT_APPROVED : &str = "approved"; +pub const RESULT_NAME : &str = "name"; +pub const RESULT_OWNER : &str = "owner"; +pub const RESULT_SYMBOL : &str = "symbol"; +pub const RESULT_TOKEN_URI : &str = "tokenURI"; + +pub const STATE_APPROVED_ACCOUNTS : &str = "approvedAccounts"; +pub const STATE_APPROVED_OPERATORS : &str = "approvedOperators"; +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 FUNC_APPROVE : &str = "approve"; +pub const FUNC_BURN : &str = "burn"; +pub const FUNC_INIT : &str = "init"; +pub const FUNC_MINT : &str = "mint"; +pub const FUNC_SAFE_TRANSFER_FROM : &str = "safeTransferFrom"; +pub const FUNC_SET_APPROVAL_FOR_ALL : &str = "setApprovalForAll"; +pub const FUNC_TRANSFER_FROM : &str = "transferFrom"; +pub const VIEW_BALANCE_OF : &str = "balanceOf"; +pub const VIEW_GET_APPROVED : &str = "getApproved"; +pub const VIEW_IS_APPROVED_FOR_ALL : &str = "isApprovedForAll"; +pub const VIEW_NAME : &str = "name"; +pub const VIEW_OWNER_OF : &str = "ownerOf"; +pub const VIEW_SYMBOL : &str = "symbol"; +pub const VIEW_TOKEN_URI : &str = "tokenURI"; + +pub const HFUNC_APPROVE : ScHname = ScHname(0xa0661268); +pub const HFUNC_BURN : ScHname = ScHname(0x7bc1efb1); +pub const HFUNC_INIT : ScHname = ScHname(0x1f44d644); +pub const HFUNC_MINT : ScHname = ScHname(0xa29addcf); +pub const HFUNC_SAFE_TRANSFER_FROM : ScHname = ScHname(0x130ce158); +pub const HFUNC_SET_APPROVAL_FOR_ALL : ScHname = ScHname(0xb8d8c776); +pub const HFUNC_TRANSFER_FROM : ScHname = ScHname(0xd5e0a602); +pub const HVIEW_BALANCE_OF : ScHname = ScHname(0x67ef8df4); +pub const HVIEW_GET_APPROVED : ScHname = ScHname(0xbe34b6ba); +pub const HVIEW_IS_APPROVED_FOR_ALL : ScHname = ScHname(0x3251b0f0); +pub const HVIEW_NAME : ScHname = ScHname(0x0df7da3a); +pub const HVIEW_OWNER_OF : ScHname = ScHname(0x1246f5ad); +pub const HVIEW_SYMBOL : ScHname = ScHname(0x3e93d19b); +pub const HVIEW_TOKEN_URI : ScHname = ScHname(0x4e1a7397); diff --git a/contracts/wasm/erc721/src/contract.rs b/contracts/wasm/erc721/src/contract.rs new file mode 100644 index 0000000000..4f23b4c652 --- /dev/null +++ b/contracts/wasm/erc721/src/contract.rs @@ -0,0 +1,227 @@ +// 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 std::ptr; + +use wasmlib::*; + +use crate::consts::*; +use crate::params::*; +use crate::results::*; + +pub struct ApproveCall { + pub func: ScFunc, + pub params: MutableApproveParams, +} + +pub struct BurnCall { + pub func: ScFunc, + pub params: MutableBurnParams, +} + +pub struct InitCall { + pub func: ScInitFunc, + pub params: MutableInitParams, +} + +pub struct MintCall { + pub func: ScFunc, + pub params: MutableMintParams, +} + +pub struct SafeTransferFromCall { + pub func: ScFunc, + pub params: MutableSafeTransferFromParams, +} + +pub struct SetApprovalForAllCall { + pub func: ScFunc, + pub params: MutableSetApprovalForAllParams, +} + +pub struct TransferFromCall { + pub func: ScFunc, + pub params: MutableTransferFromParams, +} + +pub struct BalanceOfCall { + pub func: ScView, + pub params: MutableBalanceOfParams, + pub results: ImmutableBalanceOfResults, +} + +pub struct GetApprovedCall { + pub func: ScView, + pub params: MutableGetApprovedParams, + pub results: ImmutableGetApprovedResults, +} + +pub struct IsApprovedForAllCall { + pub func: ScView, + pub params: MutableIsApprovedForAllParams, + pub results: ImmutableIsApprovedForAllResults, +} + +pub struct NameCall { + pub func: ScView, + pub results: ImmutableNameResults, +} + +pub struct OwnerOfCall { + pub func: ScView, + pub params: MutableOwnerOfParams, + pub results: ImmutableOwnerOfResults, +} + +pub struct SymbolCall { + pub func: ScView, + pub results: ImmutableSymbolResults, +} + +pub struct TokenURICall { + pub func: ScView, + pub params: MutableTokenURIParams, + pub results: ImmutableTokenURIResults, +} + +pub struct ScFuncs { +} + +impl ScFuncs { + pub fn approve(_ctx: & dyn ScFuncCallContext) -> ApproveCall { + let mut f = ApproveCall { + func: ScFunc::new(HSC_NAME, HFUNC_APPROVE), + params: MutableApproveParams { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); + f + } + + pub fn burn(_ctx: & dyn ScFuncCallContext) -> BurnCall { + let mut f = BurnCall { + func: ScFunc::new(HSC_NAME, HFUNC_BURN), + params: MutableBurnParams { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); + f + } + + pub fn init(_ctx: & dyn ScFuncCallContext) -> InitCall { + let mut f = InitCall { + func: ScInitFunc::new(HSC_NAME, HFUNC_INIT), + params: MutableInitParams { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); + f + } + + pub fn mint(_ctx: & dyn ScFuncCallContext) -> MintCall { + let mut f = MintCall { + func: ScFunc::new(HSC_NAME, HFUNC_MINT), + params: MutableMintParams { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); + f + } + + pub fn safe_transfer_from(_ctx: & dyn ScFuncCallContext) -> SafeTransferFromCall { + let mut f = SafeTransferFromCall { + func: ScFunc::new(HSC_NAME, HFUNC_SAFE_TRANSFER_FROM), + params: MutableSafeTransferFromParams { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); + f + } + + pub fn set_approval_for_all(_ctx: & dyn ScFuncCallContext) -> SetApprovalForAllCall { + let mut f = SetApprovalForAllCall { + func: ScFunc::new(HSC_NAME, HFUNC_SET_APPROVAL_FOR_ALL), + params: MutableSetApprovalForAllParams { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); + f + } + + pub fn transfer_from(_ctx: & dyn ScFuncCallContext) -> TransferFromCall { + let mut f = TransferFromCall { + func: ScFunc::new(HSC_NAME, HFUNC_TRANSFER_FROM), + params: MutableTransferFromParams { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); + f + } + + pub fn balance_of(_ctx: & dyn ScViewCallContext) -> BalanceOfCall { + let mut f = BalanceOfCall { + func: ScView::new(HSC_NAME, HVIEW_BALANCE_OF), + params: MutableBalanceOfParams { id: 0 }, + results: ImmutableBalanceOfResults { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, &mut f.results.id); + f + } + + pub fn get_approved(_ctx: & dyn ScViewCallContext) -> GetApprovedCall { + let mut f = GetApprovedCall { + func: ScView::new(HSC_NAME, HVIEW_GET_APPROVED), + params: MutableGetApprovedParams { id: 0 }, + results: ImmutableGetApprovedResults { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, &mut f.results.id); + f + } + + pub fn is_approved_for_all(_ctx: & dyn ScViewCallContext) -> IsApprovedForAllCall { + let mut f = IsApprovedForAllCall { + func: ScView::new(HSC_NAME, HVIEW_IS_APPROVED_FOR_ALL), + params: MutableIsApprovedForAllParams { id: 0 }, + results: ImmutableIsApprovedForAllResults { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, &mut f.results.id); + f + } + + pub fn name(_ctx: & dyn ScViewCallContext) -> NameCall { + let mut f = NameCall { + func: ScView::new(HSC_NAME, HVIEW_NAME), + results: ImmutableNameResults { id: 0 }, + }; + f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); + f + } + + pub fn owner_of(_ctx: & dyn ScViewCallContext) -> OwnerOfCall { + let mut f = OwnerOfCall { + func: ScView::new(HSC_NAME, HVIEW_OWNER_OF), + params: MutableOwnerOfParams { id: 0 }, + results: ImmutableOwnerOfResults { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, &mut f.results.id); + f + } + + pub fn symbol(_ctx: & dyn ScViewCallContext) -> SymbolCall { + let mut f = SymbolCall { + func: ScView::new(HSC_NAME, HVIEW_SYMBOL), + results: ImmutableSymbolResults { id: 0 }, + }; + f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); + f + } + + pub fn token_uri(_ctx: & dyn ScViewCallContext) -> TokenURICall { + let mut f = TokenURICall { + func: ScView::new(HSC_NAME, HVIEW_TOKEN_URI), + params: MutableTokenURIParams { id: 0 }, + results: ImmutableTokenURIResults { id: 0 }, + }; + f.func.set_ptrs(&mut f.params.id, &mut f.results.id); + f + } +} diff --git a/contracts/wasm/erc721/src/erc721.rs b/contracts/wasm/erc721/src/erc721.rs new file mode 100644 index 0000000000..c313ad4727 --- /dev/null +++ b/contracts/wasm/erc721/src/erc721.rs @@ -0,0 +1,243 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use wasmlib::*; + +use crate::*; +use crate::typedefs::*; + +// Follows ERC-721 standard as closely as possible +// https://eips.ethereum.org/EIPS/eip-721 +// Notable changes w.r.t. ERC-721: +// - tokenID is Hash instead of int256 +// - balance amounts are Uint64 instead of int256 +// - all address accounts are replaced with AgentID accounts +// - for consistency and to reduce confusion: +// use 'approved' when it is an AgentID +// use 'approval' when it is a Bool + +// set the required base URI, to which the base58 encoded token ID will be concatenated +const BASE_URI: &str = "my/special/base/uri/"; + +/////////////////////////// HELPER FUNCTIONS //////////////////////////// + +// checks if caller is owner, or one of its delegated operators +fn can_operate(state: MutableErc721State, caller: &ScAgentID, owner: &ScAgentID) -> bool { + if *caller == *owner { + return true; + } + + let operators = state.approved_operators().get_operators(owner); + operators.get_bool(&caller).value() +} + +// checks if caller is owner, or one of its delegated operators, or approved account for tokenID +fn can_transfer(state: MutableErc721State, caller: &ScAgentID, owner: &ScAgentID, token_id: &ScHash) -> bool { + if can_operate(state, caller, owner) { + return true; + } + + let controller = state.approved_accounts().get_agent_id(token_id); + controller.value() == *caller +} + +// common code for safeTransferFrom and transferFrom +fn transfer(ctx: &ScFuncContext, state: MutableErc721State, from: &ScAgentID, to: &ScAgentID, token_id: &ScHash) { + let token_owner = state.owners().get_agent_id(token_id); + ctx.require(token_owner.exists(), "tokenID does not exist"); + + let owner = token_owner.value(); + ctx.require(can_transfer(state, &ctx.caller(), &owner, token_id), + "not owner, operator, or approved"); + + ctx.require(owner == *from, "from is not owner"); + //TODO: ctx.require(to == , "invalid 'to' agentid"); + + let balance_from = state.balances().get_uint64(from); + let balance_to = state.balances().get_uint64(to); + + balance_from.set_value(balance_from.value() - 1); + balance_to.set_value(balance_to.value() + 1); + + token_owner.set_value(to); + + let events = Erc721Events {}; + // remove approval if it exists + let current_approved = state.approved_accounts().get_agent_id(&token_id); + if current_approved.exists() { + current_approved.delete(); + events.approval(&ScAgentID::ZERO, &owner, &token_id); + } + + events.transfer(from, to, token_id); +} + +/////////////////////////// SC FUNCS //////////////////////////// + +// Gives permission to to to transfer tokenID token to another account. +// The approval is cleared when optional approval account is omitted. +// The approval will be cleared when the token is transferred. +pub fn func_approve(ctx: &ScFuncContext, f: &ApproveContext) { + let token_id = f.params.token_id().value(); + let token_owner = f.state.owners().get_agent_id(&token_id); + ctx.require(token_owner.exists(), "tokenID does not exist"); + let owner = token_owner.value(); + ctx.require(can_operate(f.state, &ctx.caller(), &owner), "not owner or operator"); + + let approved = f.params.approved(); + if !approved.exists() { + // remove approval if it exists + let current_approved = f.state.approved_accounts().get_agent_id(&token_id); + if current_approved.exists() { + current_approved.delete(); + f.events.approval(&ScAgentID::ZERO, &owner, &token_id); + } + return; + } + + let account = approved.value(); + ctx.require(owner != account, "approved account equals owner"); + + f.state.approved_accounts().get_agent_id(&token_id).set_value(&account); + f.events.approval(&account, &owner, &token_id); +} + +// Destroys tokenID. The approval is cleared when the token is burned. +pub fn func_burn(ctx: &ScFuncContext, f: &BurnContext) { + let token_id = f.params.token_id().value(); + let owner = f.state.owners().get_agent_id(&token_id).value(); + ctx.require(owner != ScAgentID::ZERO, "tokenID does not exist"); + ctx.require(ctx.caller() == owner, "caller is not owner"); + + // remove approval if it exists + let current_approved = f.state.approved_accounts().get_agent_id(&token_id); + if current_approved.exists() { + current_approved.delete(); + f.events.approval(&ScAgentID::ZERO, &owner, &token_id); + } + + let balance = f.state.balances().get_uint64(&owner); + balance.set_value(balance.value() - 1); + + f.state.owners().get_agent_id(&token_id).delete(); + f.events.transfer(&owner, &ScAgentID::ZERO, &token_id); +} + +// Initializes the contract by setting a name and a symbol to the token collection. +pub fn func_init(_ctx: &ScFuncContext, f: &InitContext) { + let name = f.params.name().value(); + let symbol = f.params.symbol().value(); + + f.state.name().set_value(&name); + f.state.symbol().set_value(&symbol); + + f.events.init(&name, &symbol); +} + +// Mints tokenID and transfers it to caller as new owner. +pub fn func_mint(ctx: &ScFuncContext, f: &MintContext) { + let token_id = f.params.token_id().value(); + let token_owner = f.state.owners().get_agent_id(&token_id); + ctx.require(!token_owner.exists(), "tokenID already minted"); + + let owner = ctx.caller(); + token_owner.set_value(&owner); + let balance = f.state.balances().get_uint64(&owner); + balance.set_value(balance.value() + 1); + + f.events.transfer(&ScAgentID::ZERO, &owner, &token_id); + // if !owner.is_address() { + // //TODO interpret to as SC address and call its onERC721Received() function + // } +} + +// Safely transfers tokenID token from from to to, checking first that contract +// recipients are aware of the ERC721 protocol to prevent tokens from being forever locked. +pub fn func_safe_transfer_from(ctx: &ScFuncContext, f: &SafeTransferFromContext) { + let from = f.params.from().value(); + let to = f.params.to().value(); + let token_id = f.params.token_id().value(); + transfer(&ctx, f.state, &from, &to, &token_id); + // if !to.is_address() { + // //TODO interpret to as SC address and call its onERC721Received() function + // } +} + +// Approve or remove operator as an operator for the caller. +pub fn func_set_approval_for_all(ctx: &ScFuncContext, f: &SetApprovalForAllContext) { + let owner = ctx.caller(); + let operator = f.params.operator().value(); + ctx.require(owner != operator, "owner equals operator"); + + let approval = f.params.approval().value(); + let operators_for_caller = f.state.approved_operators().get_operators(&owner); + operators_for_caller.get_bool(&operator).set_value(approval); + + f.events.approval_for_all(approval, &operator, &owner); +} + +// Transfers tokenID token from from to to. +pub fn func_transfer_from(ctx: &ScFuncContext, f: &TransferFromContext) { + let from = f.params.from().value(); + let to = f.params.to().value(); + let token_id = f.params.token_id().value(); + transfer(ctx, f.state, &from, &to, &token_id); +} + +/////////////////////////// SC VIEWS //////////////////////////// + +// Returns the number of tokens in owner's account if the owner exists. +pub fn view_balance_of(_ctx: &ScViewContext, f: &BalanceOfContext) { + let owner = f.params.owner().value(); + let balance = f.state.balances().get_uint64(&owner); + if balance.exists() { + f.results.amount().set_value(balance.value()); + } +} + +// Returns the approved account for tokenID token if there is one. +pub fn view_get_approved(_ctx: &ScViewContext, f: &GetApprovedContext) { + let token_id = f.params.token_id().value(); + let approved = f.state.approved_accounts().get_agent_id(&token_id); + if approved.exists() { + f.results.approved().set_value(&approved.value()); + } +} + +// Returns if the operator is allowed to manage all the assets of owner. +pub fn view_is_approved_for_all(_ctx: &ScViewContext, f: &IsApprovedForAllContext) { + let owner = f.params.owner().value(); + let operator = f.params.operator().value(); + let operators = f.state.approved_operators().get_operators(&owner); + let approval = operators.get_bool(&operator); + if approval.exists() { + f.results.approval().set_value(approval.value()); + } +} + +// Returns the token collection name. +pub fn view_name(_ctx: &ScViewContext, f: &NameContext) { + f.results.name().set_value(&f.state.name().value()); +} + +// Returns the owner of the tokenID token if the token exists. +pub fn view_owner_of(_ctx: &ScViewContext, f: &OwnerOfContext) { + let token_id = f.params.token_id().value(); + let owner = f.state.owners().get_agent_id(&token_id); + if owner.exists() { + f.results.owner().set_value(&owner.value()); + } +} + +// Returns the token collection symbol. +pub fn view_symbol(_ctx: &ScViewContext, f: &SymbolContext) { + f.results.symbol().set_value(&f.state.symbol().value()); +} + +// Returns the Uniform Resource Identifier (URI) for tokenID token if the token exists. +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())); + } +} diff --git a/contracts/wasm/erc721/src/events.rs b/contracts/wasm/erc721/src/events.rs new file mode 100644 index 0000000000..5d13ded8be --- /dev/null +++ b/contracts/wasm/erc721/src/events.rs @@ -0,0 +1,55 @@ +// 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 Erc721Events { +} + +impl Erc721Events { + + pub fn approval(&self, approved: &ScAgentID, owner: &ScAgentID, token_id: &ScHash) { + let mut encoder = EventEncoder::new("erc721.approval"); + encoder.agent_id(&approved); + encoder.agent_id(&owner); + encoder.hash(&token_id); + encoder.emit(); + } + + pub fn approval_for_all(&self, approval: bool, operator: &ScAgentID, owner: &ScAgentID) { + let mut encoder = EventEncoder::new("erc721.approvalForAll"); + encoder.bool(approval); + encoder.agent_id(&operator); + encoder.agent_id(&owner); + encoder.emit(); + } + + pub fn init(&self, name: &str, symbol: &str) { + let mut encoder = EventEncoder::new("erc721.init"); + encoder.string(&name); + encoder.string(&symbol); + encoder.emit(); + } + + pub fn mint(&self, balance: u64, owner: &ScAgentID, token_id: &ScHash) { + let mut encoder = EventEncoder::new("erc721.mint"); + encoder.uint64(balance); + encoder.agent_id(&owner); + encoder.hash(&token_id); + encoder.emit(); + } + + pub fn transfer(&self, from: &ScAgentID, to: &ScAgentID, token_id: &ScHash) { + let mut encoder = EventEncoder::new("erc721.transfer"); + encoder.agent_id(&from); + encoder.agent_id(&to); + encoder.hash(&token_id); + encoder.emit(); + } +} diff --git a/contracts/wasm/erc721/src/keys.rs b/contracts/wasm/erc721/src/keys.rs new file mode 100644 index 0000000000..a806243367 --- /dev/null +++ b/contracts/wasm/erc721/src/keys.rs @@ -0,0 +1,74 @@ +// 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::*; + +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_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_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 const KEY_MAP_LEN: usize = 23; + +pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ + PARAM_APPROVAL, + PARAM_APPROVED, + PARAM_DATA, + PARAM_FROM, + PARAM_NAME, + PARAM_OPERATOR, + PARAM_OWNER, + PARAM_SYMBOL, + PARAM_TO, + PARAM_TOKEN_ID, + RESULT_AMOUNT, + RESULT_APPROVAL, + RESULT_APPROVED, + RESULT_NAME, + RESULT_OWNER, + RESULT_SYMBOL, + RESULT_TOKEN_URI, + STATE_APPROVED_ACCOUNTS, + STATE_APPROVED_OPERATORS, + STATE_BALANCES, + STATE_NAME, + STATE_OWNERS, + STATE_SYMBOL, +]; + +pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; + +pub fn idx_map(idx: usize) -> Key32 { + unsafe { + IDX_MAP[idx] + } +} diff --git a/contracts/wasm/erc721/src/lib.rs b/contracts/wasm/erc721/src/lib.rs new file mode 100644 index 0000000000..c1ab699f72 --- /dev/null +++ b/contracts/wasm/erc721/src/lib.rs @@ -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 + +#![allow(dead_code)] +#![allow(unused_imports)] + +use erc721::*; +use wasmlib::*; +use wasmlib::host::*; + +use crate::consts::*; +use crate::events::*; +use crate::keys::*; +use crate::params::*; +use crate::results::*; +use crate::state::*; + +mod consts; +mod contract; +mod events; +mod keys; +mod params; +mod results; +mod state; +mod typedefs; +mod erc721; + +#[no_mangle] +fn on_load() { + let exports = ScExports::new(); + exports.add_func(FUNC_APPROVE, func_approve_thunk); + exports.add_func(FUNC_BURN, func_burn_thunk); + exports.add_func(FUNC_INIT, func_init_thunk); + exports.add_func(FUNC_MINT, func_mint_thunk); + exports.add_func(FUNC_SAFE_TRANSFER_FROM, func_safe_transfer_from_thunk); + exports.add_func(FUNC_SET_APPROVAL_FOR_ALL, func_set_approval_for_all_thunk); + exports.add_func(FUNC_TRANSFER_FROM, func_transfer_from_thunk); + exports.add_view(VIEW_BALANCE_OF, view_balance_of_thunk); + exports.add_view(VIEW_GET_APPROVED, view_get_approved_thunk); + exports.add_view(VIEW_IS_APPROVED_FOR_ALL, view_is_approved_for_all_thunk); + exports.add_view(VIEW_NAME, view_name_thunk); + exports.add_view(VIEW_OWNER_OF, view_owner_of_thunk); + exports.add_view(VIEW_SYMBOL, view_symbol_thunk); + exports.add_view(VIEW_TOKEN_URI, view_token_uri_thunk); + + unsafe { + for i in 0..KEY_MAP_LEN { + IDX_MAP[i] = get_key_id_from_string(KEY_MAP[i]); + } + } +} + +pub struct ApproveContext { + events: Erc721Events, + params: ImmutableApproveParams, + state: MutableErc721State, +} + +fn func_approve_thunk(ctx: &ScFuncContext) { + ctx.log("erc721.funcApprove"); + let f = ApproveContext { + events: Erc721Events {}, + params: ImmutableApproveParams { + id: OBJ_ID_PARAMS, + }, + state: MutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.token_id().exists(), "missing mandatory tokenID"); + func_approve(ctx, &f); + ctx.log("erc721.funcApprove ok"); +} + +pub struct BurnContext { + events: Erc721Events, + params: ImmutableBurnParams, + state: MutableErc721State, +} + +fn func_burn_thunk(ctx: &ScFuncContext) { + ctx.log("erc721.funcBurn"); + let f = BurnContext { + events: Erc721Events {}, + params: ImmutableBurnParams { + id: OBJ_ID_PARAMS, + }, + state: MutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.token_id().exists(), "missing mandatory tokenID"); + func_burn(ctx, &f); + ctx.log("erc721.funcBurn ok"); +} + +pub struct InitContext { + events: Erc721Events, + params: ImmutableInitParams, + state: MutableErc721State, +} + +fn func_init_thunk(ctx: &ScFuncContext) { + ctx.log("erc721.funcInit"); + let f = InitContext { + events: Erc721Events {}, + params: ImmutableInitParams { + id: OBJ_ID_PARAMS, + }, + state: MutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.name().exists(), "missing mandatory name"); + ctx.require(f.params.symbol().exists(), "missing mandatory symbol"); + func_init(ctx, &f); + ctx.log("erc721.funcInit ok"); +} + +pub struct MintContext { + events: Erc721Events, + params: ImmutableMintParams, + state: MutableErc721State, +} + +fn func_mint_thunk(ctx: &ScFuncContext) { + ctx.log("erc721.funcMint"); + let f = MintContext { + events: Erc721Events {}, + params: ImmutableMintParams { + id: OBJ_ID_PARAMS, + }, + state: MutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.token_id().exists(), "missing mandatory tokenID"); + func_mint(ctx, &f); + ctx.log("erc721.funcMint ok"); +} + +pub struct SafeTransferFromContext { + events: Erc721Events, + params: ImmutableSafeTransferFromParams, + state: MutableErc721State, +} + +fn func_safe_transfer_from_thunk(ctx: &ScFuncContext) { + ctx.log("erc721.funcSafeTransferFrom"); + let f = SafeTransferFromContext { + events: Erc721Events {}, + params: ImmutableSafeTransferFromParams { + id: OBJ_ID_PARAMS, + }, + state: MutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.from().exists(), "missing mandatory from"); + ctx.require(f.params.to().exists(), "missing mandatory to"); + ctx.require(f.params.token_id().exists(), "missing mandatory tokenID"); + func_safe_transfer_from(ctx, &f); + ctx.log("erc721.funcSafeTransferFrom ok"); +} + +pub struct SetApprovalForAllContext { + events: Erc721Events, + params: ImmutableSetApprovalForAllParams, + state: MutableErc721State, +} + +fn func_set_approval_for_all_thunk(ctx: &ScFuncContext) { + ctx.log("erc721.funcSetApprovalForAll"); + let f = SetApprovalForAllContext { + events: Erc721Events {}, + params: ImmutableSetApprovalForAllParams { + id: OBJ_ID_PARAMS, + }, + state: MutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.approval().exists(), "missing mandatory approval"); + ctx.require(f.params.operator().exists(), "missing mandatory operator"); + func_set_approval_for_all(ctx, &f); + ctx.log("erc721.funcSetApprovalForAll ok"); +} + +pub struct TransferFromContext { + events: Erc721Events, + params: ImmutableTransferFromParams, + state: MutableErc721State, +} + +fn func_transfer_from_thunk(ctx: &ScFuncContext) { + ctx.log("erc721.funcTransferFrom"); + let f = TransferFromContext { + events: Erc721Events {}, + params: ImmutableTransferFromParams { + id: OBJ_ID_PARAMS, + }, + state: MutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.from().exists(), "missing mandatory from"); + ctx.require(f.params.to().exists(), "missing mandatory to"); + ctx.require(f.params.token_id().exists(), "missing mandatory tokenID"); + func_transfer_from(ctx, &f); + ctx.log("erc721.funcTransferFrom ok"); +} + +pub struct BalanceOfContext { + params: ImmutableBalanceOfParams, + results: MutableBalanceOfResults, + state: ImmutableErc721State, +} + +fn view_balance_of_thunk(ctx: &ScViewContext) { + ctx.log("erc721.viewBalanceOf"); + let f = BalanceOfContext { + params: ImmutableBalanceOfParams { + id: OBJ_ID_PARAMS, + }, + results: MutableBalanceOfResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.owner().exists(), "missing mandatory owner"); + view_balance_of(ctx, &f); + ctx.log("erc721.viewBalanceOf ok"); +} + +pub struct GetApprovedContext { + params: ImmutableGetApprovedParams, + results: MutableGetApprovedResults, + state: ImmutableErc721State, +} + +fn view_get_approved_thunk(ctx: &ScViewContext) { + ctx.log("erc721.viewGetApproved"); + let f = GetApprovedContext { + params: ImmutableGetApprovedParams { + id: OBJ_ID_PARAMS, + }, + results: MutableGetApprovedResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.token_id().exists(), "missing mandatory tokenID"); + view_get_approved(ctx, &f); + ctx.log("erc721.viewGetApproved ok"); +} + +pub struct IsApprovedForAllContext { + params: ImmutableIsApprovedForAllParams, + results: MutableIsApprovedForAllResults, + state: ImmutableErc721State, +} + +fn view_is_approved_for_all_thunk(ctx: &ScViewContext) { + ctx.log("erc721.viewIsApprovedForAll"); + let f = IsApprovedForAllContext { + params: ImmutableIsApprovedForAllParams { + id: OBJ_ID_PARAMS, + }, + results: MutableIsApprovedForAllResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.operator().exists(), "missing mandatory operator"); + ctx.require(f.params.owner().exists(), "missing mandatory owner"); + view_is_approved_for_all(ctx, &f); + ctx.log("erc721.viewIsApprovedForAll ok"); +} + +pub struct NameContext { + results: MutableNameResults, + state: ImmutableErc721State, +} + +fn view_name_thunk(ctx: &ScViewContext) { + ctx.log("erc721.viewName"); + let f = NameContext { + results: MutableNameResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableErc721State { + id: OBJ_ID_STATE, + }, + }; + view_name(ctx, &f); + ctx.log("erc721.viewName ok"); +} + +pub struct OwnerOfContext { + params: ImmutableOwnerOfParams, + results: MutableOwnerOfResults, + state: ImmutableErc721State, +} + +fn view_owner_of_thunk(ctx: &ScViewContext) { + ctx.log("erc721.viewOwnerOf"); + let f = OwnerOfContext { + params: ImmutableOwnerOfParams { + id: OBJ_ID_PARAMS, + }, + results: MutableOwnerOfResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.token_id().exists(), "missing mandatory tokenID"); + view_owner_of(ctx, &f); + ctx.log("erc721.viewOwnerOf ok"); +} + +pub struct SymbolContext { + results: MutableSymbolResults, + state: ImmutableErc721State, +} + +fn view_symbol_thunk(ctx: &ScViewContext) { + ctx.log("erc721.viewSymbol"); + let f = SymbolContext { + results: MutableSymbolResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableErc721State { + id: OBJ_ID_STATE, + }, + }; + view_symbol(ctx, &f); + ctx.log("erc721.viewSymbol ok"); +} + +pub struct TokenURIContext { + params: ImmutableTokenURIParams, + results: MutableTokenURIResults, + state: ImmutableErc721State, +} + +fn view_token_uri_thunk(ctx: &ScViewContext) { + ctx.log("erc721.viewTokenURI"); + let f = TokenURIContext { + params: ImmutableTokenURIParams { + id: OBJ_ID_PARAMS, + }, + results: MutableTokenURIResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableErc721State { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.token_id().exists(), "missing mandatory tokenID"); + view_token_uri(ctx, &f); + ctx.log("erc721.viewTokenURI ok"); +} diff --git a/contracts/wasm/erc721/src/params.rs b/contracts/wasm/erc721/src/params.rs new file mode 100644 index 0000000000..3f9b03d32a --- /dev/null +++ b/contracts/wasm/erc721/src/params.rs @@ -0,0 +1,352 @@ +// 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::*; +use crate::keys::*; +use crate::typedefs::*; + +#[derive(Clone, Copy)] +pub struct ImmutableApproveParams { + pub(crate) id: i32, +} + +impl ImmutableApproveParams { + pub fn approved(&self) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_APPROVED)) + } + + pub fn token_id(&self) -> ScImmutableHash { + ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableApproveParams { + pub(crate) id: i32, +} + +impl MutableApproveParams { + pub fn approved(&self) -> ScMutableAgentID { + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_APPROVED)) + } + + pub fn token_id(&self) -> ScMutableHash { + ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableBurnParams { + pub(crate) id: i32, +} + +impl ImmutableBurnParams { + pub fn token_id(&self) -> ScImmutableHash { + ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableBurnParams { + pub(crate) id: i32, +} + +impl MutableBurnParams { + pub fn token_id(&self) -> ScMutableHash { + ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableInitParams { + pub(crate) id: i32, +} + +impl ImmutableInitParams { + pub fn name(&self) -> ScImmutableString { + ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } + + pub fn symbol(&self) -> ScImmutableString { + ScImmutableString::new(self.id, idx_map(IDX_PARAM_SYMBOL)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableInitParams { + pub(crate) id: i32, +} + +impl MutableInitParams { + pub fn name(&self) -> ScMutableString { + ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } + + pub fn symbol(&self) -> ScMutableString { + ScMutableString::new(self.id, idx_map(IDX_PARAM_SYMBOL)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableMintParams { + pub(crate) id: i32, +} + +impl ImmutableMintParams { + pub fn token_id(&self) -> ScImmutableHash { + ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableMintParams { + pub(crate) id: i32, +} + +impl MutableMintParams { + pub fn token_id(&self) -> ScMutableHash { + ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableSafeTransferFromParams { + pub(crate) id: i32, +} + +impl ImmutableSafeTransferFromParams { + pub fn data(&self) -> ScImmutableBytes { + ScImmutableBytes::new(self.id, idx_map(IDX_PARAM_DATA)) + } + + pub fn from(&self) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_FROM)) + } + + pub fn to(&self) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_TO)) + } + + pub fn token_id(&self) -> ScImmutableHash { + ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableSafeTransferFromParams { + pub(crate) id: i32, +} + +impl MutableSafeTransferFromParams { + pub fn data(&self) -> ScMutableBytes { + ScMutableBytes::new(self.id, idx_map(IDX_PARAM_DATA)) + } + + pub fn from(&self) -> ScMutableAgentID { + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_FROM)) + } + + pub fn to(&self) -> ScMutableAgentID { + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_TO)) + } + + pub fn token_id(&self) -> ScMutableHash { + ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableSetApprovalForAllParams { + pub(crate) id: i32, +} + +impl ImmutableSetApprovalForAllParams { + pub fn approval(&self) -> ScImmutableBool { + ScImmutableBool::new(self.id, idx_map(IDX_PARAM_APPROVAL)) + } + + pub fn operator(&self) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OPERATOR)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableSetApprovalForAllParams { + pub(crate) id: i32, +} + +impl MutableSetApprovalForAllParams { + pub fn approval(&self) -> ScMutableBool { + ScMutableBool::new(self.id, idx_map(IDX_PARAM_APPROVAL)) + } + + pub fn operator(&self) -> ScMutableAgentID { + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OPERATOR)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableTransferFromParams { + pub(crate) id: i32, +} + +impl ImmutableTransferFromParams { + pub fn from(&self) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_FROM)) + } + + pub fn to(&self) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_TO)) + } + + pub fn token_id(&self) -> ScImmutableHash { + ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableTransferFromParams { + pub(crate) id: i32, +} + +impl MutableTransferFromParams { + pub fn from(&self) -> ScMutableAgentID { + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_FROM)) + } + + pub fn to(&self) -> ScMutableAgentID { + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_TO)) + } + + pub fn token_id(&self) -> ScMutableHash { + ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableBalanceOfParams { + pub(crate) id: i32, +} + +impl ImmutableBalanceOfParams { + pub fn owner(&self) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableBalanceOfParams { + pub(crate) id: i32, +} + +impl MutableBalanceOfParams { + pub fn owner(&self) -> ScMutableAgentID { + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableGetApprovedParams { + pub(crate) id: i32, +} + +impl ImmutableGetApprovedParams { + pub fn token_id(&self) -> ScImmutableHash { + ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableGetApprovedParams { + pub(crate) id: i32, +} + +impl MutableGetApprovedParams { + pub fn token_id(&self) -> ScMutableHash { + ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableIsApprovedForAllParams { + pub(crate) id: i32, +} + +impl ImmutableIsApprovedForAllParams { + pub fn operator(&self) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OPERATOR)) + } + + pub fn owner(&self) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableIsApprovedForAllParams { + pub(crate) id: i32, +} + +impl MutableIsApprovedForAllParams { + pub fn operator(&self) -> ScMutableAgentID { + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OPERATOR)) + } + + pub fn owner(&self) -> ScMutableAgentID { + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_OWNER)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableOwnerOfParams { + pub(crate) id: i32, +} + +impl ImmutableOwnerOfParams { + pub fn token_id(&self) -> ScImmutableHash { + ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableOwnerOfParams { + pub(crate) id: i32, +} + +impl MutableOwnerOfParams { + pub fn token_id(&self) -> ScMutableHash { + ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableTokenURIParams { + pub(crate) id: i32, +} + +impl ImmutableTokenURIParams { + pub fn token_id(&self) -> ScImmutableHash { + ScImmutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableTokenURIParams { + pub(crate) id: i32, +} + +impl MutableTokenURIParams { + pub fn token_id(&self) -> ScMutableHash { + ScMutableHash::new(self.id, idx_map(IDX_PARAM_TOKEN_ID)) + } +} diff --git a/contracts/wasm/erc721/src/results.rs b/contracts/wasm/erc721/src/results.rs new file mode 100644 index 0000000000..7a62221715 --- /dev/null +++ b/contracts/wasm/erc721/src/results.rs @@ -0,0 +1,170 @@ +// 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::*; +use crate::keys::*; +use crate::typedefs::*; + +#[derive(Clone, Copy)] +pub struct ImmutableBalanceOfResults { + pub(crate) id: i32, +} + +impl ImmutableBalanceOfResults { + pub fn amount(&self) -> ScImmutableUint64 { + ScImmutableUint64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableBalanceOfResults { + pub(crate) id: i32, +} + +impl MutableBalanceOfResults { + pub fn amount(&self) -> ScMutableUint64 { + ScMutableUint64::new(self.id, idx_map(IDX_RESULT_AMOUNT)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableGetApprovedResults { + pub(crate) id: i32, +} + +impl ImmutableGetApprovedResults { + pub fn approved(&self) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_APPROVED)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableGetApprovedResults { + pub(crate) id: i32, +} + +impl MutableGetApprovedResults { + pub fn approved(&self) -> ScMutableAgentID { + ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_APPROVED)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableIsApprovedForAllResults { + pub(crate) id: i32, +} + +impl ImmutableIsApprovedForAllResults { + pub fn approval(&self) -> ScImmutableBool { + ScImmutableBool::new(self.id, idx_map(IDX_RESULT_APPROVAL)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableIsApprovedForAllResults { + pub(crate) id: i32, +} + +impl MutableIsApprovedForAllResults { + pub fn approval(&self) -> ScMutableBool { + ScMutableBool::new(self.id, idx_map(IDX_RESULT_APPROVAL)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableNameResults { + pub(crate) id: i32, +} + +impl ImmutableNameResults { + pub fn name(&self) -> ScImmutableString { + ScImmutableString::new(self.id, idx_map(IDX_RESULT_NAME)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableNameResults { + pub(crate) id: i32, +} + +impl MutableNameResults { + pub fn name(&self) -> ScMutableString { + ScMutableString::new(self.id, idx_map(IDX_RESULT_NAME)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableOwnerOfResults { + pub(crate) id: i32, +} + +impl ImmutableOwnerOfResults { + pub fn owner(&self) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_OWNER)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableOwnerOfResults { + pub(crate) id: i32, +} + +impl MutableOwnerOfResults { + pub fn owner(&self) -> ScMutableAgentID { + ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_OWNER)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableSymbolResults { + pub(crate) id: i32, +} + +impl ImmutableSymbolResults { + pub fn symbol(&self) -> ScImmutableString { + ScImmutableString::new(self.id, idx_map(IDX_RESULT_SYMBOL)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableSymbolResults { + pub(crate) id: i32, +} + +impl MutableSymbolResults { + pub fn symbol(&self) -> ScMutableString { + ScMutableString::new(self.id, idx_map(IDX_RESULT_SYMBOL)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableTokenURIResults { + pub(crate) id: i32, +} + +impl ImmutableTokenURIResults { + pub fn token_uri(&self) -> ScImmutableString { + ScImmutableString::new(self.id, idx_map(IDX_RESULT_TOKEN_URI)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableTokenURIResults { + pub(crate) id: i32, +} + +impl MutableTokenURIResults { + pub fn token_uri(&self) -> ScMutableString { + ScMutableString::new(self.id, idx_map(IDX_RESULT_TOKEN_URI)) + } +} diff --git a/contracts/wasm/erc721/src/state.rs b/contracts/wasm/erc721/src/state.rs new file mode 100644 index 0000000000..134d226129 --- /dev/null +++ b/contracts/wasm/erc721/src/state.rs @@ -0,0 +1,160 @@ +// 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::*; +use crate::keys::*; +use crate::typedefs::*; + +pub struct MapHashToImmutableAgentID { + pub(crate) obj_id: i32, +} + +impl MapHashToImmutableAgentID { + pub fn get_agent_id(&self, key: &ScHash) -> ScImmutableAgentID { + ScImmutableAgentID::new(self.obj_id, key.get_key_id()) + } +} + +pub struct MapAgentIDToImmutableOperators { + pub(crate) obj_id: i32, +} + +impl MapAgentIDToImmutableOperators { + pub fn get_operators(&self, key: &ScAgentID) -> ImmutableOperators { + let sub_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_MAP); + ImmutableOperators { obj_id: sub_id } + } +} + +pub struct MapAgentIDToImmutableUint64 { + pub(crate) obj_id: i32, +} + +impl MapAgentIDToImmutableUint64 { + pub fn get_uint64(&self, key: &ScAgentID) -> ScImmutableUint64 { + ScImmutableUint64::new(self.obj_id, key.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableErc721State { + pub(crate) id: i32, +} + +impl ImmutableErc721State { + pub fn approved_accounts(&self) -> MapHashToImmutableAgentID { + let map_id = get_object_id(self.id, idx_map(IDX_STATE_APPROVED_ACCOUNTS), 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); + 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); + MapAgentIDToImmutableUint64 { obj_id: map_id } + } + + pub fn name(&self) -> ScImmutableString { + ScImmutableString::new(self.id, idx_map(IDX_STATE_NAME)) + } + + pub fn owners(&self) -> MapHashToImmutableAgentID { + let map_id = get_object_id(self.id, idx_map(IDX_STATE_OWNERS), TYPE_MAP); + MapHashToImmutableAgentID { obj_id: map_id } + } + + pub fn symbol(&self) -> ScImmutableString { + ScImmutableString::new(self.id, idx_map(IDX_STATE_SYMBOL)) + } +} + +pub struct MapHashToMutableAgentID { + pub(crate) obj_id: i32, +} + +impl MapHashToMutableAgentID { + pub fn clear(&self) { + clear(self.obj_id); + } + + pub fn get_agent_id(&self, key: &ScHash) -> ScMutableAgentID { + ScMutableAgentID::new(self.obj_id, key.get_key_id()) + } +} + +pub struct MapAgentIDToMutableOperators { + pub(crate) obj_id: i32, +} + +impl MapAgentIDToMutableOperators { + pub fn clear(&self) { + clear(self.obj_id); + } + + pub fn get_operators(&self, key: &ScAgentID) -> MutableOperators { + let sub_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_MAP); + MutableOperators { obj_id: sub_id } + } +} + +pub struct MapAgentIDToMutableUint64 { + pub(crate) obj_id: i32, +} + +impl MapAgentIDToMutableUint64 { + pub fn clear(&self) { + clear(self.obj_id); + } + + pub fn get_uint64(&self, key: &ScAgentID) -> ScMutableUint64 { + ScMutableUint64::new(self.obj_id, key.get_key_id()) + } +} + +#[derive(Clone, Copy)] +pub struct MutableErc721State { + pub(crate) id: i32, +} + +impl MutableErc721State { + pub fn approved_accounts(&self) -> MapHashToMutableAgentID { + let map_id = get_object_id(self.id, idx_map(IDX_STATE_APPROVED_ACCOUNTS), 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); + 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); + MapAgentIDToMutableUint64 { obj_id: map_id } + } + + pub fn name(&self) -> ScMutableString { + ScMutableString::new(self.id, idx_map(IDX_STATE_NAME)) + } + + pub fn owners(&self) -> MapHashToMutableAgentID { + let map_id = get_object_id(self.id, idx_map(IDX_STATE_OWNERS), TYPE_MAP); + MapHashToMutableAgentID { obj_id: map_id } + } + + pub fn symbol(&self) -> ScMutableString { + ScMutableString::new(self.id, idx_map(IDX_STATE_SYMBOL)) + } +} diff --git a/contracts/wasm/erc721/src/typedefs.rs b/contracts/wasm/erc721/src/typedefs.rs new file mode 100644 index 0000000000..33eacd20c5 --- /dev/null +++ b/contracts/wasm/erc721/src/typedefs.rs @@ -0,0 +1,39 @@ +// 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::*; +use wasmlib::host::*; + +pub struct MapAgentIDToImmutableBool { + pub(crate) obj_id: i32, +} + +impl MapAgentIDToImmutableBool { + pub fn get_bool(&self, key: &ScAgentID) -> ScImmutableBool { + ScImmutableBool::new(self.obj_id, key.get_key_id()) + } +} + +pub type ImmutableOperators = MapAgentIDToImmutableBool; + +pub struct MapAgentIDToMutableBool { + pub(crate) obj_id: i32, +} + +impl MapAgentIDToMutableBool { + pub fn clear(&self) { + clear(self.obj_id); + } + + pub fn get_bool(&self, key: &ScAgentID) -> ScMutableBool { + ScMutableBool::new(self.obj_id, key.get_key_id()) + } +} + +pub type MutableOperators = MapAgentIDToMutableBool; diff --git a/contracts/wasm/erc721/test/erc721_bg.wasm b/contracts/wasm/erc721/test/erc721_bg.wasm new file mode 100644 index 0000000000..5b758abf0e Binary files /dev/null and b/contracts/wasm/erc721/test/erc721_bg.wasm differ diff --git a/contracts/wasm/erc721/test/erc721_test.go b/contracts/wasm/erc721/test/erc721_test.go new file mode 100644 index 0000000000..b1f33b11ce --- /dev/null +++ b/contracts/wasm/erc721/test/erc721_test.go @@ -0,0 +1,216 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package test + +import ( + "testing" + + "github.com/iotaledger/wasp/contracts/wasm/erc721/go/erc721" + "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + "github.com/iotaledger/wasp/packages/vm/wasmsolo" + "github.com/stretchr/testify/require" +) + +func TestDeploy(t *testing.T) { + ctx := setup(t) + require.NoError(t, ctx.ContractExists(erc721.ScName)) +} + +func TestMint(t *testing.T) { + ctx := setup(t) + owner := ctx.NewSoloAgent() + tokenID := wasmlib.NewScHashFromBytes(owner.ScAgentID().Bytes()[:32]) + mint(ctx, owner, tokenID) + require.NoError(t, ctx.Err) +} + +func TestApprove(t *testing.T) { + ctx := setup(t) + owner := ctx.NewSoloAgent() + tokenID := wasmlib.NewScHashFromBytes(owner.ScAgentID().Bytes()[:32]) + mint(ctx, owner, tokenID) + require.NoError(t, ctx.Err) + + require.Nil(t, getApproved(t, ctx, tokenID)) + + approve(ctx, owner, owner, tokenID) + require.Error(t, ctx.Err) + + approved := getApproved(t, ctx, tokenID) + require.Nil(t, approved) + + friend1 := ctx.NewSoloAgent() + approve(ctx, owner, friend1, tokenID) + require.NoError(t, ctx.Err) + + approved = getApproved(t, ctx, tokenID) + require.NotNil(t, approved) + require.EqualValues(t, *approved, friend1.ScAgentID()) + + approve(ctx, owner, nil, tokenID) + require.NoError(t, ctx.Err) + + approved = getApproved(t, ctx, tokenID) + require.Nil(t, approved) +} + +func TestApproveAll(t *testing.T) { + ctx := setup(t) + owner := ctx.NewSoloAgent() + tokenID := wasmlib.NewScHashFromBytes(owner.ScAgentID().Bytes()[:32]) + mint(ctx, owner, tokenID) + require.NoError(t, ctx.Err) + + friend1 := ctx.NewSoloAgent() + require.False(t, isApprovedForAll(t, ctx, owner, friend1)) + + friend2 := ctx.NewSoloAgent() + require.False(t, isApprovedForAll(t, ctx, owner, friend2)) + + // approve friend1 + setApprovalForAll(ctx, owner, friend1, true) + require.NoError(t, ctx.Err) + + require.True(t, isApprovedForAll(t, ctx, owner, friend1)) + require.False(t, isApprovedForAll(t, ctx, owner, friend2)) + + // approve friend2 + setApprovalForAll(ctx, owner, friend2, true) + require.NoError(t, ctx.Err) + + require.True(t, isApprovedForAll(t, ctx, owner, friend1)) + require.True(t, isApprovedForAll(t, ctx, owner, friend2)) + + // unapprove friend1 + setApprovalForAll(ctx, owner, friend1, false) + require.NoError(t, ctx.Err) + + require.False(t, isApprovedForAll(t, ctx, owner, friend1)) + require.True(t, isApprovedForAll(t, ctx, owner, friend2)) + + // unapprove friend2 + setApprovalForAll(ctx, owner, friend2, false) + require.NoError(t, ctx.Err) + + require.False(t, isApprovedForAll(t, ctx, owner, friend1)) + require.False(t, isApprovedForAll(t, ctx, owner, friend2)) +} + +func TestTransferFrom(t *testing.T) { + ctx := setup(t) + owner := ctx.NewSoloAgent() + tokenID := wasmlib.NewScHashFromBytes(owner.ScAgentID().Bytes()[:32]) + mint(ctx, owner, tokenID) + require.NoError(t, ctx.Err) + + // verify current ownership + currentOwner := ownerOf(t, ctx, tokenID) + require.EqualValues(t, owner.ScAgentID(), currentOwner) + + // no one approved for token + require.Nil(t, getApproved(t, ctx, tokenID)) + + friend1 := ctx.NewSoloAgent() + + // try to transfer without approval, should fail + transferFrom(ctx, friend1, owner, friend1, tokenID) + require.Error(t, ctx.Err) + + // verify current ownership has not changed + currentOwner = ownerOf(t, ctx, tokenID) + require.EqualValues(t, owner.ScAgentID(), currentOwner) + + // have owner himself transfer token, should succeed + transferFrom(ctx, owner, owner, friend1, tokenID) + require.NoError(t, ctx.Err) + + // verify new owner + currentOwner = ownerOf(t, ctx, tokenID) + require.EqualValues(t, friend1.ScAgentID(), currentOwner) + + // have previous try to transfer token back, should fail + transferFrom(ctx, owner, friend1, owner, tokenID) + require.Error(t, ctx.Err) + + // verify new owner is still owner + currentOwner = ownerOf(t, ctx, tokenID) + require.EqualValues(t, friend1.ScAgentID(), currentOwner) + + // have new owner transfer token back, should succeed + transferFrom(ctx, friend1, friend1, owner, tokenID) + require.NoError(t, ctx.Err) + + // verify ownership has returned to first owner + currentOwner = ownerOf(t, ctx, tokenID) + require.EqualValues(t, owner.ScAgentID(), currentOwner) +} + +func setup(t *testing.T) *wasmsolo.SoloContext { + init := erc721.ScFuncs.Init(nil) + init.Params.Name().SetValue("My Valuable NFT") + init.Params.Symbol().SetValue("MVNFT") + ctx := wasmsolo.NewSoloContext(t, erc721.ScName, erc721.OnLoad, init.Func) + require.NoError(t, ctx.Err) + return ctx +} + +func approve(ctx *wasmsolo.SoloContext, owner, approved *wasmsolo.SoloAgent, tokenID wasmlib.ScHash) { + f := erc721.ScFuncs.Approve(ctx.Sign(owner)) + if approved != nil { + f.Params.Approved().SetValue(approved.ScAgentID()) + } + f.Params.TokenID().SetValue(tokenID) + f.Func.TransferIotas(1).Post() +} + +func getApproved(t *testing.T, ctx *wasmsolo.SoloContext, tokenID wasmlib.ScHash) *wasmlib.ScAgentID { + v := erc721.ScFuncs.GetApproved(ctx) + v.Params.TokenID().SetValue(tokenID) + v.Func.Call() + require.NoError(t, ctx.Err) + approved := v.Results.Approved() + if !approved.Exists() { + return nil + } + ret := approved.Value() + return &ret +} + +func isApprovedForAll(t *testing.T, ctx *wasmsolo.SoloContext, owner, friend *wasmsolo.SoloAgent) bool { + v := erc721.ScFuncs.IsApprovedForAll(ctx) + v.Params.Owner().SetValue(owner.ScAgentID()) + v.Params.Operator().SetValue(friend.ScAgentID()) + v.Func.Call() + require.NoError(t, ctx.Err) + return v.Results.Approval().Value() +} + +func mint(ctx *wasmsolo.SoloContext, owner *wasmsolo.SoloAgent, tokenID wasmlib.ScHash) { + f := erc721.ScFuncs.Mint(ctx.Sign(owner)) + f.Params.TokenID().SetValue(tokenID) + f.Func.TransferIotas(1).Post() +} + +func ownerOf(t *testing.T, ctx *wasmsolo.SoloContext, tokenID wasmlib.ScHash) wasmlib.ScAgentID { + v := erc721.ScFuncs.OwnerOf(ctx) + v.Params.TokenID().SetValue(tokenID) + v.Func.Call() + require.NoError(t, ctx.Err) + return v.Results.Owner().Value() +} + +func setApprovalForAll(ctx *wasmsolo.SoloContext, owner, operator *wasmsolo.SoloAgent, approval bool) { + f := erc721.ScFuncs.SetApprovalForAll(ctx.Sign(owner)) + f.Params.Operator().SetValue(operator.ScAgentID()) + f.Params.Approval().SetValue(approval) + f.Func.TransferIotas(1).Post() +} + +func transferFrom(ctx *wasmsolo.SoloContext, sender, from, to *wasmsolo.SoloAgent, tokenID wasmlib.ScHash) { + f := erc721.ScFuncs.TransferFrom(ctx.Sign(sender)) + f.Params.From().SetValue(from.ScAgentID()) + f.Params.To().SetValue(to.ScAgentID()) + f.Params.TokenID().SetValue(tokenID) + f.Func.TransferIotas(1).Post() +} diff --git a/contracts/wasm/erc721/ts/erc721/consts.ts b/contracts/wasm/erc721/ts/erc721/consts.ts new file mode 100644 index 0000000000..443f42c825 --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/consts.ts @@ -0,0 +1,68 @@ +// 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 const ScName = "erc721"; +export const ScDescription = "ERC-721 NFT PoC for IOTA Smart Contracts"; +export const HScName = new wasmlib.ScHname(0xd967c216); + +export const ParamApproval = "approval"; +export const ParamApproved = "approved"; +export const ParamData = "data"; +export const ParamFrom = "from"; +export const ParamName = "n"; +export const ParamOperator = "operator"; +export const ParamOwner = "owner"; +export const ParamSymbol = "s"; +export const ParamTo = "to"; +export const ParamTokenID = "tokenID"; + +export const ResultAmount = "amount"; +export const ResultApproval = "approval"; +export const ResultApproved = "approved"; +export const ResultName = "name"; +export const ResultOwner = "owner"; +export const ResultSymbol = "symbol"; +export const ResultTokenURI = "tokenURI"; + +export const StateApprovedAccounts = "approvedAccounts"; +export const StateApprovedOperators = "approvedOperators"; +export const StateBalances = "balances"; +export const StateName = "name"; +export const StateOwners = "owners"; +export const StateSymbol = "symbol"; + +export const FuncApprove = "approve"; +export const FuncBurn = "burn"; +export const FuncInit = "init"; +export const FuncMint = "mint"; +export const FuncSafeTransferFrom = "safeTransferFrom"; +export const FuncSetApprovalForAll = "setApprovalForAll"; +export const FuncTransferFrom = "transferFrom"; +export const ViewBalanceOf = "balanceOf"; +export const ViewGetApproved = "getApproved"; +export const ViewIsApprovedForAll = "isApprovedForAll"; +export const ViewName = "name"; +export const ViewOwnerOf = "ownerOf"; +export const ViewSymbol = "symbol"; +export const ViewTokenURI = "tokenURI"; + +export const HFuncApprove = new wasmlib.ScHname(0xa0661268); +export const HFuncBurn = new wasmlib.ScHname(0x7bc1efb1); +export const HFuncInit = new wasmlib.ScHname(0x1f44d644); +export const HFuncMint = new wasmlib.ScHname(0xa29addcf); +export const HFuncSafeTransferFrom = new wasmlib.ScHname(0x130ce158); +export const HFuncSetApprovalForAll = new wasmlib.ScHname(0xb8d8c776); +export const HFuncTransferFrom = new wasmlib.ScHname(0xd5e0a602); +export const HViewBalanceOf = new wasmlib.ScHname(0x67ef8df4); +export const HViewGetApproved = new wasmlib.ScHname(0xbe34b6ba); +export const HViewIsApprovedForAll = new wasmlib.ScHname(0x3251b0f0); +export const HViewName = new wasmlib.ScHname(0x0df7da3a); +export const HViewOwnerOf = new wasmlib.ScHname(0x1246f5ad); +export const HViewSymbol = new wasmlib.ScHname(0x3e93d19b); +export const HViewTokenURI = new wasmlib.ScHname(0x4e1a7397); diff --git a/contracts/wasm/erc721/ts/erc721/contract.ts b/contracts/wasm/erc721/ts/erc721/contract.ts new file mode 100644 index 0000000000..4f33962168 --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/contract.ts @@ -0,0 +1,252 @@ +// 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"; +import * as sc from "./index"; + +export class ApproveCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncApprove); + params: sc.MutableApproveParams = new sc.MutableApproveParams(); +} + +export class ApproveContext { + events: sc.Erc721Events = new sc.Erc721Events(); + params: sc.ImmutableApproveParams = new sc.ImmutableApproveParams(); + state: sc.MutableErc721State = new sc.MutableErc721State(); +} + +export class BurnCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncBurn); + params: sc.MutableBurnParams = new sc.MutableBurnParams(); +} + +export class BurnContext { + events: sc.Erc721Events = new sc.Erc721Events(); + params: sc.ImmutableBurnParams = new sc.ImmutableBurnParams(); + state: sc.MutableErc721State = new sc.MutableErc721State(); +} + +export class InitCall { + func: wasmlib.ScInitFunc = new wasmlib.ScInitFunc(sc.HScName, sc.HFuncInit); + params: sc.MutableInitParams = new sc.MutableInitParams(); +} + +export class InitContext { + events: sc.Erc721Events = new sc.Erc721Events(); + params: sc.ImmutableInitParams = new sc.ImmutableInitParams(); + state: sc.MutableErc721State = new sc.MutableErc721State(); +} + +export class MintCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncMint); + params: sc.MutableMintParams = new sc.MutableMintParams(); +} + +export class MintContext { + events: sc.Erc721Events = new sc.Erc721Events(); + params: sc.ImmutableMintParams = new sc.ImmutableMintParams(); + state: sc.MutableErc721State = new sc.MutableErc721State(); +} + +export class SafeTransferFromCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSafeTransferFrom); + params: sc.MutableSafeTransferFromParams = new sc.MutableSafeTransferFromParams(); +} + +export class SafeTransferFromContext { + events: sc.Erc721Events = new sc.Erc721Events(); + params: sc.ImmutableSafeTransferFromParams = new sc.ImmutableSafeTransferFromParams(); + state: sc.MutableErc721State = new sc.MutableErc721State(); +} + +export class SetApprovalForAllCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetApprovalForAll); + params: sc.MutableSetApprovalForAllParams = new sc.MutableSetApprovalForAllParams(); +} + +export class SetApprovalForAllContext { + events: sc.Erc721Events = new sc.Erc721Events(); + params: sc.ImmutableSetApprovalForAllParams = new sc.ImmutableSetApprovalForAllParams(); + state: sc.MutableErc721State = new sc.MutableErc721State(); +} + +export class TransferFromCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTransferFrom); + params: sc.MutableTransferFromParams = new sc.MutableTransferFromParams(); +} + +export class TransferFromContext { + events: sc.Erc721Events = new sc.Erc721Events(); + params: sc.ImmutableTransferFromParams = new sc.ImmutableTransferFromParams(); + state: sc.MutableErc721State = new sc.MutableErc721State(); +} + +export class BalanceOfCall { + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewBalanceOf); + params: sc.MutableBalanceOfParams = new sc.MutableBalanceOfParams(); + results: sc.ImmutableBalanceOfResults = new sc.ImmutableBalanceOfResults(); +} + +export class BalanceOfContext { + params: sc.ImmutableBalanceOfParams = new sc.ImmutableBalanceOfParams(); + results: sc.MutableBalanceOfResults = new sc.MutableBalanceOfResults(); + state: sc.ImmutableErc721State = new sc.ImmutableErc721State(); +} + +export class GetApprovedCall { + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetApproved); + params: sc.MutableGetApprovedParams = new sc.MutableGetApprovedParams(); + results: sc.ImmutableGetApprovedResults = new sc.ImmutableGetApprovedResults(); +} + +export class GetApprovedContext { + params: sc.ImmutableGetApprovedParams = new sc.ImmutableGetApprovedParams(); + results: sc.MutableGetApprovedResults = new sc.MutableGetApprovedResults(); + state: sc.ImmutableErc721State = new sc.ImmutableErc721State(); +} + +export class IsApprovedForAllCall { + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewIsApprovedForAll); + params: sc.MutableIsApprovedForAllParams = new sc.MutableIsApprovedForAllParams(); + results: sc.ImmutableIsApprovedForAllResults = new sc.ImmutableIsApprovedForAllResults(); +} + +export class IsApprovedForAllContext { + params: sc.ImmutableIsApprovedForAllParams = new sc.ImmutableIsApprovedForAllParams(); + results: sc.MutableIsApprovedForAllResults = new sc.MutableIsApprovedForAllResults(); + state: sc.ImmutableErc721State = new sc.ImmutableErc721State(); +} + +export class NameCall { + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewName); + results: sc.ImmutableNameResults = new sc.ImmutableNameResults(); +} + +export class NameContext { + results: sc.MutableNameResults = new sc.MutableNameResults(); + state: sc.ImmutableErc721State = new sc.ImmutableErc721State(); +} + +export class OwnerOfCall { + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewOwnerOf); + params: sc.MutableOwnerOfParams = new sc.MutableOwnerOfParams(); + results: sc.ImmutableOwnerOfResults = new sc.ImmutableOwnerOfResults(); +} + +export class OwnerOfContext { + params: sc.ImmutableOwnerOfParams = new sc.ImmutableOwnerOfParams(); + results: sc.MutableOwnerOfResults = new sc.MutableOwnerOfResults(); + state: sc.ImmutableErc721State = new sc.ImmutableErc721State(); +} + +export class SymbolCall { + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewSymbol); + results: sc.ImmutableSymbolResults = new sc.ImmutableSymbolResults(); +} + +export class SymbolContext { + results: sc.MutableSymbolResults = new sc.MutableSymbolResults(); + state: sc.ImmutableErc721State = new sc.ImmutableErc721State(); +} + +export class TokenURICall { + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTokenURI); + params: sc.MutableTokenURIParams = new sc.MutableTokenURIParams(); + results: sc.ImmutableTokenURIResults = new sc.ImmutableTokenURIResults(); +} + +export class TokenURIContext { + params: sc.ImmutableTokenURIParams = new sc.ImmutableTokenURIParams(); + results: sc.MutableTokenURIResults = new sc.MutableTokenURIResults(); + state: sc.ImmutableErc721State = new sc.ImmutableErc721State(); +} + +export class ScFuncs { + static approve(ctx: wasmlib.ScFuncCallContext): ApproveCall { + let f = new ApproveCall(); + f.func.setPtrs(f.params, null); + return f; + } + + static burn(ctx: wasmlib.ScFuncCallContext): BurnCall { + let f = new BurnCall(); + f.func.setPtrs(f.params, null); + return f; + } + + static init(ctx: wasmlib.ScFuncCallContext): InitCall { + let f = new InitCall(); + f.func.setPtrs(f.params, null); + return f; + } + + static mint(ctx: wasmlib.ScFuncCallContext): MintCall { + let f = new MintCall(); + f.func.setPtrs(f.params, null); + return f; + } + + static safeTransferFrom(ctx: wasmlib.ScFuncCallContext): SafeTransferFromCall { + let f = new SafeTransferFromCall(); + f.func.setPtrs(f.params, null); + return f; + } + + static setApprovalForAll(ctx: wasmlib.ScFuncCallContext): SetApprovalForAllCall { + let f = new SetApprovalForAllCall(); + f.func.setPtrs(f.params, null); + return f; + } + + static transferFrom(ctx: wasmlib.ScFuncCallContext): TransferFromCall { + let f = new TransferFromCall(); + f.func.setPtrs(f.params, null); + return f; + } + + static balanceOf(ctx: wasmlib.ScViewCallContext): BalanceOfCall { + let f = new BalanceOfCall(); + f.func.setPtrs(f.params, f.results); + return f; + } + + static getApproved(ctx: wasmlib.ScViewCallContext): GetApprovedCall { + let f = new GetApprovedCall(); + f.func.setPtrs(f.params, f.results); + return f; + } + + static isApprovedForAll(ctx: wasmlib.ScViewCallContext): IsApprovedForAllCall { + let f = new IsApprovedForAllCall(); + f.func.setPtrs(f.params, f.results); + return f; + } + + static name(ctx: wasmlib.ScViewCallContext): NameCall { + let f = new NameCall(); + f.func.setPtrs(null, f.results); + return f; + } + + static ownerOf(ctx: wasmlib.ScViewCallContext): OwnerOfCall { + let f = new OwnerOfCall(); + f.func.setPtrs(f.params, f.results); + return f; + } + + static symbol(ctx: wasmlib.ScViewCallContext): SymbolCall { + let f = new SymbolCall(); + f.func.setPtrs(null, f.results); + return f; + } + + static tokenURI(ctx: wasmlib.ScViewCallContext): TokenURICall { + let f = new TokenURICall(); + f.func.setPtrs(f.params, f.results); + return f; + } +} diff --git a/contracts/wasm/erc721/ts/erc721/erc721.ts b/contracts/wasm/erc721/ts/erc721/erc721.ts new file mode 100644 index 0000000000..1cd4d73655 --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/erc721.ts @@ -0,0 +1,242 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as wasmlib from "wasmlib"; +import * as sc from "./index"; + +// Follows ERC-721 standard as closely as possible +// https://eips.ethereum.org/EIPS/eip-721 +// Notable changes w.r.t. ERC-721: +// - tokenID is Hash instead of int256 +// - balance amounts are Uint64 instead of int256 +// - all address accounts are replaced with AgentID accounts +// - for consistency and to reduce confusion: +// use 'approved' when it is an AgentID +// use 'approval' when it is a Bool + +// set the required base URI, to which the base58 encoded token ID will be concatenated +const BASE_URI = "my/special/base/uri/"; +const ZERO = new wasmlib.ScAgentID() + +/////////////////////////// HELPER FUNCTIONS //////////////////////////// + +// checks if caller is owner, or one of its delegated operators +function canOperate(state: sc.MutableErc721State, caller: wasmlib.ScAgentID, owner: wasmlib.ScAgentID): boolean { + if (caller.equals(owner)) { + return true; + } + + let operators = state.approvedOperators().getOperators(owner); + return operators.getBool(caller).value(); +} + +// checks if caller is owner, or one of its delegated operators, or approved account for tokenID +function canTransfer(state: sc.MutableErc721State, caller: wasmlib.ScAgentID, owner: wasmlib.ScAgentID, tokenID: wasmlib.ScHash): boolean { + if (canOperate(state, caller, owner)) { + return true; + } + + let controller = state.approvedAccounts().getAgentID(tokenID); + return controller.value().equals(caller); +} + +// common code for safeTransferFrom and transferFrom +function transfer(ctx: wasmlib.ScFuncContext, state: sc.MutableErc721State, from: wasmlib.ScAgentID, to: wasmlib.ScAgentID, tokenID: wasmlib.ScHash): void { + let tokenOwner = state.owners().getAgentID(tokenID); + ctx.require(tokenOwner.exists(), "tokenID does not exist"); + + let owner = tokenOwner.value(); + ctx.require(canTransfer(state, ctx.caller(), owner, tokenID), + "not owner, operator, or approved"); + + ctx.require(owner.equals(from), "from is not owner"); + //TODO: ctx.require(to == , "invalid 'to' agentid"); + + let balanceFrom = state.balances().getUint64(from); + let balanceTo = state.balances().getUint64(to); + + balanceFrom.setValue(balanceFrom.value() - 1); + balanceTo.setValue(balanceTo.value() + 1); + + tokenOwner.setValue(to); + + let events = new sc.Erc721Events(); + // remove approval if it exists + let currentApproved = state.approvedAccounts().getAgentID(tokenID); + if (currentApproved.exists()) { + currentApproved.delete(); + events.approval(ZERO, owner, tokenID); + } + + events.transfer(from, to, tokenID); +} + +/////////////////////////// SC FUNCS //////////////////////////// + +// Gives permission to to to transfer tokenID token to another account. +// The approval is cleared when optional approval account is omitted. +// The approval will be cleared when the token is transferred. +export function funcApprove(ctx: wasmlib.ScFuncContext, f: sc.ApproveContext): void { + let tokenID = f.params.tokenID().value(); + let tokenOwner = f.state.owners().getAgentID(tokenID); + ctx.require(tokenOwner.exists(), "tokenID does not exist"); + let owner = tokenOwner.value(); + ctx.require(canOperate(f.state, ctx.caller(), owner), "not owner or operator"); + + let approved = f.params.approved(); + if (!approved.exists()) { + // remove approval if it exists + let currentApproved = f.state.approvedAccounts().getAgentID(tokenID); + if (currentApproved.exists()) { + currentApproved.delete(); + f.events.approval(ZERO, owner, tokenID); + } + return; + } + + let account = approved.value(); + ctx.require(!owner.equals(account), "approved account equals owner"); + + f.state.approvedAccounts().getAgentID(tokenID).setValue(account); + f.events.approval(account, owner, tokenID); +} + +// Destroys tokenID. The approval is cleared when the token is burned. +export function funcBurn(ctx: wasmlib.ScFuncContext, f: sc.BurnContext): void { + let tokenID = f.params.tokenID().value(); + let owner = f.state.owners().getAgentID(tokenID).value(); + ctx.require(!owner.equals(ZERO), "tokenID does not exist"); + ctx.require(ctx.caller().equals(owner), "caller is not owner"); + + // remove approval if it exists + let currentApproved = f.state.approvedAccounts().getAgentID(tokenID); + if (currentApproved.exists()) { + currentApproved.delete(); + f.events.approval(ZERO, owner, tokenID); + } + + let balance = f.state.balances().getUint64(owner); + balance.setValue(balance.value() - 1); + + f.state.owners().getAgentID(tokenID).delete(); + f.events.transfer(owner, ZERO, tokenID); +} + +// Initializes the contract by setting a name and a symbol to the token collection. +export function funcInit(ctx: wasmlib.ScFuncContext, f: sc.InitContext): void { + let name = f.params.name().value(); + let symbol = f.params.symbol().value(); + + f.state.name().setValue(name); + f.state.symbol().setValue(symbol); + + f.events.init(name, symbol); +} + +// Mints tokenID and transfers it to caller as new owner. +export function funcMint(ctx: wasmlib.ScFuncContext, f: sc.MintContext): void { + let tokenID = f.params.tokenID().value(); + let tokenOwner = f.state.owners().getAgentID(tokenID); + ctx.require(!tokenOwner.exists(), "tokenID already minted"); + + let owner = ctx.caller(); + tokenOwner.setValue(owner); + let balance = f.state.balances().getUint64(owner); + balance.setValue(balance.value() + 1); + + f.events.transfer(ZERO, owner, tokenID); + // if (!owner.isAddress()) { + // //TODO interpret to as SC address and call its onERC721Received() function + // } +} + +// Safely transfers tokenID token from from to to, checking first that contract +// recipients are aware of the ERC721 protocol to prevent tokens from being forever locked. +export function funcSafeTransferFrom(ctx: wasmlib.ScFuncContext, f: sc.SafeTransferFromContext): void { + let from = f.params.from().value(); + let to = f.params.to().value(); + let tokenID = f.params.tokenID().value(); + transfer(ctx, f.state, from, to, tokenID); + // if (!to.isAddress()) { + // //TODO interpret to as SC address and call its onERC721Received() function + // } +} + +// Approve or remove operator as an operator for the caller. +export function funcSetApprovalForAll(ctx: wasmlib.ScFuncContext, f: sc.SetApprovalForAllContext): void { + let owner = ctx.caller(); + let operator = f.params.operator().value(); + ctx.require(!owner.equals(operator), "owner equals operator"); + + let approval = f.params.approval().value(); + let approvalsByCaller = f.state.approvedOperators().getOperators(owner); + approvalsByCaller.getBool(operator).setValue(approval); + + f.events.approvalForAll(approval, operator, owner); +} + +// Transfers tokenID token from from to to. +export function funcTransferFrom(ctx: wasmlib.ScFuncContext, f: sc.TransferFromContext): void { + let from = f.params.from().value(); + let to = f.params.to().value(); + let tokenID = f.params.tokenID().value(); + transfer(ctx, f.state, from, to, tokenID); +} + +/////////////////////////// SC VIEWS //////////////////////////// + +// Returns the number of tokens in owner's account if the owner exists. +export function viewBalanceOf(ctx: wasmlib.ScViewContext, f: sc.BalanceOfContext): void { + let owner = f.params.owner().value(); + let balance = f.state.balances().getUint64(owner); + if (balance.exists()) { + f.results.amount().setValue(balance.value()); + } +} + +// Returns the approved account for tokenID token if there is one. +export function viewGetApproved(ctx: wasmlib.ScViewContext, f: sc.GetApprovedContext): void { + let tokenID = f.params.tokenID().value(); + let approved = f.state.approvedAccounts().getAgentID(tokenID); + if (approved.exists()) { + f.results.approved().setValue(approved.value()); + } +} + +// Returns if the operator is allowed to manage all the assets of owner. +export function viewIsApprovedForAll(ctx: wasmlib.ScViewContext, f: sc.IsApprovedForAllContext): void { + let owner = f.params.owner().value(); + let operator = f.params.operator().value(); + let operators = f.state.approvedOperators().getOperators(owner); + let approval = operators.getBool(operator); + if (approval.exists()) { + f.results.approval().setValue(approval.value()); + } +} + +// Returns the token collection name. +export function viewName(ctx: wasmlib.ScViewContext, f: sc.NameContext): void { + f.results.name().setValue(f.state.name().value()); +} + +// Returns the owner of the tokenID token if the token exists. +export function viewOwnerOf(ctx: wasmlib.ScViewContext, f: sc.OwnerOfContext): void { + let tokenID = f.params.tokenID().value(); + let owner = f.state.owners().getAgentID(tokenID); + if (owner.exists()) { + f.results.owner().setValue(owner.value()); + } +} + +// Returns the token collection symbol. +export function viewSymbol(ctx: wasmlib.ScViewContext, f: sc.SymbolContext): void { + f.results.symbol().setValue(f.state.symbol().value()); +} + +// Returns the Uniform Resource Identifier (URI) for tokenID token if the token exists. +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()); + } +} diff --git a/contracts/wasm/erc721/ts/erc721/events.ts b/contracts/wasm/erc721/ts/erc721/events.ts new file mode 100644 index 0000000000..6407257600 --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/events.ts @@ -0,0 +1,50 @@ +// 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 Erc721Events { + + approval(approved: wasmlib.ScAgentID, owner: wasmlib.ScAgentID, tokenID: wasmlib.ScHash): void { + new wasmlib.EventEncoder("erc721.approval"). + agentID(approved). + agentID(owner). + hash(tokenID). + emit(); + } + + approvalForAll(approval: bool, operator: wasmlib.ScAgentID, owner: wasmlib.ScAgentID): void { + new wasmlib.EventEncoder("erc721.approvalForAll"). + bool(approval). + agentID(operator). + agentID(owner). + emit(); + } + + init(name: string, symbol: string): void { + new wasmlib.EventEncoder("erc721.init"). + string(name). + string(symbol). + emit(); + } + + mint(balance: u64, owner: wasmlib.ScAgentID, tokenID: wasmlib.ScHash): void { + new wasmlib.EventEncoder("erc721.mint"). + uint64(balance). + agentID(owner). + hash(tokenID). + emit(); + } + + transfer(from: wasmlib.ScAgentID, to: wasmlib.ScAgentID, tokenID: wasmlib.ScHash): void { + new wasmlib.EventEncoder("erc721.transfer"). + agentID(from). + agentID(to). + hash(tokenID). + emit(); + } +} diff --git a/contracts/wasm/erc721/ts/erc721/index.ts b/contracts/wasm/erc721/ts/erc721/index.ts new file mode 100644 index 0000000000..11f170837f --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/index.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 + +export * from "./erc721"; + +export * from "./consts"; +export * from "./contract"; +export * from "./events"; +export * from "./keys"; +export * from "./lib"; +export * from "./params"; +export * from "./results"; +export * from "./state"; +export * from "./typedefs"; diff --git a/contracts/wasm/erc721/ts/erc721/keys.ts b/contracts/wasm/erc721/ts/erc721/keys.ts new file mode 100644 index 0000000000..d7fc649be8 --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/keys.ts @@ -0,0 +1,63 @@ +// 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"; +import * as sc from "./index"; + +export const IdxParamApproval = 0; +export const IdxParamApproved = 1; +export const IdxParamData = 2; +export const IdxParamFrom = 3; +export const IdxParamName = 4; +export const IdxParamOperator = 5; +export const IdxParamOwner = 6; +export const IdxParamSymbol = 7; +export const IdxParamTo = 8; +export const IdxParamTokenID = 9; + +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 IdxStateApprovedAccounts = 17; +export const IdxStateApprovedOperators = 18; +export const IdxStateBalances = 19; +export const IdxStateName = 20; +export const IdxStateOwners = 21; +export const IdxStateSymbol = 22; + +export let keyMap: string[] = [ + sc.ParamApproval, + sc.ParamApproved, + sc.ParamData, + sc.ParamFrom, + sc.ParamName, + sc.ParamOperator, + sc.ParamOwner, + sc.ParamSymbol, + sc.ParamTo, + sc.ParamTokenID, + sc.ResultAmount, + sc.ResultApproval, + sc.ResultApproved, + sc.ResultName, + sc.ResultOwner, + sc.ResultSymbol, + sc.ResultTokenURI, + sc.StateApprovedAccounts, + sc.StateApprovedOperators, + sc.StateBalances, + sc.StateName, + sc.StateOwners, + sc.StateSymbol, +]; + +export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/erc721/ts/erc721/lib.ts b/contracts/wasm/erc721/ts/erc721/lib.ts new file mode 100644 index 0000000000..ba6a48b663 --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/lib.ts @@ -0,0 +1,185 @@ +// 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"; +import * as sc from "./index"; + +export function on_call(index: i32): void { + return wasmlib.onCall(index); +} + +export function on_load(): void { + let exports = new wasmlib.ScExports(); + exports.addFunc(sc.FuncApprove, funcApproveThunk); + exports.addFunc(sc.FuncBurn, funcBurnThunk); + exports.addFunc(sc.FuncInit, funcInitThunk); + exports.addFunc(sc.FuncMint, funcMintThunk); + exports.addFunc(sc.FuncSafeTransferFrom, funcSafeTransferFromThunk); + exports.addFunc(sc.FuncSetApprovalForAll, funcSetApprovalForAllThunk); + exports.addFunc(sc.FuncTransferFrom, funcTransferFromThunk); + exports.addView(sc.ViewBalanceOf, viewBalanceOfThunk); + exports.addView(sc.ViewGetApproved, viewGetApprovedThunk); + exports.addView(sc.ViewIsApprovedForAll, viewIsApprovedForAllThunk); + exports.addView(sc.ViewName, viewNameThunk); + exports.addView(sc.ViewOwnerOf, viewOwnerOfThunk); + exports.addView(sc.ViewSymbol, viewSymbolThunk); + exports.addView(sc.ViewTokenURI, viewTokenURIThunk); + + for (let i = 0; i < sc.keyMap.length; i++) { + sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); + } +} + +function funcApproveThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("erc721.funcApprove"); + let f = new sc.ApproveContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.tokenID().exists(), "missing mandatory tokenID"); + sc.funcApprove(ctx, f); + ctx.log("erc721.funcApprove ok"); +} + +function funcBurnThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("erc721.funcBurn"); + let f = new sc.BurnContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.tokenID().exists(), "missing mandatory tokenID"); + sc.funcBurn(ctx, f); + ctx.log("erc721.funcBurn ok"); +} + +function funcInitThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("erc721.funcInit"); + let f = new sc.InitContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.name().exists(), "missing mandatory name"); + ctx.require(f.params.symbol().exists(), "missing mandatory symbol"); + sc.funcInit(ctx, f); + ctx.log("erc721.funcInit ok"); +} + +function funcMintThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("erc721.funcMint"); + let f = new sc.MintContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.tokenID().exists(), "missing mandatory tokenID"); + sc.funcMint(ctx, f); + ctx.log("erc721.funcMint ok"); +} + +function funcSafeTransferFromThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("erc721.funcSafeTransferFrom"); + let f = new sc.SafeTransferFromContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.from().exists(), "missing mandatory from"); + ctx.require(f.params.to().exists(), "missing mandatory to"); + ctx.require(f.params.tokenID().exists(), "missing mandatory tokenID"); + sc.funcSafeTransferFrom(ctx, f); + ctx.log("erc721.funcSafeTransferFrom ok"); +} + +function funcSetApprovalForAllThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("erc721.funcSetApprovalForAll"); + let f = new sc.SetApprovalForAllContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.approval().exists(), "missing mandatory approval"); + ctx.require(f.params.operator().exists(), "missing mandatory operator"); + sc.funcSetApprovalForAll(ctx, f); + ctx.log("erc721.funcSetApprovalForAll ok"); +} + +function funcTransferFromThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("erc721.funcTransferFrom"); + let f = new sc.TransferFromContext(); + f.params.mapID = wasmlib.OBJ_ID_PARAMS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + ctx.require(f.params.from().exists(), "missing mandatory from"); + ctx.require(f.params.to().exists(), "missing mandatory to"); + ctx.require(f.params.tokenID().exists(), "missing mandatory tokenID"); + sc.funcTransferFrom(ctx, f); + ctx.log("erc721.funcTransferFrom ok"); +} + +function viewBalanceOfThunk(ctx: wasmlib.ScViewContext): void { + ctx.log("erc721.viewBalanceOf"); + let f = new sc.BalanceOfContext(); + 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.owner().exists(), "missing mandatory owner"); + sc.viewBalanceOf(ctx, f); + ctx.log("erc721.viewBalanceOf ok"); +} + +function viewGetApprovedThunk(ctx: wasmlib.ScViewContext): void { + ctx.log("erc721.viewGetApproved"); + let f = new sc.GetApprovedContext(); + 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.tokenID().exists(), "missing mandatory tokenID"); + sc.viewGetApproved(ctx, f); + ctx.log("erc721.viewGetApproved ok"); +} + +function viewIsApprovedForAllThunk(ctx: wasmlib.ScViewContext): void { + ctx.log("erc721.viewIsApprovedForAll"); + let f = new sc.IsApprovedForAllContext(); + 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.operator().exists(), "missing mandatory operator"); + ctx.require(f.params.owner().exists(), "missing mandatory owner"); + sc.viewIsApprovedForAll(ctx, f); + ctx.log("erc721.viewIsApprovedForAll ok"); +} + +function viewNameThunk(ctx: wasmlib.ScViewContext): void { + ctx.log("erc721.viewName"); + let f = new sc.NameContext(); + f.results.mapID = wasmlib.OBJ_ID_RESULTS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + sc.viewName(ctx, f); + ctx.log("erc721.viewName ok"); +} + +function viewOwnerOfThunk(ctx: wasmlib.ScViewContext): void { + ctx.log("erc721.viewOwnerOf"); + let f = new sc.OwnerOfContext(); + 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.tokenID().exists(), "missing mandatory tokenID"); + sc.viewOwnerOf(ctx, f); + ctx.log("erc721.viewOwnerOf ok"); +} + +function viewSymbolThunk(ctx: wasmlib.ScViewContext): void { + ctx.log("erc721.viewSymbol"); + let f = new sc.SymbolContext(); + f.results.mapID = wasmlib.OBJ_ID_RESULTS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + sc.viewSymbol(ctx, f); + ctx.log("erc721.viewSymbol ok"); +} + +function viewTokenURIThunk(ctx: wasmlib.ScViewContext): void { + ctx.log("erc721.viewTokenURI"); + let f = new sc.TokenURIContext(); + 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.tokenID().exists(), "missing mandatory tokenID"); + sc.viewTokenURI(ctx, f); + ctx.log("erc721.viewTokenURI ok"); +} diff --git a/contracts/wasm/erc721/ts/erc721/params.ts b/contracts/wasm/erc721/ts/erc721/params.ts new file mode 100644 index 0000000000..92eaed30f6 --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/params.ts @@ -0,0 +1,225 @@ +// 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"; +import * as sc from "./index"; + +export class ImmutableApproveParams extends wasmlib.ScMapID { + approved(): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamApproved]); + } + + tokenID(): wasmlib.ScImmutableHash { + return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class MutableApproveParams extends wasmlib.ScMapID { + approved(): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamApproved]); + } + + tokenID(): wasmlib.ScMutableHash { + return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class ImmutableBurnParams extends wasmlib.ScMapID { + tokenID(): wasmlib.ScImmutableHash { + return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class MutableBurnParams extends wasmlib.ScMapID { + tokenID(): wasmlib.ScMutableHash { + return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class ImmutableInitParams extends wasmlib.ScMapID { + name(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + } + + symbol(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamSymbol]); + } +} + +export class MutableInitParams extends wasmlib.ScMapID { + name(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + } + + symbol(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamSymbol]); + } +} + +export class ImmutableMintParams extends wasmlib.ScMapID { + tokenID(): wasmlib.ScImmutableHash { + return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class MutableMintParams extends wasmlib.ScMapID { + tokenID(): wasmlib.ScMutableHash { + return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class ImmutableSafeTransferFromParams extends wasmlib.ScMapID { + data(): wasmlib.ScImmutableBytes { + return new wasmlib.ScImmutableBytes(this.mapID, sc.idxMap[sc.IdxParamData]); + } + + from(): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamFrom]); + } + + to(): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamTo]); + } + + tokenID(): wasmlib.ScImmutableHash { + return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class MutableSafeTransferFromParams extends wasmlib.ScMapID { + data(): wasmlib.ScMutableBytes { + return new wasmlib.ScMutableBytes(this.mapID, sc.idxMap[sc.IdxParamData]); + } + + from(): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamFrom]); + } + + to(): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamTo]); + } + + tokenID(): wasmlib.ScMutableHash { + return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class ImmutableSetApprovalForAllParams extends wasmlib.ScMapID { + approval(): wasmlib.ScImmutableBool { + return new wasmlib.ScImmutableBool(this.mapID, sc.idxMap[sc.IdxParamApproval]); + } + + operator(): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOperator]); + } +} + +export class MutableSetApprovalForAllParams extends wasmlib.ScMapID { + approval(): wasmlib.ScMutableBool { + return new wasmlib.ScMutableBool(this.mapID, sc.idxMap[sc.IdxParamApproval]); + } + + operator(): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOperator]); + } +} + +export class ImmutableTransferFromParams extends wasmlib.ScMapID { + from(): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamFrom]); + } + + to(): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamTo]); + } + + tokenID(): wasmlib.ScImmutableHash { + return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class MutableTransferFromParams extends wasmlib.ScMapID { + from(): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamFrom]); + } + + to(): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamTo]); + } + + tokenID(): wasmlib.ScMutableHash { + return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class ImmutableBalanceOfParams extends wasmlib.ScMapID { + owner(): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + } +} + +export class MutableBalanceOfParams extends wasmlib.ScMapID { + owner(): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + } +} + +export class ImmutableGetApprovedParams extends wasmlib.ScMapID { + tokenID(): wasmlib.ScImmutableHash { + return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class MutableGetApprovedParams extends wasmlib.ScMapID { + tokenID(): wasmlib.ScMutableHash { + return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class ImmutableIsApprovedForAllParams extends wasmlib.ScMapID { + operator(): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOperator]); + } + + owner(): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + } +} + +export class MutableIsApprovedForAllParams extends wasmlib.ScMapID { + operator(): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOperator]); + } + + owner(): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamOwner]); + } +} + +export class ImmutableOwnerOfParams extends wasmlib.ScMapID { + tokenID(): wasmlib.ScImmutableHash { + return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class MutableOwnerOfParams extends wasmlib.ScMapID { + tokenID(): wasmlib.ScMutableHash { + return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class ImmutableTokenURIParams extends wasmlib.ScMapID { + tokenID(): wasmlib.ScImmutableHash { + return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} + +export class MutableTokenURIParams extends wasmlib.ScMapID { + tokenID(): wasmlib.ScMutableHash { + return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamTokenID]); + } +} diff --git a/contracts/wasm/erc721/ts/erc721/results.ts b/contracts/wasm/erc721/ts/erc721/results.ts new file mode 100644 index 0000000000..34f4237014 --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/results.ts @@ -0,0 +1,93 @@ +// 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"; +import * as sc from "./index"; + +export class ImmutableBalanceOfResults extends wasmlib.ScMapID { + amount(): wasmlib.ScImmutableUint64 { + return new wasmlib.ScImmutableUint64(this.mapID, sc.idxMap[sc.IdxResultAmount]); + } +} + +export class MutableBalanceOfResults extends wasmlib.ScMapID { + amount(): wasmlib.ScMutableUint64 { + return new wasmlib.ScMutableUint64(this.mapID, sc.idxMap[sc.IdxResultAmount]); + } +} + +export class ImmutableGetApprovedResults extends wasmlib.ScMapID { + approved(): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultApproved]); + } +} + +export class MutableGetApprovedResults extends wasmlib.ScMapID { + approved(): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultApproved]); + } +} + +export class ImmutableIsApprovedForAllResults extends wasmlib.ScMapID { + approval(): wasmlib.ScImmutableBool { + return new wasmlib.ScImmutableBool(this.mapID, sc.idxMap[sc.IdxResultApproval]); + } +} + +export class MutableIsApprovedForAllResults extends wasmlib.ScMapID { + approval(): wasmlib.ScMutableBool { + return new wasmlib.ScMutableBool(this.mapID, sc.idxMap[sc.IdxResultApproval]); + } +} + +export class ImmutableNameResults extends wasmlib.ScMapID { + name(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultName]); + } +} + +export class MutableNameResults extends wasmlib.ScMapID { + name(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultName]); + } +} + +export class ImmutableOwnerOfResults extends wasmlib.ScMapID { + owner(): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultOwner]); + } +} + +export class MutableOwnerOfResults extends wasmlib.ScMapID { + owner(): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultOwner]); + } +} + +export class ImmutableSymbolResults extends wasmlib.ScMapID { + symbol(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultSymbol]); + } +} + +export class MutableSymbolResults extends wasmlib.ScMapID { + symbol(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultSymbol]); + } +} + +export class ImmutableTokenURIResults extends wasmlib.ScMapID { + tokenURI(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultTokenURI]); + } +} + +export class MutableTokenURIResults extends wasmlib.ScMapID { + tokenURI(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultTokenURI]); + } +} diff --git a/contracts/wasm/erc721/ts/erc721/state.ts b/contracts/wasm/erc721/ts/erc721/state.ts new file mode 100644 index 0000000000..d85b7c9295 --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/state.ts @@ -0,0 +1,155 @@ +// 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"; +import * as sc from "./index"; + +export class MapHashToImmutableAgentID { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + getAgentID(key: wasmlib.ScHash): wasmlib.ScImmutableAgentID { + return new wasmlib.ScImmutableAgentID(this.objID, key.getKeyID()); + } +} + +export class MapAgentIDToImmutableOperators { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + getOperators(key: wasmlib.ScAgentID): sc.ImmutableOperators { + let subID = wasmlib.getObjectID(this.objID, key.getKeyID(), wasmlib.TYPE_MAP); + return new sc.ImmutableOperators(subID); + } +} + +export class MapAgentIDToImmutableUint64 { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + getUint64(key: wasmlib.ScAgentID): wasmlib.ScImmutableUint64 { + return new wasmlib.ScImmutableUint64(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); + return new sc.MapHashToImmutableAgentID(mapID); + } + + approvedOperators(): sc.MapAgentIDToImmutableOperators { + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateApprovedOperators], wasmlib.TYPE_MAP); + return new sc.MapAgentIDToImmutableOperators(mapID); + } + + balances(): sc.MapAgentIDToImmutableUint64 { + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBalances], wasmlib.TYPE_MAP); + return new sc.MapAgentIDToImmutableUint64(mapID); + } + + name(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxStateName]); + } + + owners(): sc.MapHashToImmutableAgentID { + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateOwners], wasmlib.TYPE_MAP); + return new sc.MapHashToImmutableAgentID(mapID); + } + + symbol(): wasmlib.ScImmutableString { + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxStateSymbol]); + } +} + +export class MapHashToMutableAgentID { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + clear(): void { + wasmlib.clear(this.objID); + } + + getAgentID(key: wasmlib.ScHash): wasmlib.ScMutableAgentID { + return new wasmlib.ScMutableAgentID(this.objID, key.getKeyID()); + } +} + +export class MapAgentIDToMutableOperators { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + clear(): void { + wasmlib.clear(this.objID); + } + + getOperators(key: wasmlib.ScAgentID): sc.MutableOperators { + let subID = wasmlib.getObjectID(this.objID, key.getKeyID(), wasmlib.TYPE_MAP); + return new sc.MutableOperators(subID); + } +} + +export class MapAgentIDToMutableUint64 { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + clear(): void { + wasmlib.clear(this.objID); + } + + getUint64(key: wasmlib.ScAgentID): wasmlib.ScMutableUint64 { + return new wasmlib.ScMutableUint64(this.objID, key.getKeyID()); + } +} + +export class MutableErc721State extends wasmlib.ScMapID { + approvedAccounts(): sc.MapHashToMutableAgentID { + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateApprovedAccounts], wasmlib.TYPE_MAP); + return new sc.MapHashToMutableAgentID(mapID); + } + + approvedOperators(): sc.MapAgentIDToMutableOperators { + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateApprovedOperators], wasmlib.TYPE_MAP); + return new sc.MapAgentIDToMutableOperators(mapID); + } + + balances(): sc.MapAgentIDToMutableUint64 { + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBalances], wasmlib.TYPE_MAP); + return new sc.MapAgentIDToMutableUint64(mapID); + } + + name(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxStateName]); + } + + owners(): sc.MapHashToMutableAgentID { + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateOwners], wasmlib.TYPE_MAP); + return new sc.MapHashToMutableAgentID(mapID); + } + + symbol(): wasmlib.ScMutableString { + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxStateSymbol]); + } +} diff --git a/contracts/wasm/erc721/ts/erc721/tsconfig.json b/contracts/wasm/erc721/ts/erc721/tsconfig.json new file mode 100644 index 0000000000..6fb4265c72 --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "assemblyscript/std/assembly.json", + "include": ["./*.ts"] +} diff --git a/contracts/wasm/erc721/ts/erc721/typedefs.ts b/contracts/wasm/erc721/ts/erc721/typedefs.ts new file mode 100644 index 0000000000..a058931ce3 --- /dev/null +++ b/contracts/wasm/erc721/ts/erc721/typedefs.ts @@ -0,0 +1,43 @@ +// 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"; +import * as sc from "./index"; + +export class MapAgentIDToImmutableBool { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + getBool(key: wasmlib.ScAgentID): wasmlib.ScImmutableBool { + return new wasmlib.ScImmutableBool(this.objID, key.getKeyID()); + } +} + +export class ImmutableOperators extends MapAgentIDToImmutableBool { +}; + +export class MapAgentIDToMutableBool { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } + + clear(): void { + wasmlib.clear(this.objID); + } + + getBool(key: wasmlib.ScAgentID): wasmlib.ScMutableBool { + return new wasmlib.ScMutableBool(this.objID, key.getKeyID()); + } +} + +export class MutableOperators extends MapAgentIDToMutableBool { +}; diff --git a/contracts/wasm/fairauction/go/fairauction/consts.go b/contracts/wasm/fairauction/go/fairauction/consts.go index 225392daec..a64184d793 100644 --- a/contracts/wasm/fairauction/go/fairauction/consts.go +++ b/contracts/wasm/fairauction/go/fairauction/consts.go @@ -16,33 +16,33 @@ const ( ) const ( - ParamColor = wasmlib.Key("color") - ParamDescription = wasmlib.Key("description") - ParamDuration = wasmlib.Key("duration") - ParamMinimumBid = wasmlib.Key("minimumBid") - ParamOwnerMargin = wasmlib.Key("ownerMargin") + ParamColor = "color" + ParamDescription = "description" + ParamDuration = "duration" + ParamMinimumBid = "minimumBid" + ParamOwnerMargin = "ownerMargin" ) const ( - ResultBidders = wasmlib.Key("bidders") - ResultColor = wasmlib.Key("color") - ResultCreator = wasmlib.Key("creator") - ResultDeposit = wasmlib.Key("deposit") - ResultDescription = wasmlib.Key("description") - ResultDuration = wasmlib.Key("duration") - ResultHighestBid = wasmlib.Key("highestBid") - ResultHighestBidder = wasmlib.Key("highestBidder") - ResultMinimumBid = wasmlib.Key("minimumBid") - ResultNumTokens = wasmlib.Key("numTokens") - ResultOwnerMargin = wasmlib.Key("ownerMargin") - ResultWhenStarted = wasmlib.Key("whenStarted") + ResultBidders = "bidders" + ResultColor = "color" + ResultCreator = "creator" + ResultDeposit = "deposit" + ResultDescription = "description" + ResultDuration = "duration" + ResultHighestBid = "highestBid" + ResultHighestBidder = "highestBidder" + ResultMinimumBid = "minimumBid" + ResultNumTokens = "numTokens" + ResultOwnerMargin = "ownerMargin" + ResultWhenStarted = "whenStarted" ) const ( - StateAuctions = wasmlib.Key("auctions") - StateBidderList = wasmlib.Key("bidderList") - StateBids = wasmlib.Key("bids") - StateOwnerMargin = wasmlib.Key("ownerMargin") + StateAuctions = "auctions" + StateBidderList = "bidderList" + StateBids = "bids" + StateOwnerMargin = "ownerMargin" ) const ( diff --git a/contracts/wasm/fairauction/go/fairauction/keys.go b/contracts/wasm/fairauction/go/fairauction/keys.go index 24584b37df..c66bce5659 100644 --- a/contracts/wasm/fairauction/go/fairauction/keys.go +++ b/contracts/wasm/fairauction/go/fairauction/keys.go @@ -10,11 +10,12 @@ package fairauction import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" const ( - IdxParamColor = 0 - IdxParamDescription = 1 - IdxParamDuration = 2 - IdxParamMinimumBid = 3 - IdxParamOwnerMargin = 4 + IdxParamColor = 0 + IdxParamDescription = 1 + IdxParamDuration = 2 + IdxParamMinimumBid = 3 + IdxParamOwnerMargin = 4 + IdxResultBidders = 5 IdxResultColor = 6 IdxResultCreator = 7 @@ -27,10 +28,11 @@ const ( IdxResultNumTokens = 14 IdxResultOwnerMargin = 15 IdxResultWhenStarted = 16 - IdxStateAuctions = 17 - IdxStateBidderList = 18 - IdxStateBids = 19 - IdxStateOwnerMargin = 20 + + IdxStateAuctions = 17 + IdxStateBidderList = 18 + IdxStateBids = 19 + IdxStateOwnerMargin = 20 ) const keyMapLen = 21 diff --git a/contracts/wasm/fairauction/go/fairauction/lib.go b/contracts/wasm/fairauction/go/fairauction/lib.go index c59c2a1b0a..7e27fcdd01 100644 --- a/contracts/wasm/fairauction/go/fairauction/lib.go +++ b/contracts/wasm/fairauction/go/fairauction/lib.go @@ -29,6 +29,7 @@ type FinalizeAuctionContext struct { func funcFinalizeAuctionThunk(ctx wasmlib.ScFuncContext) { ctx.Log("fairauction.funcFinalizeAuction") + // only SC itself can invoke this function ctx.Require(ctx.Caller() == ctx.AccountID(), "no permission") @@ -72,6 +73,7 @@ type SetOwnerMarginContext struct { func funcSetOwnerMarginThunk(ctx wasmlib.ScFuncContext) { ctx.Log("fairauction.funcSetOwnerMargin") + // only SC creator can set owner margin ctx.Require(ctx.Caller() == ctx.ContractCreator(), "no permission") diff --git a/contracts/wasm/fairauction/go/fairauction/structs.go b/contracts/wasm/fairauction/go/fairauction/structs.go index 681e9506d2..ef4c7a49d2 100644 --- a/contracts/wasm/fairauction/go/fairauction/structs.go +++ b/contracts/wasm/fairauction/go/fairauction/structs.go @@ -75,6 +75,10 @@ type MutableAuction struct { keyID wasmlib.Key32 } +func (o MutableAuction) Delete() { + wasmlib.DelKey(o.objID, o.keyID, wasmlib.TYPE_BYTES) +} + func (o MutableAuction) Exists() bool { return wasmlib.Exists(o.objID, o.keyID, wasmlib.TYPE_BYTES) } @@ -129,6 +133,10 @@ type MutableBid struct { keyID wasmlib.Key32 } +func (o MutableBid) Delete() { + wasmlib.DelKey(o.objID, o.keyID, wasmlib.TYPE_BYTES) +} + func (o MutableBid) Exists() bool { return wasmlib.Exists(o.objID, o.keyID, wasmlib.TYPE_BYTES) } diff --git a/contracts/wasm/fairauction/src/consts.rs b/contracts/wasm/fairauction/src/consts.rs index b1ed46861d..4d64eee75b 100644 --- a/contracts/wasm/fairauction/src/consts.rs +++ b/contracts/wasm/fairauction/src/consts.rs @@ -5,50 +5,46 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; -pub const SC_NAME: &str = "fairauction"; -pub const SC_DESCRIPTION: &str = "Decentralized auction to securely sell tokens to the highest bidder"; -pub const HSC_NAME: ScHname = ScHname(0x1b5c43b1); - -pub const PARAM_COLOR: &str = "color"; -pub const PARAM_DESCRIPTION: &str = "description"; -pub const PARAM_DURATION: &str = "duration"; -pub const PARAM_MINIMUM_BID: &str = "minimumBid"; -pub const PARAM_OWNER_MARGIN: &str = "ownerMargin"; - -pub const RESULT_BIDDERS: &str = "bidders"; -pub const RESULT_COLOR: &str = "color"; -pub const RESULT_CREATOR: &str = "creator"; -pub const RESULT_DEPOSIT: &str = "deposit"; -pub const RESULT_DESCRIPTION: &str = "description"; -pub const RESULT_DURATION: &str = "duration"; -pub const RESULT_HIGHEST_BID: &str = "highestBid"; -pub const RESULT_HIGHEST_BIDDER: &str = "highestBidder"; -pub const RESULT_MINIMUM_BID: &str = "minimumBid"; -pub const RESULT_NUM_TOKENS: &str = "numTokens"; -pub const RESULT_OWNER_MARGIN: &str = "ownerMargin"; -pub const RESULT_WHEN_STARTED: &str = "whenStarted"; - -pub const STATE_AUCTIONS: &str = "auctions"; -pub const STATE_BIDDER_LIST: &str = "bidderList"; -pub const STATE_BIDS: &str = "bids"; -pub const STATE_OWNER_MARGIN: &str = "ownerMargin"; - -pub const FUNC_FINALIZE_AUCTION: &str = "finalizeAuction"; -pub const FUNC_PLACE_BID: &str = "placeBid"; -pub const FUNC_SET_OWNER_MARGIN: &str = "setOwnerMargin"; -pub const FUNC_START_AUCTION: &str = "startAuction"; -pub const VIEW_GET_INFO: &str = "getInfo"; - -pub const HFUNC_FINALIZE_AUCTION: ScHname = ScHname(0x8d534ddc); -pub const HFUNC_PLACE_BID: ScHname = ScHname(0x9bd72fa9); -pub const HFUNC_SET_OWNER_MARGIN: ScHname = ScHname(0x1774461a); -pub const HFUNC_START_AUCTION: ScHname = ScHname(0xd5b7bacb); -pub const HVIEW_GET_INFO: ScHname = ScHname(0xcfedba5f); - -// @formatter:on +pub const SC_NAME : &str = "fairauction"; +pub const SC_DESCRIPTION : &str = "Decentralized auction to securely sell tokens to the highest bidder"; +pub const HSC_NAME : ScHname = ScHname(0x1b5c43b1); + +pub const PARAM_COLOR : &str = "color"; +pub const PARAM_DESCRIPTION : &str = "description"; +pub const PARAM_DURATION : &str = "duration"; +pub const PARAM_MINIMUM_BID : &str = "minimumBid"; +pub const PARAM_OWNER_MARGIN : &str = "ownerMargin"; + +pub const RESULT_BIDDERS : &str = "bidders"; +pub const RESULT_COLOR : &str = "color"; +pub const RESULT_CREATOR : &str = "creator"; +pub const RESULT_DEPOSIT : &str = "deposit"; +pub const RESULT_DESCRIPTION : &str = "description"; +pub const RESULT_DURATION : &str = "duration"; +pub const RESULT_HIGHEST_BID : &str = "highestBid"; +pub const RESULT_HIGHEST_BIDDER : &str = "highestBidder"; +pub const RESULT_MINIMUM_BID : &str = "minimumBid"; +pub const RESULT_NUM_TOKENS : &str = "numTokens"; +pub const RESULT_OWNER_MARGIN : &str = "ownerMargin"; +pub const RESULT_WHEN_STARTED : &str = "whenStarted"; + +pub const STATE_AUCTIONS : &str = "auctions"; +pub const STATE_BIDDER_LIST : &str = "bidderList"; +pub const STATE_BIDS : &str = "bids"; +pub const STATE_OWNER_MARGIN : &str = "ownerMargin"; + +pub const FUNC_FINALIZE_AUCTION : &str = "finalizeAuction"; +pub const FUNC_PLACE_BID : &str = "placeBid"; +pub const FUNC_SET_OWNER_MARGIN : &str = "setOwnerMargin"; +pub const FUNC_START_AUCTION : &str = "startAuction"; +pub const VIEW_GET_INFO : &str = "getInfo"; + +pub const HFUNC_FINALIZE_AUCTION : ScHname = ScHname(0x8d534ddc); +pub const HFUNC_PLACE_BID : ScHname = ScHname(0x9bd72fa9); +pub const HFUNC_SET_OWNER_MARGIN : ScHname = ScHname(0x1774461a); +pub const HFUNC_START_AUCTION : ScHname = ScHname(0xd5b7bacb); +pub const HVIEW_GET_INFO : ScHname = ScHname(0xcfedba5f); diff --git a/contracts/wasm/fairauction/src/contract.rs b/contracts/wasm/fairauction/src/contract.rs index 5a918bb9c7..78cd2681ae 100644 --- a/contracts/wasm/fairauction/src/contract.rs +++ b/contracts/wasm/fairauction/src/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -18,29 +16,29 @@ use crate::params::*; use crate::results::*; pub struct FinalizeAuctionCall { - pub func: ScFunc, - pub params: MutableFinalizeAuctionParams, + pub func: ScFunc, + pub params: MutableFinalizeAuctionParams, } pub struct PlaceBidCall { - pub func: ScFunc, - pub params: MutablePlaceBidParams, + pub func: ScFunc, + pub params: MutablePlaceBidParams, } pub struct SetOwnerMarginCall { - pub func: ScFunc, - pub params: MutableSetOwnerMarginParams, + pub func: ScFunc, + pub params: MutableSetOwnerMarginParams, } pub struct StartAuctionCall { - pub func: ScFunc, - pub params: MutableStartAuctionParams, + pub func: ScFunc, + pub params: MutableStartAuctionParams, } pub struct GetInfoCall { - pub func: ScView, - pub params: MutableGetInfoParams, - pub results: ImmutableGetInfoResults, + pub func: ScView, + pub params: MutableGetInfoParams, + pub results: ImmutableGetInfoResults, } pub struct ScFuncs { @@ -49,45 +47,47 @@ pub struct ScFuncs { impl ScFuncs { pub fn finalize_auction(_ctx: & dyn ScFuncCallContext) -> FinalizeAuctionCall { let mut f = FinalizeAuctionCall { - func: ScFunc::new(HSC_NAME, HFUNC_FINALIZE_AUCTION), + func: ScFunc::new(HSC_NAME, HFUNC_FINALIZE_AUCTION), params: MutableFinalizeAuctionParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn place_bid(_ctx: & dyn ScFuncCallContext) -> PlaceBidCall { let mut f = PlaceBidCall { - func: ScFunc::new(HSC_NAME, HFUNC_PLACE_BID), + func: ScFunc::new(HSC_NAME, HFUNC_PLACE_BID), params: MutablePlaceBidParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn set_owner_margin(_ctx: & dyn ScFuncCallContext) -> SetOwnerMarginCall { let mut f = SetOwnerMarginCall { - func: ScFunc::new(HSC_NAME, HFUNC_SET_OWNER_MARGIN), + func: ScFunc::new(HSC_NAME, HFUNC_SET_OWNER_MARGIN), params: MutableSetOwnerMarginParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn start_auction(_ctx: & dyn ScFuncCallContext) -> StartAuctionCall { let mut f = StartAuctionCall { - func: ScFunc::new(HSC_NAME, HFUNC_START_AUCTION), + func: ScFunc::new(HSC_NAME, HFUNC_START_AUCTION), params: MutableStartAuctionParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn get_info(_ctx: & dyn ScViewCallContext) -> GetInfoCall { let mut f = GetInfoCall { - func: ScView::new(HSC_NAME, HVIEW_GET_INFO), - params: MutableGetInfoParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_INFO), + params: MutableGetInfoParams { id: 0 }, results: ImmutableGetInfoResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } } - -// @formatter:on diff --git a/contracts/wasm/fairauction/src/keys.rs b/contracts/wasm/fairauction/src/keys.rs index f8be26b53c..843e56e642 100644 --- a/contracts/wasm/fairauction/src/keys.rs +++ b/contracts/wasm/fairauction/src/keys.rs @@ -5,60 +5,60 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use crate::*; -pub(crate) const IDX_PARAM_COLOR: usize = 0; -pub(crate) const IDX_PARAM_DESCRIPTION: usize = 1; -pub(crate) const IDX_PARAM_DURATION: usize = 2; -pub(crate) const IDX_PARAM_MINIMUM_BID: usize = 3; -pub(crate) const IDX_PARAM_OWNER_MARGIN: usize = 4; -pub(crate) const IDX_RESULT_BIDDERS: usize = 5; -pub(crate) const IDX_RESULT_COLOR: usize = 6; -pub(crate) const IDX_RESULT_CREATOR: usize = 7; -pub(crate) const IDX_RESULT_DEPOSIT: usize = 8; -pub(crate) const IDX_RESULT_DESCRIPTION: usize = 9; -pub(crate) const IDX_RESULT_DURATION: usize = 10; -pub(crate) const IDX_RESULT_HIGHEST_BID: usize = 11; -pub(crate) const IDX_RESULT_HIGHEST_BIDDER: usize = 12; -pub(crate) const IDX_RESULT_MINIMUM_BID: usize = 13; -pub(crate) const IDX_RESULT_NUM_TOKENS: usize = 14; -pub(crate) const IDX_RESULT_OWNER_MARGIN: usize = 15; -pub(crate) const IDX_RESULT_WHEN_STARTED: usize = 16; -pub(crate) const IDX_STATE_AUCTIONS: usize = 17; -pub(crate) const IDX_STATE_BIDDER_LIST: usize = 18; -pub(crate) const IDX_STATE_BIDS: usize = 19; -pub(crate) const IDX_STATE_OWNER_MARGIN: usize = 20; +pub(crate) const IDX_PARAM_COLOR : usize = 0; +pub(crate) const IDX_PARAM_DESCRIPTION : usize = 1; +pub(crate) const IDX_PARAM_DURATION : usize = 2; +pub(crate) const IDX_PARAM_MINIMUM_BID : usize = 3; +pub(crate) const IDX_PARAM_OWNER_MARGIN : usize = 4; + +pub(crate) const IDX_RESULT_BIDDERS : usize = 5; +pub(crate) const IDX_RESULT_COLOR : usize = 6; +pub(crate) const IDX_RESULT_CREATOR : usize = 7; +pub(crate) const IDX_RESULT_DEPOSIT : usize = 8; +pub(crate) const IDX_RESULT_DESCRIPTION : usize = 9; +pub(crate) const IDX_RESULT_DURATION : usize = 10; +pub(crate) const IDX_RESULT_HIGHEST_BID : usize = 11; +pub(crate) const IDX_RESULT_HIGHEST_BIDDER : usize = 12; +pub(crate) const IDX_RESULT_MINIMUM_BID : usize = 13; +pub(crate) const IDX_RESULT_NUM_TOKENS : usize = 14; +pub(crate) const IDX_RESULT_OWNER_MARGIN : usize = 15; +pub(crate) const IDX_RESULT_WHEN_STARTED : usize = 16; + +pub(crate) const IDX_STATE_AUCTIONS : usize = 17; +pub(crate) const IDX_STATE_BIDDER_LIST : usize = 18; +pub(crate) const IDX_STATE_BIDS : usize = 19; +pub(crate) const IDX_STATE_OWNER_MARGIN : usize = 20; pub const KEY_MAP_LEN: usize = 21; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ - PARAM_COLOR, - PARAM_DESCRIPTION, - PARAM_DURATION, - PARAM_MINIMUM_BID, - PARAM_OWNER_MARGIN, - RESULT_BIDDERS, - RESULT_COLOR, - RESULT_CREATOR, - RESULT_DEPOSIT, - RESULT_DESCRIPTION, - RESULT_DURATION, - RESULT_HIGHEST_BID, - RESULT_HIGHEST_BIDDER, - RESULT_MINIMUM_BID, - RESULT_NUM_TOKENS, - RESULT_OWNER_MARGIN, - RESULT_WHEN_STARTED, - STATE_AUCTIONS, - STATE_BIDDER_LIST, - STATE_BIDS, - STATE_OWNER_MARGIN, + PARAM_COLOR, + PARAM_DESCRIPTION, + PARAM_DURATION, + PARAM_MINIMUM_BID, + PARAM_OWNER_MARGIN, + RESULT_BIDDERS, + RESULT_COLOR, + RESULT_CREATOR, + RESULT_DEPOSIT, + RESULT_DESCRIPTION, + RESULT_DURATION, + RESULT_HIGHEST_BID, + RESULT_HIGHEST_BIDDER, + RESULT_MINIMUM_BID, + RESULT_NUM_TOKENS, + RESULT_OWNER_MARGIN, + RESULT_WHEN_STARTED, + STATE_AUCTIONS, + STATE_BIDDER_LIST, + STATE_BIDS, + STATE_OWNER_MARGIN, ]; pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; @@ -68,5 +68,3 @@ pub fn idx_map(idx: usize) -> Key32 { IDX_MAP[idx] } } - -// @formatter:on diff --git a/contracts/wasm/fairauction/src/lib.rs b/contracts/wasm/fairauction/src/lib.rs index d9b6366b4b..97dec4b38d 100644 --- a/contracts/wasm/fairauction/src/lib.rs +++ b/contracts/wasm/fairauction/src/lib.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] #![allow(unused_imports)] @@ -34,10 +32,10 @@ mod fairauction; fn on_load() { let exports = ScExports::new(); exports.add_func(FUNC_FINALIZE_AUCTION, func_finalize_auction_thunk); - exports.add_func(FUNC_PLACE_BID, func_place_bid_thunk); + exports.add_func(FUNC_PLACE_BID, func_place_bid_thunk); exports.add_func(FUNC_SET_OWNER_MARGIN, func_set_owner_margin_thunk); - exports.add_func(FUNC_START_AUCTION, func_start_auction_thunk); - exports.add_view(VIEW_GET_INFO, view_get_info_thunk); + exports.add_func(FUNC_START_AUCTION, func_start_auction_thunk); + exports.add_view(VIEW_GET_INFO, view_get_info_thunk); unsafe { for i in 0..KEY_MAP_LEN { @@ -47,114 +45,114 @@ fn on_load() { } pub struct FinalizeAuctionContext { - params: ImmutableFinalizeAuctionParams, - state: MutableFairAuctionState, + params: ImmutableFinalizeAuctionParams, + state: MutableFairAuctionState, } fn func_finalize_auction_thunk(ctx: &ScFuncContext) { - ctx.log("fairauction.funcFinalizeAuction"); - // only SC itself can invoke this function - ctx.require(ctx.caller() == ctx.account_id(), "no permission"); - - let f = FinalizeAuctionContext { - params: ImmutableFinalizeAuctionParams { - id: OBJ_ID_PARAMS, - }, - state: MutableFairAuctionState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.color().exists(), "missing mandatory color"); - func_finalize_auction(ctx, &f); - ctx.log("fairauction.funcFinalizeAuction ok"); + ctx.log("fairauction.funcFinalizeAuction"); + + // only SC itself can invoke this function + ctx.require(ctx.caller() == ctx.account_id(), "no permission"); + + let f = FinalizeAuctionContext { + params: ImmutableFinalizeAuctionParams { + id: OBJ_ID_PARAMS, + }, + state: MutableFairAuctionState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.color().exists(), "missing mandatory color"); + func_finalize_auction(ctx, &f); + ctx.log("fairauction.funcFinalizeAuction ok"); } pub struct PlaceBidContext { - params: ImmutablePlaceBidParams, - state: MutableFairAuctionState, + params: ImmutablePlaceBidParams, + state: MutableFairAuctionState, } fn func_place_bid_thunk(ctx: &ScFuncContext) { - ctx.log("fairauction.funcPlaceBid"); - let f = PlaceBidContext { - params: ImmutablePlaceBidParams { - id: OBJ_ID_PARAMS, - }, - state: MutableFairAuctionState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.color().exists(), "missing mandatory color"); - func_place_bid(ctx, &f); - ctx.log("fairauction.funcPlaceBid ok"); + ctx.log("fairauction.funcPlaceBid"); + let f = PlaceBidContext { + params: ImmutablePlaceBidParams { + id: OBJ_ID_PARAMS, + }, + state: MutableFairAuctionState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.color().exists(), "missing mandatory color"); + func_place_bid(ctx, &f); + ctx.log("fairauction.funcPlaceBid ok"); } pub struct SetOwnerMarginContext { - params: ImmutableSetOwnerMarginParams, - state: MutableFairAuctionState, + params: ImmutableSetOwnerMarginParams, + state: MutableFairAuctionState, } fn func_set_owner_margin_thunk(ctx: &ScFuncContext) { - ctx.log("fairauction.funcSetOwnerMargin"); - // only SC creator can set owner margin - ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); - - let f = SetOwnerMarginContext { - params: ImmutableSetOwnerMarginParams { - id: OBJ_ID_PARAMS, - }, - state: MutableFairAuctionState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.owner_margin().exists(), "missing mandatory ownerMargin"); - func_set_owner_margin(ctx, &f); - ctx.log("fairauction.funcSetOwnerMargin ok"); + ctx.log("fairauction.funcSetOwnerMargin"); + + // only SC creator can set owner margin + ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); + + let f = SetOwnerMarginContext { + params: ImmutableSetOwnerMarginParams { + id: OBJ_ID_PARAMS, + }, + state: MutableFairAuctionState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.owner_margin().exists(), "missing mandatory ownerMargin"); + func_set_owner_margin(ctx, &f); + ctx.log("fairauction.funcSetOwnerMargin ok"); } pub struct StartAuctionContext { - params: ImmutableStartAuctionParams, - state: MutableFairAuctionState, + params: ImmutableStartAuctionParams, + state: MutableFairAuctionState, } fn func_start_auction_thunk(ctx: &ScFuncContext) { - ctx.log("fairauction.funcStartAuction"); - let f = StartAuctionContext { - params: ImmutableStartAuctionParams { - id: OBJ_ID_PARAMS, - }, - state: MutableFairAuctionState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.color().exists(), "missing mandatory color"); - ctx.require(f.params.minimum_bid().exists(), "missing mandatory minimumBid"); - func_start_auction(ctx, &f); - ctx.log("fairauction.funcStartAuction ok"); + ctx.log("fairauction.funcStartAuction"); + let f = StartAuctionContext { + params: ImmutableStartAuctionParams { + id: OBJ_ID_PARAMS, + }, + state: MutableFairAuctionState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.color().exists(), "missing mandatory color"); + ctx.require(f.params.minimum_bid().exists(), "missing mandatory minimumBid"); + func_start_auction(ctx, &f); + ctx.log("fairauction.funcStartAuction ok"); } pub struct GetInfoContext { - params: ImmutableGetInfoParams, - results: MutableGetInfoResults, - state: ImmutableFairAuctionState, + params: ImmutableGetInfoParams, + results: MutableGetInfoResults, + state: ImmutableFairAuctionState, } fn view_get_info_thunk(ctx: &ScViewContext) { - ctx.log("fairauction.viewGetInfo"); - let f = GetInfoContext { - params: ImmutableGetInfoParams { - id: OBJ_ID_PARAMS, - }, - results: MutableGetInfoResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableFairAuctionState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.color().exists(), "missing mandatory color"); - view_get_info(ctx, &f); - ctx.log("fairauction.viewGetInfo ok"); + ctx.log("fairauction.viewGetInfo"); + let f = GetInfoContext { + params: ImmutableGetInfoParams { + id: OBJ_ID_PARAMS, + }, + results: MutableGetInfoResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableFairAuctionState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.color().exists(), "missing mandatory color"); + view_get_info(ctx, &f); + ctx.log("fairauction.viewGetInfo ok"); } - -// @formatter:on diff --git a/contracts/wasm/fairauction/src/params.rs b/contracts/wasm/fairauction/src/params.rs index ed009024e5..8dcbe76892 100644 --- a/contracts/wasm/fairauction/src/params.rs +++ b/contracts/wasm/fairauction/src/params.rs @@ -13,6 +13,8 @@ use wasmlib::host::*; use crate::*; use crate::keys::*; +use crate::structs::*; +use crate::typedefs::*; #[derive(Clone, Copy)] pub struct ImmutableFinalizeAuctionParams { @@ -21,8 +23,8 @@ pub struct ImmutableFinalizeAuctionParams { impl ImmutableFinalizeAuctionParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } } #[derive(Clone, Copy)] @@ -32,8 +34,8 @@ pub struct MutableFinalizeAuctionParams { impl MutableFinalizeAuctionParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } } #[derive(Clone, Copy)] @@ -43,8 +45,8 @@ pub struct ImmutablePlaceBidParams { impl ImmutablePlaceBidParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } } #[derive(Clone, Copy)] @@ -54,8 +56,8 @@ pub struct MutablePlaceBidParams { impl MutablePlaceBidParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } } #[derive(Clone, Copy)] @@ -65,8 +67,8 @@ 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, idx_map(IDX_PARAM_OWNER_MARGIN)) + } } #[derive(Clone, Copy)] @@ -76,8 +78,8 @@ 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, idx_map(IDX_PARAM_OWNER_MARGIN)) + } } #[derive(Clone, Copy)] @@ -87,20 +89,20 @@ pub struct ImmutableStartAuctionParams { impl ImmutableStartAuctionParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } pub fn description(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) + } pub fn duration(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_DURATION)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_DURATION)) + } pub fn minimum_bid(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_MINIMUM_BID)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_MINIMUM_BID)) + } } #[derive(Clone, Copy)] @@ -110,20 +112,20 @@ pub struct MutableStartAuctionParams { impl MutableStartAuctionParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } pub fn description(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) + } pub fn duration(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_DURATION)) - } + ScMutableInt32::new(self.id, idx_map(IDX_PARAM_DURATION)) + } pub fn minimum_bid(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_MINIMUM_BID)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_MINIMUM_BID)) + } } #[derive(Clone, Copy)] @@ -133,8 +135,8 @@ pub struct ImmutableGetInfoParams { impl ImmutableGetInfoParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } } #[derive(Clone, Copy)] @@ -144,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, idx_map(IDX_PARAM_COLOR)) + } } diff --git a/contracts/wasm/fairauction/src/results.rs b/contracts/wasm/fairauction/src/results.rs index 2edace8c43..9c97fda447 100644 --- a/contracts/wasm/fairauction/src/results.rs +++ b/contracts/wasm/fairauction/src/results.rs @@ -14,6 +14,7 @@ use wasmlib::host::*; use crate::*; use crate::keys::*; use crate::structs::*; +use crate::typedefs::*; #[derive(Clone, Copy)] pub struct ImmutableGetInfoResults { @@ -22,52 +23,52 @@ pub struct ImmutableGetInfoResults { impl ImmutableGetInfoResults { pub fn bidders(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_BIDDERS)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_BIDDERS)) + } pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_RESULT_COLOR)) - } + ScImmutableColor::new(self.id, idx_map(IDX_RESULT_COLOR)) + } pub fn creator(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_CREATOR)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_CREATOR)) + } pub fn deposit(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_DEPOSIT)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_DEPOSIT)) + } pub fn description(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_DESCRIPTION)) - } + ScImmutableString::new(self.id, idx_map(IDX_RESULT_DESCRIPTION)) + } pub fn duration(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_DURATION)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_DURATION)) + } pub fn highest_bid(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_HIGHEST_BID)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_HIGHEST_BID)) + } pub fn highest_bidder(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_HIGHEST_BIDDER)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_RESULT_HIGHEST_BIDDER)) + } pub fn minimum_bid(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_MINIMUM_BID)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_MINIMUM_BID)) + } pub fn num_tokens(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_NUM_TOKENS)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_NUM_TOKENS)) + } pub fn owner_margin(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_OWNER_MARGIN)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_OWNER_MARGIN)) + } pub fn when_started(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_WHEN_STARTED)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_WHEN_STARTED)) + } } #[derive(Clone, Copy)] @@ -77,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, idx_map(IDX_RESULT_BIDDERS)) + } pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_RESULT_COLOR)) - } + ScMutableColor::new(self.id, idx_map(IDX_RESULT_COLOR)) + } pub fn creator(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_CREATOR)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_CREATOR)) + } pub fn deposit(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_DEPOSIT)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_DEPOSIT)) + } pub fn description(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_DESCRIPTION)) - } + ScMutableString::new(self.id, idx_map(IDX_RESULT_DESCRIPTION)) + } pub fn duration(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_RESULT_DURATION)) - } + ScMutableInt32::new(self.id, idx_map(IDX_RESULT_DURATION)) + } pub fn highest_bid(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_HIGHEST_BID)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_HIGHEST_BID)) + } pub fn highest_bidder(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_HIGHEST_BIDDER)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_RESULT_HIGHEST_BIDDER)) + } pub fn minimum_bid(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_MINIMUM_BID)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_MINIMUM_BID)) + } pub fn num_tokens(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_NUM_TOKENS)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_NUM_TOKENS)) + } pub fn owner_margin(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_OWNER_MARGIN)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_OWNER_MARGIN)) + } pub fn when_started(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_WHEN_STARTED)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_WHEN_STARTED)) + } } diff --git a/contracts/wasm/fairauction/src/state.rs b/contracts/wasm/fairauction/src/state.rs index 6201943eb4..aeff8bb397 100644 --- a/contracts/wasm/fairauction/src/state.rs +++ b/contracts/wasm/fairauction/src/state.rs @@ -17,7 +17,7 @@ use crate::structs::*; use crate::typedefs::*; pub struct MapColorToImmutableAuction { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapColorToImmutableAuction { @@ -27,7 +27,7 @@ impl MapColorToImmutableAuction { } pub struct MapColorToImmutableBidderList { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapColorToImmutableBidderList { @@ -38,7 +38,7 @@ impl MapColorToImmutableBidderList { } pub struct MapColorToImmutableBids { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapColorToImmutableBids { @@ -55,32 +55,32 @@ 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); - MapColorToImmutableAuction { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_AUCTIONS), 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); - MapColorToImmutableBidderList { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_BIDDER_LIST), 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); - MapColorToImmutableBids { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_BIDS), 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, idx_map(IDX_STATE_OWNER_MARGIN)) + } } pub struct MapColorToMutableAuction { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapColorToMutableAuction { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_auction(&self, key: &ScColor) -> MutableAuction { @@ -89,12 +89,12 @@ impl MapColorToMutableAuction { } pub struct MapColorToMutableBidderList { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapColorToMutableBidderList { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_bidder_list(&self, key: &ScColor) -> MutableBidderList { @@ -104,12 +104,12 @@ impl MapColorToMutableBidderList { } pub struct MapColorToMutableBids { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapColorToMutableBids { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_bids(&self, key: &ScColor) -> MutableBids { @@ -125,21 +125,21 @@ pub struct MutableFairAuctionState { impl MutableFairAuctionState { pub fn auctions(&self) -> MapColorToMutableAuction { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_AUCTIONS), TYPE_MAP); - MapColorToMutableAuction { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_AUCTIONS), 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); - MapColorToMutableBidderList { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_BIDDER_LIST), 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); - MapColorToMutableBids { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_BIDS), 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, idx_map(IDX_STATE_OWNER_MARGIN)) + } } diff --git a/contracts/wasm/fairauction/src/structs.rs b/contracts/wasm/fairauction/src/structs.rs index 9c238f72c6..a59feab046 100644 --- a/contracts/wasm/fairauction/src/structs.rs +++ b/contracts/wasm/fairauction/src/structs.rs @@ -5,58 +5,58 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] +#![allow(unused_imports)] use wasmlib::*; use wasmlib::host::*; +use crate::typedefs::*; pub struct Auction { - pub color: ScColor, // color of tokens for sale - pub creator: ScAgentID, // issuer of start_auction transaction - pub deposit: i64, // deposit by auction owner to cover the SC fees - pub description: String, // auction description - pub duration: i32, // auction duration in minutes - pub highest_bid: i64, // the current highest bid amount - pub highest_bidder: ScAgentID, // the current highest bidder - pub minimum_bid: i64, // minimum bid amount - pub num_tokens: i64, // number of tokens for sale - pub owner_margin: i64, // auction owner's margin in promilles - pub when_started: i64, // timestamp when auction started + pub color : ScColor, // color of tokens for sale + pub creator : ScAgentID, // issuer of start_auction transaction + pub deposit : i64, // deposit by auction owner to cover the SC fees + pub description : String, // auction description + pub duration : i32, // auction duration in minutes + pub highest_bid : i64, // the current highest bid amount + pub highest_bidder : ScAgentID, // the current highest bidder + pub minimum_bid : i64, // minimum bid amount + pub num_tokens : i64, // number of tokens for sale + pub owner_margin : i64, // auction owner's margin in promilles + pub when_started : i64, // timestamp when auction started } impl Auction { pub fn from_bytes(bytes: &[u8]) -> Auction { let mut decode = BytesDecoder::new(bytes); Auction { - color: decode.color(), - creator: decode.agent_id(), - deposit: decode.int64(), - description: decode.string(), - duration: decode.int32(), - highest_bid: decode.int64(), - highest_bidder: decode.agent_id(), - minimum_bid: decode.int64(), - num_tokens: decode.int64(), - owner_margin: decode.int64(), - when_started: decode.int64(), + color : decode.color(), + creator : decode.agent_id(), + deposit : decode.int64(), + description : decode.string(), + duration : decode.int32(), + highest_bid : decode.int64(), + highest_bidder : decode.agent_id(), + minimum_bid : decode.int64(), + num_tokens : decode.int64(), + owner_margin : decode.int64(), + when_started : decode.int64(), } } pub fn to_bytes(&self) -> Vec { let mut encode = BytesEncoder::new(); - encode.color(&self.color); - encode.agent_id(&self.creator); - encode.int64(self.deposit); - encode.string(&self.description); - encode.int32(self.duration); - encode.int64(self.highest_bid); - encode.agent_id(&self.highest_bidder); - encode.int64(self.minimum_bid); - encode.int64(self.num_tokens); - encode.int64(self.owner_margin); - encode.int64(self.when_started); + encode.color(&self.color); + encode.agent_id(&self.creator); + encode.int64(self.deposit); + encode.string(&self.description); + encode.int32(self.duration); + encode.int64(self.highest_bid); + encode.agent_id(&self.highest_bidder); + encode.int64(self.minimum_bid); + encode.int64(self.num_tokens); + encode.int64(self.owner_margin); + encode.int64(self.when_started); return encode.data(); } } @@ -82,6 +82,10 @@ pub struct MutableAuction { } impl MutableAuction { + 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) } @@ -96,26 +100,26 @@ impl MutableAuction { } pub struct Bid { - pub amount: i64, // cumulative amount of bids from same bidder - pub index: i32, // index of bidder in bidder list - pub timestamp: i64, // timestamp of most recent bid + pub amount : i64, // cumulative amount of bids from same bidder + pub index : i32, // index of bidder in bidder list + pub timestamp : i64, // timestamp of most recent bid } impl Bid { pub fn from_bytes(bytes: &[u8]) -> Bid { let mut decode = BytesDecoder::new(bytes); Bid { - amount: decode.int64(), - index: decode.int32(), - timestamp: decode.int64(), + amount : decode.int64(), + index : decode.int32(), + timestamp : decode.int64(), } } pub fn to_bytes(&self) -> Vec { let mut encode = BytesEncoder::new(); - encode.int64(self.amount); - encode.int32(self.index); - encode.int64(self.timestamp); + encode.int64(self.amount); + encode.int32(self.index); + encode.int64(self.timestamp); return encode.data(); } } @@ -141,6 +145,10 @@ pub struct MutableBid { } impl MutableBid { + 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) } @@ -153,5 +161,3 @@ impl MutableBid { Bid::from_bytes(&get_bytes(self.obj_id, self.key_id, TYPE_BYTES)) } } - -// @formatter:on diff --git a/contracts/wasm/fairauction/src/typedefs.rs b/contracts/wasm/fairauction/src/typedefs.rs index 260aaebe7c..dc306d8ad5 100644 --- a/contracts/wasm/fairauction/src/typedefs.rs +++ b/contracts/wasm/fairauction/src/typedefs.rs @@ -5,17 +5,14 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use wasmlib::host::*; - use crate::structs::*; pub struct ArrayOfImmutableAgentID { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfImmutableAgentID { @@ -31,7 +28,7 @@ impl ArrayOfImmutableAgentID { pub type ImmutableBidderList = ArrayOfImmutableAgentID; pub struct ArrayOfMutableAgentID { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfMutableAgentID { @@ -51,7 +48,7 @@ impl ArrayOfMutableAgentID { pub type MutableBidderList = ArrayOfMutableAgentID; pub struct MapAgentIDToImmutableBid { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapAgentIDToImmutableBid { @@ -63,12 +60,12 @@ impl MapAgentIDToImmutableBid { pub type ImmutableBids = MapAgentIDToImmutableBid; pub struct MapAgentIDToMutableBid { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapAgentIDToMutableBid { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_bid(&self, key: &ScAgentID) -> MutableBid { @@ -77,5 +74,3 @@ impl MapAgentIDToMutableBid { } pub type MutableBids = MapAgentIDToMutableBid; - -// @formatter:on diff --git a/contracts/wasm/fairauction/test/fairauction_bg.wasm b/contracts/wasm/fairauction/test/fairauction_bg.wasm index 960c862ae3..86bf39de87 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/consts.ts b/contracts/wasm/fairauction/ts/fairauction/consts.ts index 9fb063c8f5..e4b544c88d 100644 --- a/contracts/wasm/fairauction/ts/fairauction/consts.ts +++ b/contracts/wasm/fairauction/ts/fairauction/consts.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export const ScName = "fairauction"; export const ScDescription = "Decentralized auction to securely sell tokens to the highest bidder"; diff --git a/contracts/wasm/fairauction/ts/fairauction/contract.ts b/contracts/wasm/fairauction/ts/fairauction/contract.ts index 8c70e07bb8..56b06394f3 100644 --- a/contracts/wasm/fairauction/ts/fairauction/contract.ts +++ b/contracts/wasm/fairauction/ts/fairauction/contract.ts @@ -5,63 +5,62 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class FinalizeAuctionCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncFinalizeAuction); - params: sc.MutableFinalizeAuctionParams = new sc.MutableFinalizeAuctionParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncFinalizeAuction); + params: sc.MutableFinalizeAuctionParams = new sc.MutableFinalizeAuctionParams(); } export class FinalizeAuctionContext { - params: sc.ImmutableFinalizeAuctionParams = new sc.ImmutableFinalizeAuctionParams(); - state: sc.MutableFairAuctionState = new sc.MutableFairAuctionState(); + params: sc.ImmutableFinalizeAuctionParams = new sc.ImmutableFinalizeAuctionParams(); + state: sc.MutableFairAuctionState = new sc.MutableFairAuctionState(); } export class PlaceBidCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPlaceBid); - params: sc.MutablePlaceBidParams = new sc.MutablePlaceBidParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPlaceBid); + params: sc.MutablePlaceBidParams = new sc.MutablePlaceBidParams(); } export class PlaceBidContext { - params: sc.ImmutablePlaceBidParams = new sc.ImmutablePlaceBidParams(); - state: sc.MutableFairAuctionState = new sc.MutableFairAuctionState(); + params: sc.ImmutablePlaceBidParams = new sc.ImmutablePlaceBidParams(); + state: sc.MutableFairAuctionState = new sc.MutableFairAuctionState(); } export class SetOwnerMarginCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetOwnerMargin); - params: sc.MutableSetOwnerMarginParams = new sc.MutableSetOwnerMarginParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetOwnerMargin); + params: sc.MutableSetOwnerMarginParams = new sc.MutableSetOwnerMarginParams(); } export class SetOwnerMarginContext { - params: sc.ImmutableSetOwnerMarginParams = new sc.ImmutableSetOwnerMarginParams(); - state: sc.MutableFairAuctionState = new sc.MutableFairAuctionState(); + params: sc.ImmutableSetOwnerMarginParams = new sc.ImmutableSetOwnerMarginParams(); + state: sc.MutableFairAuctionState = new sc.MutableFairAuctionState(); } export class StartAuctionCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncStartAuction); - params: sc.MutableStartAuctionParams = new sc.MutableStartAuctionParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncStartAuction); + params: sc.MutableStartAuctionParams = new sc.MutableStartAuctionParams(); } export class StartAuctionContext { - params: sc.ImmutableStartAuctionParams = new sc.ImmutableStartAuctionParams(); - state: sc.MutableFairAuctionState = new sc.MutableFairAuctionState(); + params: sc.ImmutableStartAuctionParams = new sc.ImmutableStartAuctionParams(); + state: sc.MutableFairAuctionState = new sc.MutableFairAuctionState(); } export class GetInfoCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetInfo); - params: sc.MutableGetInfoParams = new sc.MutableGetInfoParams(); - results: sc.ImmutableGetInfoResults = new sc.ImmutableGetInfoResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetInfo); + params: sc.MutableGetInfoParams = new sc.MutableGetInfoParams(); + results: sc.ImmutableGetInfoResults = new sc.ImmutableGetInfoResults(); } export class GetInfoContext { - params: sc.ImmutableGetInfoParams = new sc.ImmutableGetInfoParams(); - results: sc.MutableGetInfoResults = new sc.MutableGetInfoResults(); - state: sc.ImmutableFairAuctionState = new sc.ImmutableFairAuctionState(); + params: sc.ImmutableGetInfoParams = new sc.ImmutableGetInfoParams(); + results: sc.MutableGetInfoResults = new sc.MutableGetInfoResults(); + state: sc.ImmutableFairAuctionState = new sc.ImmutableFairAuctionState(); } export class ScFuncs { - static finalizeAuction(ctx: wasmlib.ScFuncCallContext): FinalizeAuctionCall { let f = new FinalizeAuctionCall(); f.func.setPtrs(f.params, null); diff --git a/contracts/wasm/fairauction/ts/fairauction/keys.ts b/contracts/wasm/fairauction/ts/fairauction/keys.ts index 9bb253e5d8..b4d09d3c3a 100644 --- a/contracts/wasm/fairauction/ts/fairauction/keys.ts +++ b/contracts/wasm/fairauction/ts/fairauction/keys.ts @@ -5,14 +5,15 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; -export const IdxParamColor = 0; -export const IdxParamDescription = 1; -export const IdxParamDuration = 2; -export const IdxParamMinimumBid = 3; -export const IdxParamOwnerMargin = 4; +export const IdxParamColor = 0; +export const IdxParamDescription = 1; +export const IdxParamDuration = 2; +export const IdxParamMinimumBid = 3; +export const IdxParamOwnerMargin = 4; + export const IdxResultBidders = 5; export const IdxResultColor = 6; export const IdxResultCreator = 7; @@ -25,33 +26,34 @@ export const IdxResultMinimumBid = 13; export const IdxResultNumTokens = 14; export const IdxResultOwnerMargin = 15; export const IdxResultWhenStarted = 16; -export const IdxStateAuctions = 17; -export const IdxStateBidderList = 18; -export const IdxStateBids = 19; -export const IdxStateOwnerMargin = 20; + +export const IdxStateAuctions = 17; +export const IdxStateBidderList = 18; +export const IdxStateBids = 19; +export const IdxStateOwnerMargin = 20; export let keyMap: string[] = [ - sc.ParamColor, - sc.ParamDescription, - sc.ParamDuration, - sc.ParamMinimumBid, - sc.ParamOwnerMargin, - sc.ResultBidders, - sc.ResultColor, - sc.ResultCreator, - sc.ResultDeposit, - sc.ResultDescription, - sc.ResultDuration, - sc.ResultHighestBid, - sc.ResultHighestBidder, - sc.ResultMinimumBid, - sc.ResultNumTokens, - sc.ResultOwnerMargin, - sc.ResultWhenStarted, - sc.StateAuctions, - sc.StateBidderList, - sc.StateBids, - sc.StateOwnerMargin, + sc.ParamColor, + sc.ParamDescription, + sc.ParamDuration, + sc.ParamMinimumBid, + sc.ParamOwnerMargin, + sc.ResultBidders, + sc.ResultColor, + sc.ResultCreator, + sc.ResultDeposit, + sc.ResultDescription, + sc.ResultDuration, + sc.ResultHighestBid, + sc.ResultHighestBidder, + sc.ResultMinimumBid, + sc.ResultNumTokens, + sc.ResultOwnerMargin, + sc.ResultWhenStarted, + sc.StateAuctions, + sc.StateBidderList, + sc.StateBids, + sc.StateOwnerMargin, ]; export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/fairauction/ts/fairauction/lib.ts b/contracts/wasm/fairauction/ts/fairauction/lib.ts index 9b46528318..2f7ea11525 100644 --- a/contracts/wasm/fairauction/ts/fairauction/lib.ts +++ b/contracts/wasm/fairauction/ts/fairauction/lib.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export function on_call(index: i32): void { @@ -15,10 +15,10 @@ export function on_call(index: i32): void { export function on_load(): void { let exports = new wasmlib.ScExports(); exports.addFunc(sc.FuncFinalizeAuction, funcFinalizeAuctionThunk); - exports.addFunc(sc.FuncPlaceBid, funcPlaceBidThunk); - exports.addFunc(sc.FuncSetOwnerMargin, funcSetOwnerMarginThunk); - exports.addFunc(sc.FuncStartAuction, funcStartAuctionThunk); - exports.addView(sc.ViewGetInfo, viewGetInfoThunk); + exports.addFunc(sc.FuncPlaceBid, funcPlaceBidThunk); + exports.addFunc(sc.FuncSetOwnerMargin, funcSetOwnerMarginThunk); + exports.addFunc(sc.FuncStartAuction, funcStartAuctionThunk); + exports.addView(sc.ViewGetInfo, viewGetInfoThunk); for (let i = 0; i < sc.keyMap.length; i++) { sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); @@ -26,59 +26,61 @@ export function on_load(): void { } function funcFinalizeAuctionThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("fairauction.funcFinalizeAuction"); - // only SC itself can invoke this function - ctx.require(ctx.caller().equals(ctx.accountID()), "no permission"); + ctx.log("fairauction.funcFinalizeAuction"); - let f = new sc.FinalizeAuctionContext(); + // only SC itself can invoke this function + ctx.require(ctx.caller().equals(ctx.accountID()), "no permission"); + + let f = new sc.FinalizeAuctionContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.color().exists(), "missing mandatory color") - sc.funcFinalizeAuction(ctx, f); - ctx.log("fairauction.funcFinalizeAuction ok"); + ctx.require(f.params.color().exists(), "missing mandatory color"); + sc.funcFinalizeAuction(ctx, f); + ctx.log("fairauction.funcFinalizeAuction ok"); } function funcPlaceBidThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("fairauction.funcPlaceBid"); - let f = new sc.PlaceBidContext(); + ctx.log("fairauction.funcPlaceBid"); + let f = new sc.PlaceBidContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.color().exists(), "missing mandatory color") - sc.funcPlaceBid(ctx, f); - ctx.log("fairauction.funcPlaceBid ok"); + ctx.require(f.params.color().exists(), "missing mandatory color"); + sc.funcPlaceBid(ctx, f); + ctx.log("fairauction.funcPlaceBid ok"); } function funcSetOwnerMarginThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("fairauction.funcSetOwnerMargin"); - // only SC creator can set owner margin - ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + ctx.log("fairauction.funcSetOwnerMargin"); + + // only SC creator can set owner margin + ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); - let f = new sc.SetOwnerMarginContext(); + let f = new sc.SetOwnerMarginContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.ownerMargin().exists(), "missing mandatory ownerMargin") - sc.funcSetOwnerMargin(ctx, f); - ctx.log("fairauction.funcSetOwnerMargin ok"); + ctx.require(f.params.ownerMargin().exists(), "missing mandatory ownerMargin"); + sc.funcSetOwnerMargin(ctx, f); + ctx.log("fairauction.funcSetOwnerMargin ok"); } function funcStartAuctionThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("fairauction.funcStartAuction"); - let f = new sc.StartAuctionContext(); + ctx.log("fairauction.funcStartAuction"); + let f = new sc.StartAuctionContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.color().exists(), "missing mandatory color") - ctx.require(f.params.minimumBid().exists(), "missing mandatory minimumBid") - sc.funcStartAuction(ctx, f); - ctx.log("fairauction.funcStartAuction ok"); + ctx.require(f.params.color().exists(), "missing mandatory color"); + ctx.require(f.params.minimumBid().exists(), "missing mandatory minimumBid"); + sc.funcStartAuction(ctx, f); + ctx.log("fairauction.funcStartAuction ok"); } function viewGetInfoThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("fairauction.viewGetInfo"); - let f = new sc.GetInfoContext(); + ctx.log("fairauction.viewGetInfo"); + let f = new sc.GetInfoContext(); 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.color().exists(), "missing mandatory color") - sc.viewGetInfo(ctx, f); - ctx.log("fairauction.viewGetInfo ok"); + ctx.require(f.params.color().exists(), "missing mandatory color"); + sc.viewGetInfo(ctx, f); + ctx.log("fairauction.viewGetInfo ok"); } diff --git a/contracts/wasm/fairauction/ts/fairauction/params.ts b/contracts/wasm/fairauction/ts/fairauction/params.ts index 493722760d..eccc9a4cb5 100644 --- a/contracts/wasm/fairauction/ts/fairauction/params.ts +++ b/contracts/wasm/fairauction/ts/fairauction/params.ts @@ -5,99 +5,89 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxParamColor]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } } 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, sc.idxMap[sc.IdxParamOwnerMargin]); + } } 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, sc.idxMap[sc.IdxParamOwnerMargin]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } description(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamDescription]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamDescription]); + } duration(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamDuration]); - } + return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamDuration]); + } minimumBid(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamMinimumBid]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamMinimumBid]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } description(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamDescription]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamDescription]); + } duration(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamDuration]); - } + return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamDuration]); + } minimumBid(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamMinimumBid]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamMinimumBid]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } } diff --git a/contracts/wasm/fairauction/ts/fairauction/results.ts b/contracts/wasm/fairauction/ts/fairauction/results.ts index 59dd2a1465..3e55c1bb0e 100644 --- a/contracts/wasm/fairauction/ts/fairauction/results.ts +++ b/contracts/wasm/fairauction/ts/fairauction/results.ts @@ -5,107 +5,105 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxResultBidders]); + } color(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxResultColor]); - } + return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxResultColor]); + } creator(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultCreator]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultCreator]); + } deposit(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultDeposit]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultDeposit]); + } description(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultDescription]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxResultDescription]); + } duration(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxResultDuration]); - } + return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxResultDuration]); + } highestBid(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultHighestBid]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultHighestBid]); + } highestBidder(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultHighestBidder]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxResultHighestBidder]); + } minimumBid(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultMinimumBid]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultMinimumBid]); + } numTokens(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultNumTokens]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultNumTokens]); + } ownerMargin(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultOwnerMargin]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultOwnerMargin]); + } whenStarted(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultWhenStarted]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultWhenStarted]); + } } 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, sc.idxMap[sc.IdxResultBidders]); + } color(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxResultColor]); - } + return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxResultColor]); + } creator(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultCreator]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultCreator]); + } deposit(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultDeposit]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultDeposit]); + } description(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultDescription]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxResultDescription]); + } duration(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxResultDuration]); - } + return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxResultDuration]); + } highestBid(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultHighestBid]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultHighestBid]); + } highestBidder(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultHighestBidder]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxResultHighestBidder]); + } minimumBid(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultMinimumBid]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultMinimumBid]); + } numTokens(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultNumTokens]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultNumTokens]); + } ownerMargin(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultOwnerMargin]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultOwnerMargin]); + } whenStarted(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultWhenStarted]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultWhenStarted]); + } } diff --git a/contracts/wasm/fairauction/ts/fairauction/state.ts b/contracts/wasm/fairauction/ts/fairauction/state.ts index 3de34106d4..cc35e60b89 100644 --- a/contracts/wasm/fairauction/ts/fairauction/state.ts +++ b/contracts/wasm/fairauction/ts/fairauction/state.ts @@ -5,11 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class MapColorToImmutableAuction { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -21,7 +21,7 @@ export class MapColorToImmutableAuction { } export class MapColorToImmutableBidderList { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -34,7 +34,7 @@ export class MapColorToImmutableBidderList { } export class MapColorToImmutableBids { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -47,36 +47,35 @@ 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); - return new sc.MapColorToImmutableAuction(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateAuctions], wasmlib.TYPE_MAP); + return new sc.MapColorToImmutableAuction(mapID); + } bidderList(): sc.MapColorToImmutableBidderList { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBidderList], wasmlib.TYPE_MAP); - return new sc.MapColorToImmutableBidderList(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBidderList], wasmlib.TYPE_MAP); + return new sc.MapColorToImmutableBidderList(mapID); + } bids(): sc.MapColorToImmutableBids { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBids], wasmlib.TYPE_MAP); - return new sc.MapColorToImmutableBids(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBids], 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, sc.idxMap[sc.IdxStateOwnerMargin]); + } } export class MapColorToMutableAuction { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getAuction(key: wasmlib.ScColor): sc.MutableAuction { @@ -85,14 +84,14 @@ export class MapColorToMutableAuction { } export class MapColorToMutableBidderList { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getBidderList(key: wasmlib.ScColor): sc.MutableBidderList { @@ -102,14 +101,14 @@ export class MapColorToMutableBidderList { } export class MapColorToMutableBids { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getBids(key: wasmlib.ScColor): sc.MutableBids { @@ -119,23 +118,22 @@ export class MapColorToMutableBids { } export class MutableFairAuctionState extends wasmlib.ScMapID { - auctions(): sc.MapColorToMutableAuction { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateAuctions], wasmlib.TYPE_MAP); - return new sc.MapColorToMutableAuction(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateAuctions], wasmlib.TYPE_MAP); + return new sc.MapColorToMutableAuction(mapID); + } bidderList(): sc.MapColorToMutableBidderList { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBidderList], wasmlib.TYPE_MAP); - return new sc.MapColorToMutableBidderList(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBidderList], wasmlib.TYPE_MAP); + return new sc.MapColorToMutableBidderList(mapID); + } bids(): sc.MapColorToMutableBids { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBids], wasmlib.TYPE_MAP); - return new sc.MapColorToMutableBids(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBids], 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, sc.idxMap[sc.IdxStateOwnerMargin]); + } } diff --git a/contracts/wasm/fairauction/ts/fairauction/structs.ts b/contracts/wasm/fairauction/ts/fairauction/structs.ts index 9a53456c19..2325e38180 100644 --- a/contracts/wasm/fairauction/ts/fairauction/structs.ts +++ b/contracts/wasm/fairauction/ts/fairauction/structs.ts @@ -5,52 +5,52 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export class Auction { - color : wasmlib.ScColor = new wasmlib.ScColor(0); // color of tokens for sale - creator : wasmlib.ScAgentID = new wasmlib.ScAgentID(); // issuer of start_auction transaction - deposit : i64 = 0; // deposit by auction owner to cover the SC fees - description : string = ""; // auction description - duration : i32 = 0; // auction duration in minutes - highestBid : i64 = 0; // the current highest bid amount - highestBidder: wasmlib.ScAgentID = new wasmlib.ScAgentID(); // the current highest bidder - minimumBid : i64 = 0; // minimum bid amount - numTokens : i64 = 0; // number of tokens for sale - ownerMargin : i64 = 0; // auction owner's margin in promilles - whenStarted : i64 = 0; // timestamp when auction started + color : wasmlib.ScColor = new wasmlib.ScColor(0); // color of tokens for sale + creator : wasmlib.ScAgentID = new wasmlib.ScAgentID(); // issuer of start_auction transaction + deposit : i64 = 0; // deposit by auction owner to cover the SC fees + description : string = ""; // auction description + duration : i32 = 0; // auction duration in minutes + highestBid : i64 = 0; // the current highest bid amount + highestBidder : wasmlib.ScAgentID = new wasmlib.ScAgentID(); // the current highest bidder + minimumBid : i64 = 0; // minimum bid amount + numTokens : i64 = 0; // number of tokens for sale + ownerMargin : i64 = 0; // auction owner's margin in promilles + whenStarted : i64 = 0; // timestamp when auction started static fromBytes(bytes: u8[]): Auction { let decode = new wasmlib.BytesDecoder(bytes); let data = new Auction(); - data.color = decode.color(); - data.creator = decode.agentID(); - data.deposit = decode.int64(); - data.description = decode.string(); - data.duration = decode.int32(); - data.highestBid = decode.int64(); + data.color = decode.color(); + data.creator = decode.agentID(); + data.deposit = decode.int64(); + data.description = decode.string(); + data.duration = decode.int32(); + data.highestBid = decode.int64(); data.highestBidder = decode.agentID(); - data.minimumBid = decode.int64(); - data.numTokens = decode.int64(); - data.ownerMargin = decode.int64(); - data.whenStarted = decode.int64(); + data.minimumBid = decode.int64(); + data.numTokens = decode.int64(); + data.ownerMargin = decode.int64(); + data.whenStarted = decode.int64(); decode.close(); return data; } bytes(): u8[] { return new wasmlib.BytesEncoder(). - color(this.color). - agentID(this.creator). - int64(this.deposit). - string(this.description). - int32(this.duration). - int64(this.highestBid). - agentID(this.highestBidder). - int64(this.minimumBid). - int64(this.numTokens). - int64(this.ownerMargin). - int64(this.whenStarted). + color(this.color). + agentID(this.creator). + int64(this.deposit). + string(this.description). + int32(this.duration). + int64(this.highestBid). + agentID(this.highestBidder). + int64(this.minimumBid). + int64(this.numTokens). + int64(this.ownerMargin). + int64(this.whenStarted). data(); } } @@ -69,7 +69,7 @@ export class ImmutableAuction { } value(): Auction { - return Auction.fromBytes(wasmlib.getBytes(this.objID, this.keyID,wasmlib. TYPE_BYTES)); + return Auction.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); } } @@ -82,6 +82,10 @@ export class MutableAuction { 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); } @@ -91,20 +95,20 @@ export class MutableAuction { } value(): Auction { - return Auction.fromBytes(wasmlib.getBytes(this.objID, this.keyID,wasmlib. TYPE_BYTES)); + return Auction.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); } } export class Bid { - amount : i64 = 0; // cumulative amount of bids from same bidder - index : i32 = 0; // index of bidder in bidder list - timestamp: i64 = 0; // timestamp of most recent bid + amount : i64 = 0; // cumulative amount of bids from same bidder + index : i32 = 0; // index of bidder in bidder list + timestamp : i64 = 0; // timestamp of most recent bid static fromBytes(bytes: u8[]): Bid { let decode = new wasmlib.BytesDecoder(bytes); let data = new Bid(); - data.amount = decode.int64(); - data.index = decode.int32(); + data.amount = decode.int64(); + data.index = decode.int32(); data.timestamp = decode.int64(); decode.close(); return data; @@ -112,9 +116,9 @@ export class Bid { bytes(): u8[] { return new wasmlib.BytesEncoder(). - int64(this.amount). - int32(this.index). - int64(this.timestamp). + int64(this.amount). + int32(this.index). + int64(this.timestamp). data(); } } @@ -133,7 +137,7 @@ export class ImmutableBid { } value(): Bid { - return Bid.fromBytes(wasmlib.getBytes(this.objID, this.keyID,wasmlib. TYPE_BYTES)); + return Bid.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); } } @@ -146,6 +150,10 @@ export class MutableBid { 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); } @@ -155,6 +163,6 @@ export class MutableBid { } value(): Bid { - return Bid.fromBytes(wasmlib.getBytes(this.objID, this.keyID,wasmlib. TYPE_BYTES)); + return Bid.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); } } diff --git a/contracts/wasm/fairauction/ts/fairauction/typedefs.ts b/contracts/wasm/fairauction/ts/fairauction/typedefs.ts index 30d6a27bac..246878fa3c 100644 --- a/contracts/wasm/fairauction/ts/fairauction/typedefs.ts +++ b/contracts/wasm/fairauction/ts/fairauction/typedefs.ts @@ -5,11 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ArrayOfImmutableAgentID { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -28,7 +28,7 @@ export class ImmutableBidderList extends ArrayOfImmutableAgentID { }; export class ArrayOfMutableAgentID { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -51,7 +51,7 @@ export class MutableBidderList extends ArrayOfMutableAgentID { }; export class MapAgentIDToImmutableBid { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -66,14 +66,14 @@ export class ImmutableBids extends MapAgentIDToImmutableBid { }; export class MapAgentIDToMutableBid { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getBid(key: wasmlib.ScAgentID): sc.MutableBid { diff --git a/contracts/wasm/fairroulette/frontend/package-lock.json b/contracts/wasm/fairroulette/frontend/package-lock.json index a67c277c27..20257cd895 100644 --- a/contracts/wasm/fairroulette/frontend/package-lock.json +++ b/contracts/wasm/fairroulette/frontend/package-lock.json @@ -1,6502 +1,46 @@ { "name": "svelte-app", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 1, "requires": true, - "packages": { - "": { - "name": "svelte-app", - "version": "1.0.0", - "dependencies": { - "@babel/eslint-parser": "^7.15.8", - "lottie-web": "^5.7.13", - "svelte-router-spa": "^6.0.2" - }, - "devDependencies": { - "@rollup/plugin-commonjs": "^17.0.0", - "@rollup/plugin-node-resolve": "^11.0.0", - "@rollup/plugin-replace": "^3.0.0", - "@rollup/plugin-typescript": "^8.2.5", - "@tsconfig/svelte": "^2.0.0", - "@types/gtag.js": "^0.0.7", - "@typescript-eslint/eslint-plugin": "^4.29.2", - "@typescript-eslint/parser": "^4.29.2", - "base64-js": "^1.5.1", - "blakejs": "^1.1.1", - "eslint": "^7.32.0", - "eslint-plugin-security": "^1.4.0", - "eslint-plugin-svelte3": "^3.2.0", - "ieee754": "^1.2.1", - "nanoevents": "^6.0.0", - "node-sass": "^6.0.1", - "prettier": "^2.3.2", - "random-number-csprng": "^1.0.2", - "rollup": "^2.3.4", - "rollup-plugin-css-only": "^3.1.0", - "rollup-plugin-livereload": "^2.0.0", - "rollup-plugin-node-builtins": "^2.1.2", - "rollup-plugin-node-globals": "^1.4.0", - "rollup-plugin-svelte": "^7.0.0", - "rollup-plugin-terser": "^7.0.0", - "rollup-plugin-typescript2": "^0.30.0", - "rollup-plugin-web-worker-loader": "^1.6.1", - "sirv-cli": "^1.0.0", - "svelte": "^3.0.0", - "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" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz", - "integrity": "sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.15.8", - "@babel/generator": "^7.15.8", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.8", - "@babel/helpers": "^7.15.4", - "@babel/parser": "^7.15.8", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", - "peer": true, - "dependencies": { - "@babel/highlight": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/core/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@babel/eslint-parser": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.15.8.tgz", - "integrity": "sha512-fYP7QFngCvgxjUuw8O057SVH5jCXsbFFOoE77CFDcvzwBVgTOkMD/L4mIC5Ud1xf8chK/no2fRbSSn1wvNmKuQ==", - "dependencies": { - "eslint-scope": "^5.1.1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": ">=7.11.0", - "eslint": ">=7.5.0" - } - }, - "node_modules/@babel/eslint-parser/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz", - "integrity": "sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==", - "peer": true, - "dependencies": { - "@babel/types": "^7.15.6", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", - "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", - "peer": true, - "dependencies": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "peer": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", - "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", - "peer": true, - "dependencies": { - "@babel/helper-get-function-arity": "^7.15.4", - "@babel/template": "^7.15.4", - "@babel/types": "^7.15.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", - "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", - "peer": true, - "dependencies": { - "@babel/types": "^7.15.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", - "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", - "peer": true, - "dependencies": { - "@babel/types": "^7.15.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", - "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", - "peer": true, - "dependencies": { - "@babel/types": "^7.15.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", - "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", - "peer": true, - "dependencies": { - "@babel/types": "^7.15.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz", - "integrity": "sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==", - "peer": true, - "dependencies": { - "@babel/helper-module-imports": "^7.15.4", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-simple-access": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/helper-validator-identifier": "^7.15.7", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", - "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", - "peer": true, - "dependencies": { - "@babel/types": "^7.15.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", - "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", - "peer": true, - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", - "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", - "peer": true, - "dependencies": { - "@babel/types": "^7.15.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", - "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", - "peer": true, - "dependencies": { - "@babel/types": "^7.15.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.15.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", - "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", - "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", - "peer": true, - "dependencies": { - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz", - "integrity": "sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==", - "peer": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/template": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", - "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template/node_modules/@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", - "peer": true, - "dependencies": { - "@babel/highlight": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", - "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-hoist-variables": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", - "peer": true, - "dependencies": { - "@babel/highlight": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/types": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", - "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", - "peer": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", - "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.1.1", - "espree": "^7.3.0", - "globals": "^13.9.0", - "ignore": "^4.0.6", - "import-fresh": "^3.2.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", - "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.0", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==" - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.21", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz", - "integrity": "sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==", - "dev": true - }, - "node_modules/@rollup/plugin-commonjs": { - "version": "17.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-17.1.0.tgz", - "integrity": "sha512-PoMdXCw0ZyvjpCMT5aV4nkL0QywxP29sODQsSGeDpr/oI49Qq9tRtAsb/LbYbDzFlOydVEqHmmZWFtXJEAX9ew==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "commondir": "^1.0.1", - "estree-walker": "^2.0.1", - "glob": "^7.1.6", - "is-reference": "^1.2.1", - "magic-string": "^0.25.7", - "resolve": "^1.17.0" - }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^2.30.0" - } - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "11.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", - "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">= 10.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" - } - }, - "node_modules/@rollup/plugin-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-3.0.0.tgz", - "integrity": "sha512-3c7JCbMuYXM4PbPWT4+m/4Y6U60SgsnDT/cCyAyUKwFHg7pTSfsSQzIpETha3a3ig6OdOKzZz87D9ZXIK3qsDg==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "magic-string": "^0.25.7" - }, - "peerDependencies": { - "rollup": "^1.20.0 || ^2.0.0" - } - }, - "node_modules/@rollup/plugin-typescript": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.3.0.tgz", - "integrity": "sha512-I5FpSvLbtAdwJ+naznv+B4sjXZUcIvLLceYpITAn7wAP8W0wqc5noLdGIp9HGVntNhRWXctwPYrSSFQxtl0FPA==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^3.1.0", - "resolve": "^1.17.0" - }, - "engines": { - "node": ">=8.0.0" - }, - "peerDependencies": { - "rollup": "^2.14.0", - "tslib": "*", - "typescript": ">=3.7.0" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dev": true, - "dependencies": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0" - } - }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - }, - "node_modules/@tsconfig/svelte": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/svelte/-/svelte-2.0.1.tgz", - "integrity": "sha512-aqkICXbM1oX5FfgZd2qSSAGdyo/NRxjWCamxoyi3T8iVQnzGge19HhDYzZ6NrVOW7bhcWNSq9XexWFtMzbB24A==", - "dev": true - }, - "node_modules/@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "node_modules/@types/gtag.js": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.7.tgz", - "integrity": "sha512-Kl5beBoB0OXw7WeFgHHpLEchvC7HyIu3v1AksNNTemAF6jmEmQGqhZQSHcG6BOU/Lq0xsByQNqLzicLPjVkxYQ==", - "dev": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.9", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", - "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", - "dev": true - }, - "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "16.11.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz", - "integrity": "sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==", - "dev": true - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true - }, - "node_modules/@types/pug": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@types/pug/-/pug-2.0.5.tgz", - "integrity": "sha512-LOnASQoeNZMkzexRuyqcBBDZ6rS+rQxUMkmj5A0PkhhiSZivLIuz6Hxyr1mkGoEZEkk66faROmpMi4fFkrKsBA==", - "dev": true - }, - "node_modules/@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/sass": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/@types/sass/-/sass-1.16.1.tgz", - "integrity": "sha512-iZUcRrGuz/Tbg3loODpW7vrQJkUtpY2fFSf4ELqqkApcS2TkZ1msk7ie8iZPB86lDOP8QOTTmuvWjc5S0R9OjQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz", - "integrity": "sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg==", - "dev": true, - "dependencies": { - "@typescript-eslint/experimental-utils": "4.33.0", - "@typescript-eslint/scope-manager": "4.33.0", - "debug": "^4.3.1", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.1.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^4.0.0", - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz", - "integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.33.0.tgz", - "integrity": "sha512-ZohdsbXadjGBSK0/r+d87X0SBmKzOq4/S5nzK6SBgJspFo9/CUDJ7hjayuze+JK7CZQLDMroqytp7pOcFKTxZA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "4.33.0", - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/typescript-estree": "4.33.0", - "debug": "^4.3.1" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz", - "integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz", - "integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz", - "integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.33.0", - "@typescript-eslint/visitor-keys": "4.33.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.33.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz", - "integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.33.0", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/abstract-leveldown": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/abstract-leveldown/-/abstract-leveldown-0.12.4.tgz", - "integrity": "sha1-KeGOYy5g5OIh1YECR4UqY9ey5BA=", - "dev": true, - "dependencies": { - "xtend": "~3.0.0" - } - }, - "node_modules/abstract-leveldown/node_modules/xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "engines": { - "node": ">=0.4.2" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/aproba": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", - "dev": true - }, - "node_modules/are-we-there-yet": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", - "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/asn1.js/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/async-foreach": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", - "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", - "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "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/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/bl": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/bl/-/bl-0.8.2.tgz", - "integrity": "sha1-yba8oI0bwuoA/Ir7Txpf0eHGbk4=", - "dev": true, - "dependencies": { - "readable-stream": "~1.0.26" - } - }, - "node_modules/bl/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/bl/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/bl/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "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/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "node_modules/browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "dependencies": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "dependencies": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "node_modules/browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/browserify-fs": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browserify-fs/-/browserify-fs-1.0.0.tgz", - "integrity": "sha1-8HWqinKdTRcW0GZiDjhvzBMRqW8=", - "dev": true, - "dependencies": { - "level-filesystem": "^1.0.1", - "level-js": "^2.1.3", - "levelup": "^0.18.2" - } - }, - "node_modules/browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "dev": true, - "dependencies": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - } - }, - "node_modules/browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "dependencies": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - } - }, - "node_modules/browserify-sign/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/browserify-sign/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "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/browserslist": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.5.tgz", - "integrity": "sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==", - "peer": true, - "dependencies": { - "caniuse-lite": "^1.0.30001271", - "electron-to-chromium": "^1.3.878", - "escalade": "^3.1.1", - "node-releases": "^2.0.1", - "picocolors": "^1.0.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-es6": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/buffer-es6/-/buffer-es6-4.9.3.tgz", - "integrity": "sha1-8mNHuC33b9N+GLy1KIxJcM/VxAQ=", - "dev": true - }, - "node_modules/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 - }, - "node_modules/buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "node_modules/builtin-modules": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", - "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-keys": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", - "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "map-obj": "^4.0.0", - "quick-lru": "^4.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001271", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001271.tgz", - "integrity": "sha512-BBruZFWmt3HFdVPS8kceTBIguKxu4f99n5JNp06OlPD/luoAMIaIK5ieV5YjnBLH3Nysai9sxj9rpJj4ZisXOA==", - "peer": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chokidar": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", - "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/clone": { - "version": "0.1.19", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.1.19.tgz", - "integrity": "sha1-YT+2hjmyaklKxTJT4Vsaa9iK2oU=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/console-clear": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/console-clear/-/console-clear-1.1.1.tgz", - "integrity": "sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "peer": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, - "node_modules/create-ecdh/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/create-error": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/create-error/-/create-error-0.3.1.tgz", - "integrity": "sha1-aYECRaYp5lRDK/BDdzYAA6U1GiM=", - "dev": true - }, - "node_modules/create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "node_modules/create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "dependencies": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - }, - "engines": { - "node": "*" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", - "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", - "dev": true, - "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/deferred-leveldown": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-0.2.0.tgz", - "integrity": "sha1-LO8fER4cV4cNi7uK8mUOWHzS9bQ=", - "dev": true, - "dependencies": { - "abstract-leveldown": "~0.12.1" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", - "dev": true - }, - "node_modules/des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, - "node_modules/diffie-hellman/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.3.880", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.880.tgz", - "integrity": "sha512-iwIP/6WoeSimzUKJIQtjtpVDsK8Ir8qQCMXsUBwg+rxJR2Uh3wTNSbxoYRfs+3UWx/9MAnPIxVZCyWkm8MT0uw==", - "peer": true - }, - "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "dev": true, - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dependencies": { - "ansi-colors": "^4.1.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/errno": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", - "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", - "dev": true, - "dependencies": { - "prr": "~1.0.1" - }, - "bin": { - "errno": "cli.js" - } - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es6-promise": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", - "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", - "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", - "dependencies": { - "@babel/code-frame": "7.12.11", - "@eslint/eslintrc": "^0.4.3", - "@humanwhocodes/config-array": "^0.5.0", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.0.1", - "doctrine": "^3.0.0", - "enquirer": "^2.3.5", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^2.1.0", - "eslint-visitor-keys": "^2.0.0", - "espree": "^7.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^5.1.2", - "globals": "^13.6.0", - "ignore": "^4.0.6", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^3.13.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "progress": "^2.0.0", - "regexpp": "^3.1.0", - "semver": "^7.2.1", - "strip-ansi": "^6.0.0", - "strip-json-comments": "^3.1.0", - "table": "^6.0.9", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-plugin-security": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-security/-/eslint-plugin-security-1.4.0.tgz", - "integrity": "sha512-xlS7P2PLMXeqfhyf3NpqbvbnW04kN8M9NtmhpR3XGyOvt/vNKS7XPXT5EDbwKW9vCjWH4PpfQvgD/+JgN0VJKA==", - "dev": true, - "dependencies": { - "safe-regex": "^1.1.0" - } - }, - "node_modules/eslint-plugin-svelte3": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-3.2.1.tgz", - "integrity": "sha512-YoBR9mLoKCjGghJ/gvpnFZKaMEu/VRcuxpSRS8KuozuEo7CdBH7bmBHa6FmMm0i4kJnOyx+PVsaptz96K6H/4Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "eslint": ">=6.0.0", - "svelte": "^3.2.0" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint/node_modules/eslint-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", - "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dependencies": { - "eslint-visitor-keys": "^1.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/eslint/node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/eslint/node_modules/ignore": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/esm": { - "version": "3.2.25", - "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", - "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dependencies": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "engines": { - "node": ">=4" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "dependencies": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", - "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", - "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==" - }, - "node_modules/foreach": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", - "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", - "dev": true - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" - }, - "node_modules/fwd-stream": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/fwd-stream/-/fwd-stream-1.0.4.tgz", - "integrity": "sha1-7Sgcq+1G/uz5Ie4y3ExQs3KsfPo=", - "dev": true, - "dependencies": { - "readable-stream": "~1.0.26-4" - } - }, - "node_modules/fwd-stream/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/fwd-stream/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/fwd-stream/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/gauge": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", - "dev": true, - "dependencies": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "node_modules/gauge/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gauge/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/gaze": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", - "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", - "dev": true, - "dependencies": { - "globule": "^1.0.0" - }, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "peer": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-port": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", - "integrity": "sha1-3Xzn3hh8Bsi/NTeWrHHgmfCYDrw=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globals": { - "version": "13.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", - "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", - "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.1.1", - "ignore": "^5.1.4", - "merge2": "^1.3.0", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globule": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.3.tgz", - "integrity": "sha512-mb1aYtDbIjTu4ShMB85m3UzjX9BVKe9WCzsnfMSZk+K5GpIbBOexgg4PPCt5eHDEG5/ZQAUX2Kct02zfiPLsKg==", - "dev": true, - "dependencies": { - "glob": "~7.1.1", - "lodash": "~4.17.10", - "minimatch": "~3.0.2" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/globule/node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true - }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-ansi/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", - "dev": true - }, - "node_modules/hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/hash-base/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/hash-base/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "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/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", - "dev": true, - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/hosted-git-info": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", - "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } - }, - "node_modules/idb-wrapper": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/idb-wrapper/-/idb-wrapper-1.7.2.tgz", - "integrity": "sha512-zfNREywMuf0NzDo9mVsL0yegjsirJxHpKHvWcyRozIqQy89g0a3U+oBPOCN4cc0oCiOuYgZHimzaW/R46G1Mpg==", - "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/ignore": { - "version": "5.1.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", - "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/is": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/is/-/is-0.2.7.tgz", - "integrity": "sha1-OzSixI81mXLzUEKEkZOucmS2NWI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", - "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", - "dev": true, - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "dependencies": { - "number-is-nan": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-object": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/is-object/-/is-object-0.1.2.tgz", - "integrity": "sha1-AO+8CIFsM8/ErIJR0TLhDcZQmNc=", - "dev": true - }, - "node_modules/is-observable": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-2.1.0.tgz", - "integrity": "sha512-DailKdLb0WU+xX8K5w7VsJhapwHLZ9jjmazqCJq4X12CTgqq73TKnbRcnSLuXYPOoLQgV5IrD7ePiX/h1vnkBw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/isbuffer": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/isbuffer/-/isbuffer-0.0.0.tgz", - "integrity": "sha1-OMFG2d9Si4v5sHAcPUPPEt8/w5s=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "node_modules/jest-worker": { - "version": "26.6.2", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", - "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", - "dev": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/js-base64": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz", - "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==", - "dev": true - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "peer": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "node_modules/json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "peer": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/level-blobs": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/level-blobs/-/level-blobs-0.1.7.tgz", - "integrity": "sha1-mrm5e7mfHtv594o0M+Ie1WOGva8=", - "dev": true, - "dependencies": { - "level-peek": "1.0.6", - "once": "^1.3.0", - "readable-stream": "^1.0.26-4" - } - }, - "node_modules/level-blobs/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/level-blobs/node_modules/readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/level-blobs/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/level-filesystem": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/level-filesystem/-/level-filesystem-1.2.0.tgz", - "integrity": "sha1-oArKmRnEpN+v3KaoEI0iWq3/Y7M=", - "dev": true, - "dependencies": { - "concat-stream": "^1.4.4", - "errno": "^0.1.1", - "fwd-stream": "^1.0.4", - "level-blobs": "^0.1.7", - "level-peek": "^1.0.6", - "level-sublevel": "^5.2.0", - "octal": "^1.0.0", - "once": "^1.3.0", - "xtend": "^2.2.0" - } - }, - "node_modules/level-fix-range": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/level-fix-range/-/level-fix-range-1.0.2.tgz", - "integrity": "sha1-vxW5Fa422EcMgh6IPd95zRZCCCg=", - "dev": true - }, - "node_modules/level-hooks": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/level-hooks/-/level-hooks-4.5.0.tgz", - "integrity": "sha1-G5rmGSKTDzMF0aYfxNg8gQLA3ZM=", - "dev": true, - "dependencies": { - "string-range": "~1.2" - } - }, - "node_modules/level-js": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/level-js/-/level-js-2.2.4.tgz", - "integrity": "sha1-vAVfQYBjXUSJtWHJSG+jcOjBFpc=", - "dev": true, - "dependencies": { - "abstract-leveldown": "~0.12.0", - "idb-wrapper": "^1.5.0", - "isbuffer": "~0.0.0", - "ltgt": "^2.1.2", - "typedarray-to-buffer": "~1.0.0", - "xtend": "~2.1.2" - } - }, - "node_modules/level-js/node_modules/xtend": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", - "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", - "dev": true, - "dependencies": { - "object-keys": "~0.4.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/level-peek": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/level-peek/-/level-peek-1.0.6.tgz", - "integrity": "sha1-vsUccqgu5GTTNkNMfIdsP8vM538=", - "dev": true, - "dependencies": { - "level-fix-range": "~1.0.2" - } - }, - "node_modules/level-sublevel": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/level-sublevel/-/level-sublevel-5.2.3.tgz", - "integrity": "sha1-dEwSxy0ucr543eO5tc2E1iGRQTo=", - "dev": true, - "dependencies": { - "level-fix-range": "2.0", - "level-hooks": ">=4.4.0 <5", - "string-range": "~1.2.1", - "xtend": "~2.0.4" - } - }, - "node_modules/level-sublevel/node_modules/level-fix-range": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/level-fix-range/-/level-fix-range-2.0.0.tgz", - "integrity": "sha1-xBfWIVlEIVGhnZojZ4aPFyTC1Ug=", - "dev": true, - "dependencies": { - "clone": "~0.1.9" - } - }, - "node_modules/level-sublevel/node_modules/object-keys": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.2.0.tgz", - "integrity": "sha1-zd7AKZiwkb5CvxA1rjLknxy26mc=", - "deprecated": "Please update to the latest object-keys", - "dev": true, - "dependencies": { - "foreach": "~2.0.1", - "indexof": "~0.0.1", - "is": "~0.2.6" - } - }, - "node_modules/level-sublevel/node_modules/xtend": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.0.6.tgz", - "integrity": "sha1-XqZXptukRwacLlnFihE4ywxebO4=", - "dev": true, - "dependencies": { - "is-object": "~0.1.2", - "object-keys": "~0.2.0" - }, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/levelup": { - "version": "0.18.6", - "resolved": "https://registry.npmjs.org/levelup/-/levelup-0.18.6.tgz", - "integrity": "sha1-5qAcsIlhbI7MApHCqb0/DETj5es=", - "dev": true, - "dependencies": { - "bl": "~0.8.1", - "deferred-leveldown": "~0.2.0", - "errno": "~0.1.1", - "prr": "~0.0.0", - "readable-stream": "~1.0.26", - "semver": "~2.3.1", - "xtend": "~3.0.0" - } - }, - "node_modules/levelup/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "node_modules/levelup/node_modules/prr": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", - "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", - "dev": true - }, - "node_modules/levelup/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/levelup/node_modules/semver": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-2.3.2.tgz", - "integrity": "sha1-uYSPJdbPNjMwc+ye+IVtQvEjPlI=", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/levelup/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "node_modules/levelup/node_modules/xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", - "dev": true - }, - "node_modules/livereload": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz", - "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==", - "dev": true, - "dependencies": { - "chokidar": "^3.5.0", - "livereload-js": "^3.3.1", - "opts": ">= 1.2.0", - "ws": "^7.4.3" - }, - "bin": { - "livereload": "bin/livereload.js" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/livereload-js": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.3.2.tgz", - "integrity": "sha512-w677WnINxFkuixAoUEXOStewzLYGI76XVag+0JWMMEyjJQKs0ibWZMxkTlB96Lm3EjZ7IeOxVziBEbtxVQqQZA==", - "dev": true - }, - "node_modules/local-access": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/local-access/-/local-access-1.1.0.tgz", - "integrity": "sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=" - }, - "node_modules/lottie-web": { - "version": "5.7.14", - "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.7.14.tgz", - "integrity": "sha512-J+QEPse7Rws0XvTqRJNtcE8cszb5FWYFHubEK6bgDJtw64/AQJ40aazbWXsWGBM4sm/PgLBLgmmhDU4QpLiieg==" - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ltgt": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ltgt/-/ltgt-2.2.1.tgz", - "integrity": "sha1-81ypHEk/e3PaDgdJUwTxezH4fuU=", - "dev": true - }, - "node_modules/magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.4" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/map-obj": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", - "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/meow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", - "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", - "dev": true, - "dependencies": { - "@types/minimist": "^1.2.0", - "camelcase-keys": "^6.2.2", - "decamelize": "^1.2.0", - "decamelize-keys": "^1.1.0", - "hard-rejection": "^2.1.0", - "minimist-options": "4.1.0", - "normalize-package-data": "^3.0.0", - "read-pkg-up": "^7.0.1", - "redent": "^3.0.0", - "trim-newlines": "^3.0.0", - "type-fest": "^0.18.0", - "yargs-parser": "^20.2.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/meow/node_modules/type-fest": { - "version": "0.18.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", - "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dev": true, - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "dependencies": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - }, - "bin": { - "miller-rabin": "bin/miller-rabin" - } - }, - "node_modules/miller-rabin/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/mime": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", - "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/mime-db": { - "version": "1.50.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", - "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.33", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", - "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", - "dev": true, - "dependencies": { - "mime-db": "1.50.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "node_modules/minimist-options": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", - "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", - "dev": true, - "dependencies": { - "arrify": "^1.0.1", - "is-plain-obj": "^1.1.0", - "kind-of": "^6.0.3" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/minipass": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz", - "integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/mri": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", - "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "dev": true - }, - "node_modules/nanoevents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/nanoevents/-/nanoevents-6.0.2.tgz", - "integrity": "sha512-FRS2otuFcPPYDPYViNWQ42+1iZqbXydinkRHTHFxrF4a1CpBfmydR9zkI44WSXAXCyPrkcGtPk5CnpW6Y3lFKQ==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" - }, - "node_modules/node-gyp": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-7.1.2.tgz", - "integrity": "sha512-CbpcIo7C3eMu3dL1c3d0xw449fHIGALIJsRP4DDPHpyiW8vcriNY7ubh9TE4zEKfSxscY7PjeFnshE7h75ynjQ==", - "dev": true, - "dependencies": { - "env-paths": "^2.2.0", - "glob": "^7.1.4", - "graceful-fs": "^4.2.3", - "nopt": "^5.0.0", - "npmlog": "^4.1.2", - "request": "^2.88.2", - "rimraf": "^3.0.2", - "semver": "^7.3.2", - "tar": "^6.0.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">= 10.12.0" - } - }, - "node_modules/node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", - "peer": true - }, - "node_modules/node-sass": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-6.0.1.tgz", - "integrity": "sha512-f+Rbqt92Ful9gX0cGtdYwjTrWAaGURgaK5rZCWOgCNyGWusFYHhbqCCBoFBeat+HKETOU02AyTxNhJV0YZf2jQ==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "async-foreach": "^0.1.3", - "chalk": "^1.1.1", - "cross-spawn": "^7.0.3", - "gaze": "^1.0.0", - "get-stdin": "^4.0.1", - "glob": "^7.0.3", - "lodash": "^4.17.15", - "meow": "^9.0.0", - "nan": "^2.13.2", - "node-gyp": "^7.1.0", - "npmlog": "^4.0.0", - "request": "^2.88.0", - "sass-graph": "2.2.5", - "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" - }, - "bin": { - "node-sass": "bin/node-sass" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/node-sass/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/node-sass/node_modules/ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/node-sass/node_modules/chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "dependencies": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/node-sass/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/node-sass/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/node-sass/node_modules/supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/normalize-package-data": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", - "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^4.0.1", - "is-core-module": "^2.5.0", - "semver": "^7.3.4", - "validate-npm-package-license": "^3.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/npmlog": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", - "dev": true, - "dependencies": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "node_modules/number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", - "dev": true - }, - "node_modules/observable-fns": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/observable-fns/-/observable-fns-0.6.1.tgz", - "integrity": "sha512-9gRK4+sRWzeN6AOewNBTLXir7Zl/i3GB6Yl26gK4flxz8BXVpD3kt8amREmWNb0mxYOGDotvE5a4N+PtGGKdkg==", - "dev": true - }, - "node_modules/octal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/octal/-/octal-1.0.0.tgz", - "integrity": "sha1-Y+cWKmjvvrniE1iNWOmJ0eXEUws=", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/opts": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz", - "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==", - "dev": true - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "dependencies": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "dev": true, - "dependencies": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "peer": true - }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.4.1.tgz", - "integrity": "sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/process-es6": { - "version": "0.11.6", - "resolved": "https://registry.npmjs.org/process-es6/-/process-es6-0.11.6.tgz", - "integrity": "sha1-xrs4n5qVH4K9TrFpYAEFvS/5x3g=", - "dev": true - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", - "dev": true - }, - "node_modules/public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "dependencies": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "node_modules/public-encrypt/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", - "dev": true - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "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/quick-lru": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", - "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/random-number-csprng": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/random-number-csprng/-/random-number-csprng-1.0.2.tgz", - "integrity": "sha1-/NEg5i3/wsB2dMfD/gHhayX3OiY=", - "dev": true, - "dependencies": { - "bluebird": "^3.3.3", - "create-error": "^0.3.1" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "dependencies": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "node_modules/read-pkg/node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/read-pkg/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/redent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", - "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", - "dev": true, - "dependencies": { - "indent-string": "^4.0.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "node_modules/require-relative": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", - "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", - "dev": true - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dev": true, - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "dev": true, - "dependencies": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "node_modules/rollup": { - "version": "2.58.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.58.3.tgz", - "integrity": "sha512-ei27MSw1KhRur4p87Q0/Va2NAYqMXOX++FNEumMBcdreIRLURKy+cE2wcDJKBn0nfmhP2ZGrJkP1XPO+G8FJQw==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=10.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup-plugin-css-only": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-css-only/-/rollup-plugin-css-only-3.1.0.tgz", - "integrity": "sha512-TYMOE5uoD76vpj+RTkQLzC9cQtbnJNktHPB507FzRWBVaofg7KhIqq1kGbcVOadARSozWF883Ho9KpSPKH8gqA==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "4" - }, - "engines": { - "node": ">=10.12.0" - }, - "peerDependencies": { - "rollup": "1 || 2" - } - }, - "node_modules/rollup-plugin-css-only/node_modules/@rollup/pluginutils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.1.tgz", - "integrity": "sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==", - "dev": true, - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/rollup-plugin-livereload": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.5.tgz", - "integrity": "sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==", - "dev": true, - "dependencies": { - "livereload": "^0.9.1" - }, - "engines": { - "node": ">=8.3" - } - }, - "node_modules/rollup-plugin-node-builtins": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-builtins/-/rollup-plugin-node-builtins-2.1.2.tgz", - "integrity": "sha1-JKH+1KQyV7a2Q3HYq8bOGrFFl+k=", - "dev": true, - "dependencies": { - "browserify-fs": "^1.0.0", - "buffer-es6": "^4.9.2", - "crypto-browserify": "^3.11.0", - "process-es6": "^0.11.2" - } - }, - "node_modules/rollup-plugin-node-globals": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-globals/-/rollup-plugin-node-globals-1.4.0.tgz", - "integrity": "sha512-xRkB+W/m1KLIzPUmG0ofvR+CPNcvuCuNdjVBVS7ALKSxr3EDhnzNceGkGi1m8MToSli13AzKFYH4ie9w3I5L3g==", - "dev": true, - "dependencies": { - "acorn": "^5.7.3", - "buffer-es6": "^4.9.3", - "estree-walker": "^0.5.2", - "magic-string": "^0.22.5", - "process-es6": "^0.11.6", - "rollup-pluginutils": "^2.3.1" - } - }, - "node_modules/rollup-plugin-node-globals/node_modules/acorn": { - "version": "5.7.4", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", - "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/rollup-plugin-node-globals/node_modules/estree-walker": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.2.tgz", - "integrity": "sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig==", - "dev": true - }, - "node_modules/rollup-plugin-node-globals/node_modules/magic-string": { - "version": "0.22.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", - "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", - "dev": true, - "dependencies": { - "vlq": "^0.2.2" - } - }, - "node_modules/rollup-plugin-svelte": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.1.0.tgz", - "integrity": "sha512-vopCUq3G+25sKjwF5VilIbiY6KCuMNHP1PFvx2Vr3REBNMDllKHFZN2B9jwwC+MqNc3UPKkjXnceLPEjTjXGXg==", - "dev": true, - "dependencies": { - "require-relative": "^0.8.7", - "rollup-pluginutils": "^2.8.2" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "rollup": ">=2.0.0", - "svelte": ">=3.5.0" - } - }, - "node_modules/rollup-plugin-terser": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", - "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "jest-worker": "^26.2.1", - "serialize-javascript": "^4.0.0", - "terser": "^5.0.0" - }, - "peerDependencies": { - "rollup": "^2.0.0" - } - }, - "node_modules/rollup-plugin-typescript2": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.30.0.tgz", - "integrity": "sha512-NUFszIQyhgDdhRS9ya/VEmsnpTe+GERDMmFo0Y+kf8ds51Xy57nPNGglJY+W6x1vcouA7Au7nsTgsLFj2I0PxQ==", - "dev": true, - "dependencies": { - "@rollup/pluginutils": "^4.1.0", - "find-cache-dir": "^3.3.1", - "fs-extra": "8.1.0", - "resolve": "1.20.0", - "tslib": "2.1.0" - }, - "peerDependencies": { - "rollup": ">=1.26.3", - "typescript": ">=2.4.0" - } - }, - "node_modules/rollup-plugin-typescript2/node_modules/@rollup/pluginutils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.1.tgz", - "integrity": "sha512-clDjivHqWGXi7u+0d2r2sBi4Ie6VLEAzWMIkvJLnDmxoOhBYOTfzGbOQBA32THHm11/LiJbd01tJUpJsbshSWQ==", - "dev": true, - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/rollup-plugin-typescript2/node_modules/tslib": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", - "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", - "dev": true - }, - "node_modules/rollup-plugin-web-worker-loader": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-web-worker-loader/-/rollup-plugin-web-worker-loader-1.6.1.tgz", - "integrity": "sha512-4QywQSz1NXFHKdyiou16mH3ijpcfLtLGOrAqvAqu1Gx+P8+zj+3gwC2BSL/VW1d+LW4nIHC8F7d7OXhs9UdR2A==", - "dev": true, - "peerDependencies": { - "rollup": "^1.9.2 || ^2.0.0" - } - }, - "node_modules/rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "dependencies": { - "estree-walker": "^0.6.1" - } - }, - "node_modules/rollup-pluginutils/node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "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" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/sade": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/sade/-/sade-1.7.4.tgz", - "integrity": "sha512-y5yauMD93rX840MwUJr7C1ysLFBgMspsdTo4UVrDg3fXDvtwOyIqykhVAAm6fk/3au77773itJStObgK+LKaiA==", - "dev": true, - "dependencies": { - "mri": "^1.1.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/sander": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/sander/-/sander-0.5.1.tgz", - "integrity": "sha1-dB4kXiMfB8r7b98PEzrfohalAq0=", - "dev": true, - "dependencies": { - "es6-promise": "^3.1.2", - "graceful-fs": "^4.1.3", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.2" - } - }, - "node_modules/sander/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/sass-graph": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz", - "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==", - "dev": true, - "dependencies": { - "glob": "^7.0.0", - "lodash": "^4.0.0", - "scss-tokenizer": "^0.2.3", - "yargs": "^13.3.2" - }, - "bin": { - "sassgraph": "bin/sassgraph" - } - }, - "node_modules/scss-tokenizer": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", - "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", - "dev": true, - "dependencies": { - "js-base64": "^2.1.8", - "source-map": "^0.4.2" - } - }, - "node_modules/semiver": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz", - "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", - "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - }, - "bin": { - "sha.js": "bin.js" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.5.tgz", - "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", - "dev": true - }, - "node_modules/sirv": { - "version": "1.0.18", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-1.0.18.tgz", - "integrity": "sha512-f2AOPogZmXgJ9Ma2M22ZEhc1dNtRIzcEkiflMFeVTRq+OViOZMvH1IPMVOwrKaxpSaHioBJiDR0SluRqGa7atA==", - "dev": true, - "dependencies": { - "@polka/url": "^1.0.0-next.20", - "mime": "^2.3.1", - "totalist": "^1.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/sirv-cli": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/sirv-cli/-/sirv-cli-1.0.14.tgz", - "integrity": "sha512-yyUTNr984ANKDloqepkYbBSqvx3buwYg2sQKPWjSU+IBia5loaoka2If8N9CMwt8AfP179cdEl7kYJ//iWJHjQ==", - "dev": true, - "dependencies": { - "console-clear": "^1.1.0", - "get-port": "^3.2.0", - "kleur": "^3.0.0", - "local-access": "^1.0.1", - "sade": "^1.6.0", - "semiver": "^1.0.0", - "sirv": "^1.0.13", - "tinydate": "^1.0.0" - }, - "bin": { - "sirv": "bin.js" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/sorcery": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.10.0.tgz", - "integrity": "sha1-iukK19fLBfxZ8asMY3hF1cFaUrc=", - "dev": true, - "dependencies": { - "buffer-crc32": "^0.2.5", - "minimist": "^1.2.0", - "sander": "^0.5.0", - "sourcemap-codec": "^1.3.0" - }, - "bin": { - "sorcery": "bin/index.js" - } - }, - "node_modules/source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "dev": true, - "dependencies": { - "amdefine": ">=0.0.4" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/source-map-support/node_modules/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", - "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", - "dev": true - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "node_modules/sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sshpk/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "node_modules/stdout-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz", - "integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==", - "dev": true, - "dependencies": { - "readable-stream": "^2.0.1" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-range": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/string-range/-/string-range-1.2.2.tgz", - "integrity": "sha1-qJPtNH5yKZvIO++78qaSqNI51d0=", - "dev": true - }, - "node_modules/string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "dependencies": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "dependencies": { - "ansi-regex": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/svelte": { - "version": "3.44.0", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.44.0.tgz", - "integrity": "sha512-zWACSJBSncGiDvFfYOMFGNV5zDLOlyhftmO5yOZ0lEtQMptpElaRtl39MWz1+lYCpwUq4F3Q2lTzI9TrTL+eMA==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/svelte-check": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-2.2.7.tgz", - "integrity": "sha512-lH8ArmwVC+D314cToZkXBBfj7NlpvgQGP7nXCAMnNHo6hTEcbKcf/cAZgzbnAOTftjIJrmLHp+EDW887VJFSOQ==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0", - "chokidar": "^3.4.1", - "fast-glob": "^3.2.7", - "import-fresh": "^3.2.1", - "minimist": "^1.2.5", - "sade": "^1.7.4", - "source-map": "^0.7.3", - "svelte-preprocess": "^4.0.0", - "typescript": "*" - }, - "bin": { - "svelte-check": "bin/svelte-check" - }, - "peerDependencies": { - "svelte": "^3.24.0" - } - }, - "node_modules/svelte-check/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/svelte-preprocess": { - "version": "4.9.8", - "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.9.8.tgz", - "integrity": "sha512-EQS/oRZzMtYdAprppZxY3HcysKh11w54MgA63ybtL+TAZ4hVqYOnhw41JVJjWN9dhPnNjjLzvbZ2tMhTsla1Og==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@types/pug": "^2.0.4", - "@types/sass": "^1.16.0", - "detect-indent": "^6.0.0", - "magic-string": "^0.25.7", - "sorcery": "^0.10.0", - "strip-indent": "^3.0.0" - }, - "engines": { - "node": ">= 9.11.2" - }, - "peerDependencies": { - "@babel/core": "^7.10.2", - "coffeescript": "^2.5.1", - "less": "^3.11.3", - "postcss": "^7 || ^8", - "postcss-load-config": "^2.1.0 || ^3.0.0", - "pug": "^3.0.0", - "sass": "^1.26.8", - "stylus": "^0.54.7", - "sugarss": "^2.0.0", - "svelte": "^3.23.0", - "typescript": "^3.9.5 || ^4.0.0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - }, - "coffeescript": { - "optional": true - }, - "less": { - "optional": true - }, - "node-sass": { - "optional": true - }, - "postcss": { - "optional": true - }, - "postcss-load-config": { - "optional": true - }, - "pug": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "typescript": { - "optional": true - } - } - }, - "node_modules/svelte-router-spa": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/svelte-router-spa/-/svelte-router-spa-6.0.3.tgz", - "integrity": "sha512-aHgyUVVI/WjipQNmKcXpX0hFZtkW5Y6hwH5aXLr2P/aRQ/qlX8ZbKQJUwKjOD59p7tt/c+wqokiIt68N7aNuKQ==", - "dependencies": { - "url-params-parser": "^1.0.3" - }, - "peerDependencies": { - "svelte": "^3.36.0" - } - }, - "node_modules/table": { - "version": "6.7.2", - "resolved": "https://registry.npmjs.org/table/-/table-6.7.2.tgz", - "integrity": "sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g==", - "dependencies": { - "ajv": "^8.0.1", - "lodash.clonedeep": "^4.5.0", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.6.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", - "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/table/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/table/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/table/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar": { - "version": "6.1.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", - "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^3.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/tar/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.9.0.tgz", - "integrity": "sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==", - "dev": true, - "dependencies": { - "commander": "^2.20.0", - "source-map": "~0.7.2", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" - }, - "node_modules/threads": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/threads/-/threads-1.7.0.tgz", - "integrity": "sha512-Mx5NBSHX3sQYR6iI9VYbgHKBLisyB+xROCBGjjWm1O9wb9vfLxdaGtmT/KCjUqMsSNW6nERzCW3T6H43LqjDZQ==", - "dev": true, - "dependencies": { - "callsites": "^3.1.0", - "debug": "^4.2.0", - "is-observable": "^2.1.0", - "observable-fns": "^0.6.1" - }, - "funding": { - "url": "https://github.com/andywer/threads.js?sponsor=1" - }, - "optionalDependencies": { - "tiny-worker": ">= 2" - } - }, - "node_modules/tiny-worker": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tiny-worker/-/tiny-worker-2.3.0.tgz", - "integrity": "sha512-pJ70wq5EAqTAEl9IkGzA+fN0836rycEuz2Cn6yeZ6FRzlVS5IDOkFHpIoEsksPRQV34GDqXm65+OlnZqUSyK2g==", - "dev": true, - "optional": true, - "dependencies": { - "esm": "^3.2.25" - } - }, - "node_modules/tinydate": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz", - "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "peer": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/totalist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-1.1.0.tgz", - "integrity": "sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/trim-newlines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", - "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "dev": true, - "dependencies": { - "glob": "^7.1.2" - } - }, - "node_modules/tslib": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", - "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "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/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/typedarray-to-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-1.0.4.tgz", - "integrity": "sha1-m7i6DoQfs/TPH+fCRenz+opf6Zw=", - "dev": true - }, - "node_modules/typescript": { - "version": "4.4.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", - "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/url-params-parser": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/url-params-parser/-/url-params-parser-1.0.4.tgz", - "integrity": "sha512-0m6BqGpY2OetTZ3UPTLKkbTfUHigsX2YhrzORT9iYiyUJ/SP2WJ3cggg2YWtvMs36GPwK9Q44ffddyarniu2Tg==" - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/verror/node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "node_modules/vlq": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", - "dev": true - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/ws": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", - "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", - "dev": true, - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xtend": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.2.0.tgz", - "integrity": "sha1-7vax8ZjByN6vrYsXZaBNrUoBxak=", - "dev": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/yargs/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - }, "dependencies": { "@babel/code-frame": { "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", - "peer": true - }, - "@babel/core": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.8.tgz", - "integrity": "sha512-3UG9dsxvYBMYwRv+gS41WKHno4K60/9GPy1CJaH6xy3Elq8CTtvtjT5R5jmNhXfCYLX2mTw+7/aq5ak/gOE0og==", - "peer": true, - "requires": { - "@babel/code-frame": "^7.15.8", - "@babel/generator": "^7.15.8", - "@babel/helper-compilation-targets": "^7.15.4", - "@babel/helper-module-transforms": "^7.15.8", - "@babel/helpers": "^7.15.4", - "@babel/parser": "^7.15.8", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", - "peer": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "peer": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "peer": true - } - } - }, - "@babel/eslint-parser": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.15.8.tgz", - "integrity": "sha512-fYP7QFngCvgxjUuw8O057SVH5jCXsbFFOoE77CFDcvzwBVgTOkMD/L4mIC5Ud1xf8chK/no2fRbSSn1wvNmKuQ==", - "requires": { - "eslint-scope": "^5.1.1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "@babel/generator": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.8.tgz", - "integrity": "sha512-ECmAKstXbp1cvpTTZciZCgfOt6iN64lR0d+euv3UZisU5awfRawOvg07Utn/qBGuH4bRIEZKrA/4LzZyXhZr8g==", - "peer": true, - "requires": { - "@babel/types": "^7.15.6", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "peer": true - } + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" } }, - "@babel/helper-compilation-targets": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.4.tgz", - "integrity": "sha512-rMWPCirulnPSe4d+gwdWXLfAXTTBj8M3guAf5xFQJ0nvFY7tfNAFnWdqaHegHlgDZOCT4qvhF3BYlSJag8yhqQ==", - "peer": true, + "@babel/eslint-parser": { + "version": "7.15.8", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.15.8.tgz", + "integrity": "sha512-fYP7QFngCvgxjUuw8O057SVH5jCXsbFFOoE77CFDcvzwBVgTOkMD/L4mIC5Ud1xf8chK/no2fRbSSn1wvNmKuQ==", "requires": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", + "eslint-scope": "^5.1.1", + "eslint-visitor-keys": "^2.1.0", "semver": "^6.3.0" }, "dependencies": { "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "peer": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, - "@babel/helper-function-name": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.15.4.tgz", - "integrity": "sha512-Z91cOMM4DseLIGOnog+Z8OI6YseR9bua+HpvLAQ2XayUGU+neTtX+97caALaLdyu53I/fjhbeCnWnRH1O3jFOw==", - "peer": true, - "requires": { - "@babel/helper-get-function-arity": "^7.15.4", - "@babel/template": "^7.15.4", - "@babel/types": "^7.15.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.15.4.tgz", - "integrity": "sha512-1/AlxSF92CmGZzHnC515hm4SirTxtpDnLEJ0UyEMgTMZN+6bxXKg04dKhiRx5Enel+SUA1G1t5Ed/yQia0efrA==", - "peer": true, - "requires": { - "@babel/types": "^7.15.4" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.15.4.tgz", - "integrity": "sha512-VTy085egb3jUGVK9ycIxQiPbquesq0HUQ+tPO0uv5mPEBZipk+5FkRKiWq5apuyTE9FUrjENB0rCf8y+n+UuhA==", - "peer": true, - "requires": { - "@babel/types": "^7.15.4" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.4.tgz", - "integrity": "sha512-cokOMkxC/BTyNP1AlY25HuBWM32iCEsLPI4BHDpJCHHm1FU2E7dKWWIXJgQgSFiu4lp8q3bL1BIKwqkSUviqtA==", - "peer": true, - "requires": { - "@babel/types": "^7.15.4" - } - }, - "@babel/helper-module-imports": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.15.4.tgz", - "integrity": "sha512-jeAHZbzUwdW/xHgHQ3QmWR4Jg6j15q4w/gCfwZvtqOxoo5DKtLHk8Bsf4c5RZRC7NmLEs+ohkdq8jFefuvIxAA==", - "peer": true, - "requires": { - "@babel/types": "^7.15.4" - } - }, - "@babel/helper-module-transforms": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.8.tgz", - "integrity": "sha512-DfAfA6PfpG8t4S6npwzLvTUpp0sS7JrcuaMiy1Y5645laRJIp/LiLGIBbQKaXSInK8tiGNI7FL7L8UvB8gdUZg==", - "peer": true, - "requires": { - "@babel/helper-module-imports": "^7.15.4", - "@babel/helper-replace-supers": "^7.15.4", - "@babel/helper-simple-access": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/helper-validator-identifier": "^7.15.7", - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.6" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.15.4.tgz", - "integrity": "sha512-E/z9rfbAOt1vDW1DR7k4SzhzotVV5+qMciWV6LaG1g4jeFrkDlJedjtV4h0i4Q/ITnUu+Pk08M7fczsB9GXBDw==", - "peer": true, - "requires": { - "@babel/types": "^7.15.4" - } - }, - "@babel/helper-replace-supers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.4.tgz", - "integrity": "sha512-/ztT6khaXF37MS47fufrKvIsiQkx1LBRvSJNzRqmbyeZnTwU9qBxXYLaaT/6KaxfKhjs2Wy8kG8ZdsFUuWBjzw==", - "peer": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.15.4", - "@babel/helper-optimise-call-expression": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" - } - }, - "@babel/helper-simple-access": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.15.4.tgz", - "integrity": "sha512-UzazrDoIVOZZcTeHHEPYrr1MvTR/K+wgLg6MY6e1CJyaRhbibftF6fR2KU2sFRtI/nERUZR9fBd6aKgBlIBaPg==", - "peer": true, - "requires": { - "@babel/types": "^7.15.4" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.15.4.tgz", - "integrity": "sha512-HsFqhLDZ08DxCpBdEVtKmywj6PQbwnF6HHybur0MAnkAKnlS6uHkwnmRIkElB2Owpfb4xL4NwDmDLFubueDXsw==", - "peer": true, - "requires": { - "@babel/types": "^7.15.4" - } - }, "@babel/helper-validator-identifier": { "version": "7.15.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", - "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==" - }, - "@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", - "peer": true - }, - "@babel/helpers": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.15.4.tgz", - "integrity": "sha512-V45u6dqEJ3w2rlryYYXf6i9rQ5YMNu4FLS6ngs8ikblhu2VdR1AqAd6aJjBzmf2Qzh6KOLqKHxEN9+TFbAkAVQ==", - "peer": true, - "requires": { - "@babel/template": "^7.15.4", - "@babel/traverse": "^7.15.4", - "@babel/types": "^7.15.4" - } + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "dev": true }, "@babel/highlight": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.14.5", "chalk": "^2.0.0", @@ -6507,6 +51,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, "requires": { "color-convert": "^1.9.0" } @@ -6515,6 +60,7 @@ "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -6525,6 +71,7 @@ "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, "requires": { "color-name": "1.1.3" } @@ -6532,104 +79,37 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "requires": { "has-flag": "^3.0.0" } } } }, - "@babel/parser": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.8.tgz", - "integrity": "sha512-BRYa3wcQnjS/nqI8Ac94pYYpJfojHVvVXJ97+IDCImX4Jc8W8Xv1+47enbruk+q1etOpsQNwnfFcNGw+gtPGxA==", - "peer": true - }, - "@babel/template": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", - "integrity": "sha512-UgBAfEa1oGuYgDIPM2G+aHa4Nlo9Lh6mGD2bDBGMTbYnc38vulXPuC1MGjYILIEmlwl6Rd+BPR9ee3gm20CBtg==", - "peer": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", - "peer": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - } - } - }, - "@babel/traverse": { - "version": "7.15.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.4.tgz", - "integrity": "sha512-W6lQD8l4rUbQR/vYgSuCAE75ADyyQvOpFVsvPPdkhf6lATXAsQIG9YdtOcu8BB1dZ0LKu+Zo3c1wEcbKeuhdlA==", - "peer": true, - "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.4", - "@babel/helper-function-name": "^7.15.4", - "@babel/helper-hoist-variables": "^7.15.4", - "@babel/helper-split-export-declaration": "^7.15.4", - "@babel/parser": "^7.15.4", - "@babel/types": "^7.15.4", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.15.8", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.15.8.tgz", - "integrity": "sha512-2IAnmn8zbvC/jKYhq5Ki9I+DwjlrtMPUCH/CpHvqI4dNnlwHwsxoIhlc8WcYY5LSYknXQtAlFYuHfqAFCvQ4Wg==", - "peer": true, - "requires": { - "@babel/highlight": "^7.14.5" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "peer": true - } - } - }, - "@babel/types": { - "version": "7.15.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.6.tgz", - "integrity": "sha512-BPU+7QhqNjmWyDO0/vitH/CuhpV8ZmK1wpKva8nuyNF5MJfuRNWMc+hc14+u9xT93kvykMdncrJT19h74uB1Ig==", - "peer": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - } - }, "@eslint/eslintrc": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -6645,7 +125,8 @@ "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true } } }, @@ -6653,6 +134,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.0", "debug": "^4.1.1", @@ -6662,7 +144,8 @@ "@humanwhocodes/object-schema": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==" + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true }, "@nodelib/fs.scandir": { "version": "2.1.5", @@ -6939,18 +422,20 @@ "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true }, "acorn-jsx": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "requires": {} + "dev": true }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -6967,17 +452,20 @@ "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -7012,6 +500,7 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -7066,7 +555,8 @@ "astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true }, "async-foreach": { "version": "0.1.3", @@ -7095,7 +585,8 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "base64-js": { "version": "1.5.1", @@ -7183,6 +674,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -7297,19 +789,6 @@ } } }, - "browserslist": { - "version": "4.17.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.5.tgz", - "integrity": "sha512-I3ekeB92mmpctWBoLXe0d5wPS2cBuRvvW0JyyJHMrk9/HmP2ZjrTboNAZ8iuGqaEIlKguljbQY32OkOJIRrgoA==", - "peer": true, - "requires": { - "caniuse-lite": "^1.0.30001271", - "electron-to-chromium": "^1.3.878", - "escalade": "^3.1.1", - "node-releases": "^2.0.1", - "picocolors": "^1.0.0" - } - }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -7343,7 +822,8 @@ "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true }, "camelcase": { "version": "5.3.1", @@ -7362,12 +842,6 @@ "quick-lru": "^4.0.1" } }, - "caniuse-lite": { - "version": "1.0.30001271", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001271.tgz", - "integrity": "sha512-BBruZFWmt3HFdVPS8kceTBIguKxu4f99n5JNp06OlPD/luoAMIaIK5ieV5YjnBLH3Nysai9sxj9rpJj4ZisXOA==", - "peer": true - }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -7378,6 +852,7 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -7476,6 +951,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { "color-name": "~1.1.4" } @@ -7483,7 +959,8 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "combined-stream": { "version": "1.0.8", @@ -7509,7 +986,8 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", @@ -7535,15 +1013,6 @@ "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true }, - "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "peer": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, "core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -7605,6 +1074,7 @@ "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -7643,6 +1113,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, "requires": { "ms": "2.1.2" } @@ -7674,7 +1145,8 @@ "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true }, "deepmerge": { "version": "4.2.2", @@ -7751,6 +1223,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, "requires": { "esutils": "^2.0.2" } @@ -7765,12 +1238,6 @@ "safer-buffer": "^2.1.0" } }, - "electron-to-chromium": { - "version": "1.3.880", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.880.tgz", - "integrity": "sha512-iwIP/6WoeSimzUKJIQtjtpVDsK8Ir8qQCMXsUBwg+rxJR2Uh3wTNSbxoYRfs+3UWx/9MAnPIxVZCyWkm8MT0uw==", - "peer": true - }, "elliptic": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", @@ -7804,6 +1271,7 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, "requires": { "ansi-colors": "^4.1.1" } @@ -7838,21 +1306,17 @@ "integrity": "sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=", "dev": true }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "peer": true - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true }, "eslint": { "version": "7.32.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, "requires": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.3", @@ -7900,6 +1364,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" }, @@ -7907,14 +1372,16 @@ "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true } } }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true } } }, @@ -7931,8 +1398,7 @@ "version": "3.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-svelte3/-/eslint-plugin-svelte3-3.2.1.tgz", "integrity": "sha512-YoBR9mLoKCjGghJ/gvpnFZKaMEu/VRcuxpSRS8KuozuEo7CdBH7bmBHa6FmMm0i4kJnOyx+PVsaptz96K6H/4Q==", - "dev": true, - "requires": {} + "dev": true }, "eslint-scope": { "version": "5.1.1", @@ -7968,6 +1434,7 @@ "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, "requires": { "acorn": "^7.4.0", "acorn-jsx": "^5.3.1", @@ -7977,19 +1444,22 @@ "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true } } }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true }, "esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, "requires": { "estraverse": "^5.1.0" }, @@ -7997,7 +1467,8 @@ "estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true } } }, @@ -8030,7 +1501,8 @@ "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true }, "evp_bytestokey": { "version": "1.0.3", @@ -8057,7 +1529,8 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true }, "fast-glob": { "version": "3.2.7", @@ -8075,12 +1548,14 @@ "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true }, "fastq": { "version": "1.13.0", @@ -8095,6 +1570,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, "requires": { "flat-cache": "^3.0.4" } @@ -8133,6 +1609,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, "requires": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -8141,7 +1618,8 @@ "flatted": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", - "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==" + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", + "dev": true }, "foreach": { "version": "2.0.5", @@ -8189,7 +1667,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "fsevents": { "version": "2.3.2", @@ -8207,7 +1686,8 @@ "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true }, "fwd-stream": { "version": "1.0.4", @@ -8286,12 +1766,6 @@ "globule": "^1.0.0" } }, - "gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "peer": true - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -8323,6 +1797,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -8336,6 +1811,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -8344,6 +1820,7 @@ "version": "13.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.12.0.tgz", "integrity": "sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==", + "dev": true, "requires": { "type-fest": "^0.20.2" } @@ -8446,7 +1923,8 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true }, "has-unicode": { "version": "2.0.1", @@ -8547,6 +2025,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -8555,7 +2034,8 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true }, "indent-string": { "version": "4.0.0", @@ -8573,6 +2053,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -8581,7 +2062,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "is": { "version": "0.2.7", @@ -8616,7 +2098,8 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true }, "is-fullwidth-code-point": { "version": "1.0.0", @@ -8631,6 +2114,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -8695,7 +2179,8 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true }, "isstream": { "version": "0.1.2", @@ -8723,12 +2208,14 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true }, "js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -8740,12 +2227,6 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "peer": true - }, "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", @@ -8761,12 +2242,14 @@ "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true }, "json-stringify-safe": { "version": "5.0.1", @@ -8774,15 +2257,6 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "peer": true, - "requires": { - "minimist": "^1.2.5" - } - }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", @@ -9026,6 +2500,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "requires": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -9079,17 +2554,20 @@ "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true }, "lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=" + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true }, "lottie-web": { "version": "5.7.14", @@ -9100,6 +2578,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, "requires": { "yallist": "^4.0.0" } @@ -9264,6 +2743,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -9271,7 +2751,8 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true }, "minimist-options": { "version": "4.1.0", @@ -9321,7 +2802,8 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, "nan": { "version": "2.15.0", @@ -9338,7 +2820,8 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true }, "node-gyp": { "version": "7.1.2", @@ -9358,12 +2841,6 @@ "which": "^2.0.2" } }, - "node-releases": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", - "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", - "peer": true - }, "node-sass": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-6.0.1.tgz", @@ -9514,6 +2991,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -9522,6 +3000,7 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, "requires": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -9565,6 +3044,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, "requires": { "callsites": "^3.0.0" } @@ -9603,12 +3083,14 @@ "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true }, "path-parse": { "version": "1.0.7", @@ -9641,12 +3123,6 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "peer": true - }, "picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", @@ -9665,7 +3141,8 @@ "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true }, "prettier": { "version": "2.4.1", @@ -9688,7 +3165,8 @@ "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true }, "prr": { "version": "1.0.1", @@ -9727,7 +3205,8 @@ "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true }, "qs": { "version": "6.5.2", @@ -9876,7 +3355,8 @@ "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==" + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true }, "request": { "version": "2.88.2", @@ -9923,7 +3403,8 @@ "require-from-string": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true }, "require-main-filename": { "version": "2.0.0", @@ -9950,7 +3431,8 @@ "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true }, "ret": { "version": "0.1.15", @@ -9968,6 +3450,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, "requires": { "glob": "^7.1.3" } @@ -10127,8 +3610,7 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/rollup-plugin-web-worker-loader/-/rollup-plugin-web-worker-loader-1.6.1.tgz", "integrity": "sha512-4QywQSz1NXFHKdyiou16mH3ijpcfLtLGOrAqvAqu1Gx+P8+zj+3gwC2BSL/VW1d+LW4nIHC8F7d7OXhs9UdR2A==", - "dev": true, - "requires": {} + "dev": true }, "rollup-pluginutils": { "version": "2.8.2", @@ -10168,7 +3650,8 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "safe-regex": { "version": "1.1.0", @@ -10240,6 +3723,7 @@ "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, "requires": { "lru-cache": "^6.0.0" } @@ -10273,6 +3757,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -10280,7 +3765,8 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true }, "signal-exit": { "version": "3.0.5", @@ -10325,6 +3811,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, "requires": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -10334,7 +3821,8 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true } } }, @@ -10418,7 +3906,8 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true }, "sshpk": { "version": "1.16.1", @@ -10454,15 +3943,6 @@ "readable-stream": "^2.0.1" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, "string-range": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/string-range/-/string-range-1.2.2.tgz", @@ -10497,10 +3977,20 @@ } } }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, "strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -10517,12 +4007,14 @@ "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -10530,7 +4022,8 @@ "svelte": { "version": "3.44.0", "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.44.0.tgz", - "integrity": "sha512-zWACSJBSncGiDvFfYOMFGNV5zDLOlyhftmO5yOZ0lEtQMptpElaRtl39MWz1+lYCpwUq4F3Q2lTzI9TrTL+eMA==" + "integrity": "sha512-zWACSJBSncGiDvFfYOMFGNV5zDLOlyhftmO5yOZ0lEtQMptpElaRtl39MWz1+lYCpwUq4F3Q2lTzI9TrTL+eMA==", + "dev": true }, "svelte-check": { "version": "2.2.7", @@ -10583,6 +4076,7 @@ "version": "6.7.2", "resolved": "https://registry.npmjs.org/table/-/table-6.7.2.tgz", "integrity": "sha512-UFZK67uvyNivLeQbVtkiUs8Uuuxv24aSL4/Vil2PJVtMgU8Lx0CYkP12uCGa3kjyQzOSgV1+z9Wkb82fCGsO0g==", + "dev": true, "requires": { "ajv": "^8.0.1", "lodash.clonedeep": "^4.5.0", @@ -10596,6 +4090,7 @@ "version": "8.6.3", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", + "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -10606,22 +4101,26 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -10674,7 +4173,8 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true }, "threads": { "version": "1.7.0", @@ -10705,12 +4205,6 @@ "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==", "dev": true }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "peer": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -10793,6 +4287,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "requires": { "prelude-ls": "^1.2.1" } @@ -10800,7 +4295,8 @@ "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true }, "typedarray": { "version": "0.0.6", @@ -10830,6 +4326,7 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "requires": { "punycode": "^2.1.0" } @@ -10854,7 +4351,8 @@ "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true }, "validate-npm-package-license": { "version": "3.0.4", @@ -10895,6 +4393,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "requires": { "isexe": "^2.0.0" } @@ -10917,7 +4416,8 @@ "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true }, "wrap-ansi": { "version": "5.1.0", @@ -10991,14 +4491,14 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "ws": { "version": "7.5.5", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", - "dev": true, - "requires": {} + "dev": true }, "xtend": { "version": "2.2.0", @@ -11015,7 +4515,8 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "yargs": { "version": "13.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 f4c77a6991..8c9e21baf0 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,40 +62,40 @@ export class FairRouletteService { private handleVmMessage(message: string[]): void { const messageHandlers: MessageHandlers = { - 'fairroulette.bet.placed': (index) => { + 'fairroulette.bet': (index) => { const bet: Bet = { - better: message[index + 1], - amount: Number(message[index + 2]), - betNumber: Number(message[index + 3]), + better: message[index + 2], + amount: Number(message[index + 3]), + betNumber: Number(message[index + 4]), }; this.emitter.emit('betPlaced', bet); }, - 'fairroulette.round.state': (index) => { - if (message[index + 1] == '1') { - this.emitter.emit('roundStarted', message[index + 2]); - } else { - this.emitter.emit('roundStopped'); - } + 'fairroulette.payout': (index) => { + const bet: Bet = { + better: message[index + 2], + amount: Number(message[index + 3]), + betNumber: undefined, + }; + + this.emitter.emit('payout', bet); }, - 'fairroulette.round.number': (index) => { - this.emitter.emit('roundNumber', message[index + 1] || 0); + 'fairroulette.round': (index) => { + this.emitter.emit('roundNumber', message[index + 2] || 0); }, - 'fairroulette.round.winning_number': (index) => { - this.emitter.emit('winningNumber', message[index + 1] || 0); + 'fairroulette.start': (index) => { + this.emitter.emit('roundStarted', message[index + 1] || 0); }, - 'fairroulette.payout': (index) => { - const bet: Bet = { - better: message[index + 1], - amount: Number(message[index + 2]), - betNumber: undefined, - }; + 'fairroulette.stop': (index) => { + this.emitter.emit('roundStopped'); + }, - this.emitter.emit('payout', bet); + 'fairroulette.winner': (index) => { + this.emitter.emit('winningNumber', message[index + 2] || 0); }, }; @@ -108,7 +108,7 @@ export class FairRouletteService { } private handleIncomingMessage(message: MessageEvent): void { - const msg = message.data.toString().split(' '); + const msg = message.data.toString().split('|'); if (msg.length == 0) { return; 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 c05eeef18a..cd9e674287 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 @@ -71,6 +71,7 @@ export class OffLedger { 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); 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 f4fac899aa..968bbaac3b 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 @@ -42,6 +42,7 @@ export class OnLedger { 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); diff --git a/contracts/wasm/fairroulette/go/fairroulette/consts.go b/contracts/wasm/fairroulette/go/fairroulette/consts.go index c1909a2672..69bdc218e0 100644 --- a/contracts/wasm/fairroulette/go/fairroulette/consts.go +++ b/contracts/wasm/fairroulette/go/fairroulette/consts.go @@ -10,29 +10,30 @@ package fairroulette import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" const ( - ScName = "fairroulette" - HScName = wasmlib.ScHname(0xdf79d138) + ScName = "fairroulette" + ScDescription = "" + HScName = wasmlib.ScHname(0xdf79d138) ) const ( - ParamNumber = wasmlib.Key("number") - ParamPlayPeriod = wasmlib.Key("playPeriod") + ParamNumber = "number" + ParamPlayPeriod = "playPeriod" ) const ( - ResultLastWinningNumber = wasmlib.Key("lastWinningNumber") - ResultRoundNumber = wasmlib.Key("roundNumber") - ResultRoundStartedAt = wasmlib.Key("roundStartedAt") - ResultRoundStatus = wasmlib.Key("roundStatus") + ResultLastWinningNumber = "lastWinningNumber" + ResultRoundNumber = "roundNumber" + ResultRoundStartedAt = "roundStartedAt" + ResultRoundStatus = "roundStatus" ) const ( - StateBets = wasmlib.Key("bets") - StateLastWinningNumber = wasmlib.Key("lastWinningNumber") - StatePlayPeriod = wasmlib.Key("playPeriod") - StateRoundNumber = wasmlib.Key("roundNumber") - StateRoundStartedAt = wasmlib.Key("roundStartedAt") - StateRoundStatus = wasmlib.Key("roundStatus") + StateBets = "bets" + StateLastWinningNumber = "lastWinningNumber" + StatePlayPeriod = "playPeriod" + StateRoundNumber = "roundNumber" + StateRoundStartedAt = "roundStartedAt" + StateRoundStatus = "roundStatus" ) const ( diff --git a/contracts/wasm/fairroulette/go/fairroulette/events.go b/contracts/wasm/fairroulette/go/fairroulette/events.go new file mode 100644 index 0000000000..353c75c871 --- /dev/null +++ b/contracts/wasm/fairroulette/go/fairroulette/events.go @@ -0,0 +1,50 @@ +// 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 + +//nolint:gocritic +package fairroulette + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type FairRouletteEvents struct{} + +func (e FairRouletteEvents) Bet(address wasmlib.ScAddress, amount int64, number int64) { + wasmlib.NewEventEncoder("fairroulette.bet"). + Address(address). + Int64(amount). + Int64(number). + Emit() +} + +func (e FairRouletteEvents) Payout(address wasmlib.ScAddress, amount int64) { + wasmlib.NewEventEncoder("fairroulette.payout"). + Address(address). + Int64(amount). + Emit() +} + +func (e FairRouletteEvents) Round(number int64) { + wasmlib.NewEventEncoder("fairroulette.round"). + Int64(number). + Emit() +} + +func (e FairRouletteEvents) Start() { + wasmlib.NewEventEncoder("fairroulette.start"). + Emit() +} + +func (e FairRouletteEvents) Stop() { + wasmlib.NewEventEncoder("fairroulette.stop"). + Emit() +} + +func (e FairRouletteEvents) Winner(number int64) { + wasmlib.NewEventEncoder("fairroulette.winner"). + Int64(number). + Emit() +} diff --git a/contracts/wasm/fairroulette/go/fairroulette/fairroulette.go b/contracts/wasm/fairroulette/go/fairroulette/fairroulette.go index a26a299a70..729953c23c 100644 --- a/contracts/wasm/fairroulette/go/fairroulette/fairroulette.go +++ b/contracts/wasm/fairroulette/go/fairroulette/fairroulette.go @@ -81,9 +81,7 @@ func funcPlaceBet(ctx wasmlib.ScFuncContext, f *PlaceBetContext) { // of serializing the bet struct into a bytes representation. bets.GetBet(betNr).SetValue(bet) - ctx.Event("fairroulette.bet.placed " + bet.Better.Address().String() + - " " + ctx.Utility().String(bet.Amount) + - " " + ctx.Utility().String(bet.Number)) + f.Events.Bet(bet.Better.Address(), bet.Amount, bet.Number) // Was this the first bet of this round? if betNr == 0 { @@ -105,13 +103,12 @@ func funcPlaceBet(ctx wasmlib.ScFuncContext, f *PlaceBetContext) { timestamp := int32(ctx.Timestamp() / NanoTimeDivider) f.State.RoundStartedAt().SetValue(timestamp) - ctx.Event("fairroulette.round.state " + f.State.RoundStatus().String() + - " " + ctx.Utility().String(int64(timestamp))) + f.Events.Start() roundNumber := f.State.RoundNumber() roundNumber.SetValue(roundNumber.Value() + 1) - ctx.Event("fairroulette.round.number " + roundNumber.String()) + f.Events.Round(roundNumber.Value()) // And now for our next trick we post a delayed request to ourselves on the Tangle. // We are requesting to call the 'payWinners' function, but delay it for the playPeriod @@ -133,7 +130,7 @@ func funcPayWinners(ctx wasmlib.ScFuncContext, f *PayWinnersContext) { // generator will use the next 8 bytes from the hash as its random Int64 number and once // it runs out of data it simply hashes the previous hash for a next pseudo-random sequence. // Here we determine the winning number for this round in the range of 1 thru MaxNumber. - winningNumber := ctx.Utility().Random(MaxNumber-1) + 1 + winningNumber := ctx.Random(MaxNumber-1) + 1 // Save the last winning number in state storage under 'lastWinningNumber' so that there // is (limited) time for people to call the 'getLastWinningNumber' View to verify the last @@ -178,8 +175,7 @@ func funcPayWinners(ctx wasmlib.ScFuncContext, f *PayWinnersContext) { // so that the 'bets' array becomes available for when the next betting round ends. bets.Clear() - ctx.Event("fairroulette.round.winning_number " + ctx.Utility().String(winningNumber)) - + f.Events.Winner(winningNumber) // Did we have any winners at all? if len(winners) == 0 { // No winners, log this fact to the log on the host. @@ -221,7 +217,7 @@ func funcPayWinners(ctx wasmlib.ScFuncContext, f *PayWinnersContext) { } // Announce who got sent what as event. - ctx.Event("fairroulette.payout " + bet.Better.Address().String() + " " + ctx.Utility().String(payout)) + f.Events.Payout(bet.Better.Address(), payout) } // This is where we transfer the remainder after payout to the creator of the smart contract. @@ -237,7 +233,7 @@ func funcPayWinners(ctx wasmlib.ScFuncContext, f *PayWinnersContext) { // Set round status to 0, send out event to notify that the round has ended f.State.RoundStatus().SetValue(0) - ctx.Event("fairroulette.round.state " + f.State.RoundStatus().String()) + f.Events.Stop() } func funcForceReset(ctx wasmlib.ScFuncContext, f *ForceResetContext) { @@ -249,7 +245,7 @@ func funcForceReset(ctx wasmlib.ScFuncContext, f *ForceResetContext) { // Set round status to 0, send out event to notify that the round has ended f.State.RoundStatus().SetValue(0) - ctx.Event("fairroulette.round.state " + f.State.RoundStatus().String()) + f.Events.Stop() } // 'playPeriod' can be used by the contract creator to set the length of a betting round diff --git a/contracts/wasm/fairroulette/go/fairroulette/keys.go b/contracts/wasm/fairroulette/go/fairroulette/keys.go index 2837c356f4..3f95a7a418 100644 --- a/contracts/wasm/fairroulette/go/fairroulette/keys.go +++ b/contracts/wasm/fairroulette/go/fairroulette/keys.go @@ -10,18 +10,20 @@ package fairroulette import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" const ( - IdxParamNumber = 0 - IdxParamPlayPeriod = 1 + IdxParamNumber = 0 + IdxParamPlayPeriod = 1 + IdxResultLastWinningNumber = 2 IdxResultRoundNumber = 3 IdxResultRoundStartedAt = 4 IdxResultRoundStatus = 5 - IdxStateBets = 6 - IdxStateLastWinningNumber = 7 - IdxStatePlayPeriod = 8 - IdxStateRoundNumber = 9 - IdxStateRoundStartedAt = 10 - IdxStateRoundStatus = 11 + + IdxStateBets = 6 + IdxStateLastWinningNumber = 7 + IdxStatePlayPeriod = 8 + IdxStateRoundNumber = 9 + IdxStateRoundStartedAt = 10 + IdxStateRoundStatus = 11 ) const keyMapLen = 12 diff --git a/contracts/wasm/fairroulette/go/fairroulette/lib.go b/contracts/wasm/fairroulette/go/fairroulette/lib.go index a6b2d30b11..5ca3bb14f4 100644 --- a/contracts/wasm/fairroulette/go/fairroulette/lib.go +++ b/contracts/wasm/fairroulette/go/fairroulette/lib.go @@ -27,11 +27,13 @@ func OnLoad() { } type ForcePayoutContext struct { - State MutableFairRouletteState + Events FairRouletteEvents + State MutableFairRouletteState } func funcForcePayoutThunk(ctx wasmlib.ScFuncContext) { ctx.Log("fairroulette.funcForcePayout") + // only SC creator can restart the round forcefully ctx.Require(ctx.Caller() == ctx.ContractCreator(), "no permission") @@ -45,11 +47,13 @@ func funcForcePayoutThunk(ctx wasmlib.ScFuncContext) { } type ForceResetContext struct { - State MutableFairRouletteState + Events FairRouletteEvents + State MutableFairRouletteState } func funcForceResetThunk(ctx wasmlib.ScFuncContext) { ctx.Log("fairroulette.funcForceReset") + // only SC creator can restart the round forcefully ctx.Require(ctx.Caller() == ctx.ContractCreator(), "no permission") @@ -63,11 +67,13 @@ func funcForceResetThunk(ctx wasmlib.ScFuncContext) { } type PayWinnersContext struct { - State MutableFairRouletteState + Events FairRouletteEvents + State MutableFairRouletteState } func funcPayWinnersThunk(ctx wasmlib.ScFuncContext) { ctx.Log("fairroulette.funcPayWinners") + // only SC itself can invoke this function ctx.Require(ctx.Caller() == ctx.AccountID(), "no permission") @@ -81,6 +87,7 @@ func funcPayWinnersThunk(ctx wasmlib.ScFuncContext) { } type PlaceBetContext struct { + Events FairRouletteEvents Params ImmutablePlaceBetParams State MutableFairRouletteState } @@ -101,12 +108,14 @@ func funcPlaceBetThunk(ctx wasmlib.ScFuncContext) { } type PlayPeriodContext struct { + Events FairRouletteEvents Params ImmutablePlayPeriodParams State MutableFairRouletteState } func funcPlayPeriodThunk(ctx wasmlib.ScFuncContext) { ctx.Log("fairroulette.funcPlayPeriod") + // only SC creator can update the play period ctx.Require(ctx.Caller() == ctx.ContractCreator(), "no permission") diff --git a/contracts/wasm/fairroulette/go/fairroulette/structs.go b/contracts/wasm/fairroulette/go/fairroulette/structs.go index 34b0d66237..944ed41420 100644 --- a/contracts/wasm/fairroulette/go/fairroulette/structs.go +++ b/contracts/wasm/fairroulette/go/fairroulette/structs.go @@ -51,6 +51,10 @@ type MutableBet struct { keyID wasmlib.Key32 } +func (o MutableBet) Delete() { + wasmlib.DelKey(o.objID, o.keyID, wasmlib.TYPE_BYTES) +} + func (o MutableBet) Exists() bool { return wasmlib.Exists(o.objID, o.keyID, wasmlib.TYPE_BYTES) } diff --git a/contracts/wasm/fairroulette/schema.yaml b/contracts/wasm/fairroulette/schema.yaml index 9e739154a1..d895358ffe 100644 --- a/contracts/wasm/fairroulette/schema.yaml +++ b/contracts/wasm/fairroulette/schema.yaml @@ -1,5 +1,19 @@ name: FairRoulette description: "" +events: + bet: + address: Address // address of better + amount: Int64 // amount of iotas to bet + number: Int64 // number to bet on + payout: + address: Address // address of winner + amount: Int64 // amount of iotas won + round: + number: Int64 // current betting round number + start: + stop: + winner: + number: Int64 // the winning number structs: Bet: amount: Int64 diff --git a/contracts/wasm/fairroulette/src/consts.rs b/contracts/wasm/fairroulette/src/consts.rs index e2fabf0556..fd808c56f5 100644 --- a/contracts/wasm/fairroulette/src/consts.rs +++ b/contracts/wasm/fairroulette/src/consts.rs @@ -5,48 +5,45 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; -pub const SC_NAME: &str = "fairroulette"; -pub const HSC_NAME: ScHname = ScHname(0xdf79d138); - -pub const PARAM_NUMBER: &str = "number"; -pub const PARAM_PLAY_PERIOD: &str = "playPeriod"; - -pub const RESULT_LAST_WINNING_NUMBER: &str = "lastWinningNumber"; -pub const RESULT_ROUND_NUMBER: &str = "roundNumber"; -pub const RESULT_ROUND_STARTED_AT: &str = "roundStartedAt"; -pub const RESULT_ROUND_STATUS: &str = "roundStatus"; - -pub const STATE_BETS: &str = "bets"; -pub const STATE_LAST_WINNING_NUMBER: &str = "lastWinningNumber"; -pub const STATE_PLAY_PERIOD: &str = "playPeriod"; -pub const STATE_ROUND_NUMBER: &str = "roundNumber"; -pub const STATE_ROUND_STARTED_AT: &str = "roundStartedAt"; -pub const STATE_ROUND_STATUS: &str = "roundStatus"; - -pub const FUNC_FORCE_PAYOUT: &str = "forcePayout"; -pub const FUNC_FORCE_RESET: &str = "forceReset"; -pub const FUNC_PAY_WINNERS: &str = "payWinners"; -pub const FUNC_PLACE_BET: &str = "placeBet"; -pub const FUNC_PLAY_PERIOD: &str = "playPeriod"; -pub const VIEW_LAST_WINNING_NUMBER: &str = "lastWinningNumber"; -pub const VIEW_ROUND_NUMBER: &str = "roundNumber"; -pub const VIEW_ROUND_STARTED_AT: &str = "roundStartedAt"; -pub const VIEW_ROUND_STATUS: &str = "roundStatus"; - -pub const HFUNC_FORCE_PAYOUT: ScHname = ScHname(0x555a4c4f); -pub const HFUNC_FORCE_RESET: ScHname = ScHname(0xa331951e); -pub const HFUNC_PAY_WINNERS: ScHname = ScHname(0xfb2b0144); -pub const HFUNC_PLACE_BET: ScHname = ScHname(0xdfba7d1b); -pub const HFUNC_PLAY_PERIOD: ScHname = ScHname(0xcb94b293); -pub const HVIEW_LAST_WINNING_NUMBER: ScHname = ScHname(0x2f5f09fe); -pub const HVIEW_ROUND_NUMBER: ScHname = ScHname(0x0dcfe520); -pub const HVIEW_ROUND_STARTED_AT: ScHname = ScHname(0x725de8b4); -pub const HVIEW_ROUND_STATUS: ScHname = ScHname(0x145053b5); - -// @formatter:on +pub const SC_NAME : &str = "fairroulette"; +pub const SC_DESCRIPTION : &str = ""; +pub const HSC_NAME : ScHname = ScHname(0xdf79d138); + +pub const PARAM_NUMBER : &str = "number"; +pub const PARAM_PLAY_PERIOD : &str = "playPeriod"; + +pub const RESULT_LAST_WINNING_NUMBER : &str = "lastWinningNumber"; +pub const RESULT_ROUND_NUMBER : &str = "roundNumber"; +pub const RESULT_ROUND_STARTED_AT : &str = "roundStartedAt"; +pub const RESULT_ROUND_STATUS : &str = "roundStatus"; + +pub const STATE_BETS : &str = "bets"; +pub const STATE_LAST_WINNING_NUMBER : &str = "lastWinningNumber"; +pub const STATE_PLAY_PERIOD : &str = "playPeriod"; +pub const STATE_ROUND_NUMBER : &str = "roundNumber"; +pub const STATE_ROUND_STARTED_AT : &str = "roundStartedAt"; +pub const STATE_ROUND_STATUS : &str = "roundStatus"; + +pub const FUNC_FORCE_PAYOUT : &str = "forcePayout"; +pub const FUNC_FORCE_RESET : &str = "forceReset"; +pub const FUNC_PAY_WINNERS : &str = "payWinners"; +pub const FUNC_PLACE_BET : &str = "placeBet"; +pub const FUNC_PLAY_PERIOD : &str = "playPeriod"; +pub const VIEW_LAST_WINNING_NUMBER : &str = "lastWinningNumber"; +pub const VIEW_ROUND_NUMBER : &str = "roundNumber"; +pub const VIEW_ROUND_STARTED_AT : &str = "roundStartedAt"; +pub const VIEW_ROUND_STATUS : &str = "roundStatus"; + +pub const HFUNC_FORCE_PAYOUT : ScHname = ScHname(0x555a4c4f); +pub const HFUNC_FORCE_RESET : ScHname = ScHname(0xa331951e); +pub const HFUNC_PAY_WINNERS : ScHname = ScHname(0xfb2b0144); +pub const HFUNC_PLACE_BET : ScHname = ScHname(0xdfba7d1b); +pub const HFUNC_PLAY_PERIOD : ScHname = ScHname(0xcb94b293); +pub const HVIEW_LAST_WINNING_NUMBER : ScHname = ScHname(0x2f5f09fe); +pub const HVIEW_ROUND_NUMBER : ScHname = ScHname(0x0dcfe520); +pub const HVIEW_ROUND_STARTED_AT : ScHname = ScHname(0x725de8b4); +pub const HVIEW_ROUND_STATUS : ScHname = ScHname(0x145053b5); diff --git a/contracts/wasm/fairroulette/src/contract.rs b/contracts/wasm/fairroulette/src/contract.rs index 174a6ed640..cfdd6239e9 100644 --- a/contracts/wasm/fairroulette/src/contract.rs +++ b/contracts/wasm/fairroulette/src/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -18,45 +16,45 @@ use crate::params::*; use crate::results::*; pub struct ForcePayoutCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct ForceResetCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct PayWinnersCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct PlaceBetCall { - pub func: ScFunc, - pub params: MutablePlaceBetParams, + pub func: ScFunc, + pub params: MutablePlaceBetParams, } pub struct PlayPeriodCall { - pub func: ScFunc, - pub params: MutablePlayPeriodParams, + pub func: ScFunc, + pub params: MutablePlayPeriodParams, } pub struct LastWinningNumberCall { - pub func: ScView, - pub results: ImmutableLastWinningNumberResults, + pub func: ScView, + pub results: ImmutableLastWinningNumberResults, } pub struct RoundNumberCall { - pub func: ScView, - pub results: ImmutableRoundNumberResults, + pub func: ScView, + pub results: ImmutableRoundNumberResults, } pub struct RoundStartedAtCall { - pub func: ScView, - pub results: ImmutableRoundStartedAtResults, + pub func: ScView, + pub results: ImmutableRoundStartedAtResults, } pub struct RoundStatusCall { - pub func: ScView, - pub results: ImmutableRoundStatusResults, + pub func: ScView, + pub results: ImmutableRoundStatusResults, } pub struct ScFuncs { @@ -68,64 +66,70 @@ impl ScFuncs { func: ScFunc::new(HSC_NAME, HFUNC_FORCE_PAYOUT), } } + pub fn force_reset(_ctx: & dyn ScFuncCallContext) -> ForceResetCall { ForceResetCall { func: ScFunc::new(HSC_NAME, HFUNC_FORCE_RESET), } } + pub fn pay_winners(_ctx: & dyn ScFuncCallContext) -> PayWinnersCall { PayWinnersCall { func: ScFunc::new(HSC_NAME, HFUNC_PAY_WINNERS), } } + pub fn place_bet(_ctx: & dyn ScFuncCallContext) -> PlaceBetCall { let mut f = PlaceBetCall { - func: ScFunc::new(HSC_NAME, HFUNC_PLACE_BET), + func: ScFunc::new(HSC_NAME, HFUNC_PLACE_BET), params: MutablePlaceBetParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn play_period(_ctx: & dyn ScFuncCallContext) -> PlayPeriodCall { let mut f = PlayPeriodCall { - func: ScFunc::new(HSC_NAME, HFUNC_PLAY_PERIOD), + func: ScFunc::new(HSC_NAME, HFUNC_PLAY_PERIOD), params: MutablePlayPeriodParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn last_winning_number(_ctx: & dyn ScViewCallContext) -> LastWinningNumberCall { let mut f = LastWinningNumberCall { - func: ScView::new(HSC_NAME, HVIEW_LAST_WINNING_NUMBER), + func: ScView::new(HSC_NAME, HVIEW_LAST_WINNING_NUMBER), results: ImmutableLastWinningNumberResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn round_number(_ctx: & dyn ScViewCallContext) -> RoundNumberCall { let mut f = RoundNumberCall { - func: ScView::new(HSC_NAME, HVIEW_ROUND_NUMBER), + func: ScView::new(HSC_NAME, HVIEW_ROUND_NUMBER), results: ImmutableRoundNumberResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn round_started_at(_ctx: & dyn ScViewCallContext) -> RoundStartedAtCall { let mut f = RoundStartedAtCall { - func: ScView::new(HSC_NAME, HVIEW_ROUND_STARTED_AT), + func: ScView::new(HSC_NAME, HVIEW_ROUND_STARTED_AT), results: ImmutableRoundStartedAtResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn round_status(_ctx: & dyn ScViewCallContext) -> RoundStatusCall { let mut f = RoundStatusCall { - func: ScView::new(HSC_NAME, HVIEW_ROUND_STATUS), + func: ScView::new(HSC_NAME, HVIEW_ROUND_STATUS), results: ImmutableRoundStatusResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/contracts/wasm/fairroulette/src/events.rs b/contracts/wasm/fairroulette/src/events.rs new file mode 100644 index 0000000000..be639f0726 --- /dev/null +++ b/contracts/wasm/fairroulette/src/events.rs @@ -0,0 +1,51 @@ +// 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 FairRouletteEvents { +} + +impl FairRouletteEvents { + + pub fn bet(&self, address: &ScAddress, amount: i64, number: i64) { + let mut encoder = EventEncoder::new("fairroulette.bet"); + encoder.address(&address); + encoder.int64(amount); + encoder.int64(number); + encoder.emit(); + } + + pub fn payout(&self, address: &ScAddress, amount: i64) { + let mut encoder = EventEncoder::new("fairroulette.payout"); + encoder.address(&address); + encoder.int64(amount); + encoder.emit(); + } + + pub fn round(&self, number: i64) { + let mut encoder = EventEncoder::new("fairroulette.round"); + encoder.int64(number); + encoder.emit(); + } + + pub fn start(&self) { + EventEncoder::new("fairroulette.start").emit(); + } + + pub fn stop(&self) { + EventEncoder::new("fairroulette.stop").emit(); + } + + pub fn winner(&self, number: i64) { + let mut encoder = EventEncoder::new("fairroulette.winner"); + encoder.int64(number); + encoder.emit(); + } +} diff --git a/contracts/wasm/fairroulette/src/fairroulette.rs b/contracts/wasm/fairroulette/src/fairroulette.rs index f955a59d1c..7b2bc95955 100644 --- a/contracts/wasm/fairroulette/src/fairroulette.rs +++ b/contracts/wasm/fairroulette/src/fairroulette.rs @@ -25,7 +25,7 @@ const DEFAULT_PLAY_PERIOD: i32 = 60; const ENABLE_SELF_POST: bool = true; // The number to divide nano seconds to seconds. -const NANO_TIME_DIVIDER: i64 = 1000000000; +const NANO_TIME_DIVIDER: i64 = 1_000_000_000; // 'placeBet' is used by betters to place a bet on a number from 1 to MAX_NUMBER. The first // incoming bet triggers a betting round of configurable duration. After the playing period @@ -81,12 +81,7 @@ pub fn func_place_bet(ctx: &ScFuncContext, f: &PlaceBetContext) { // of serializing the bet struct into a bytes representation. bets.get_bet(bet_nr).set_value(&bet); - ctx.event(&format!( - "fairroulette.bet.placed {0} {1} {2}", - &bet.better.address().to_string(), - bet.amount, - bet.number - )); + f.events.bet(&bet.better.address(), bet.amount, bet.number); // Was this the first bet of this round? if bet_nr == 0 { @@ -109,19 +104,12 @@ pub fn func_place_bet(ctx: &ScFuncContext, f: &PlaceBetContext) { let timestamp = (ctx.timestamp() / NANO_TIME_DIVIDER) as i32; f.state.round_started_at().set_value(timestamp); - ctx.event(&format!( - "fairroulette.round.state {0} {1}", - f.state.round_status().value(), - timestamp - )); + f.events.start(); let round_number = f.state.round_number(); round_number.set_value(round_number.value() + 1); - ctx.event(&format!( - "fairroulette.round.number {0}", - round_number.value() - )); + f.events.round(round_number.value()); // And now for our next trick we post a delayed request to ourselves on the Tangle. // We are requesting to call the 'payWinners' function, but delay it for the play_period @@ -145,7 +133,7 @@ pub fn func_pay_winners(ctx: &ScFuncContext, f: &PayWinnersContext) { // generator will use the next 8 bytes from the hash as its random Int64 number and once // it runs out of data it simply hashes the previous hash for a next pseudo-random sequence. // Here we determine the winning number for this round in the range of 1 thru MAX_NUMBER. - let winning_number: i64 = ctx.utility().random(MAX_NUMBER - 1) + 1; + let winning_number: i64 = ctx.random(MAX_NUMBER - 1) + 1; // Save the last winning number in state storage under 'lastWinningNumber' so that there // is (limited) time for people to call the 'getLastWinningNumber' View to verify the last @@ -190,10 +178,7 @@ pub fn func_pay_winners(ctx: &ScFuncContext, f: &PayWinnersContext) { // so that the 'bets' array becomes available for when the next betting round ends. bets.clear(); - ctx.event(&format!( - "fairroulette.round.winning_number {}", - winning_number - )); + f.events.winner(winning_number); // Did we have any winners at all? if winners.is_empty() { @@ -236,11 +221,7 @@ pub fn func_pay_winners(ctx: &ScFuncContext, f: &PayWinnersContext) { } // Announce who got sent what as event. - ctx.event(&format!( - "fairroulette.payout {} {}", - &bet.better.address().to_string(), - payout - )); + f.events.payout(&bet.better.address(), payout); } // This is where we transfer the remainder after payout to the creator of the smart contract. @@ -256,26 +237,20 @@ pub fn func_pay_winners(ctx: &ScFuncContext, f: &PayWinnersContext) { // Set round status to 0, send out event to notify that the round has ended f.state.round_status().set_value(0); - ctx.event(&format!( - "fairroulette.round.state {0}", - f.state.round_status().value() - )); + f.events.stop(); } -pub fn func_force_reset(ctx: &ScFuncContext, f: &ForceResetContext) { - +pub fn func_force_reset(_ctx: &ScFuncContext, f: &ForceResetContext) { + // Get the 'bets' array in state storage. let bets: ArrayOfMutableBet = f.state.bets(); - + // Clear all bets. bets.clear(); - + // Set round status to 0, send out event to notify that the round has ended f.state.round_status().set_value(0); - ctx.event(&format!( - "fairroulette.round.state {0}", - f.state.round_status().value() - )); + f.events.stop(); } // 'playPeriod' can be used by the contract creator to set the length of a betting round diff --git a/contracts/wasm/fairroulette/src/keys.rs b/contracts/wasm/fairroulette/src/keys.rs index 8f0d713f5a..e487249b10 100644 --- a/contracts/wasm/fairroulette/src/keys.rs +++ b/contracts/wasm/fairroulette/src/keys.rs @@ -5,42 +5,42 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use crate::*; -pub(crate) const IDX_PARAM_NUMBER: usize = 0; -pub(crate) const IDX_PARAM_PLAY_PERIOD: usize = 1; -pub(crate) const IDX_RESULT_LAST_WINNING_NUMBER: usize = 2; -pub(crate) const IDX_RESULT_ROUND_NUMBER: usize = 3; -pub(crate) const IDX_RESULT_ROUND_STARTED_AT: usize = 4; -pub(crate) const IDX_RESULT_ROUND_STATUS: usize = 5; -pub(crate) const IDX_STATE_BETS: usize = 6; -pub(crate) const IDX_STATE_LAST_WINNING_NUMBER: usize = 7; -pub(crate) const IDX_STATE_PLAY_PERIOD: usize = 8; -pub(crate) const IDX_STATE_ROUND_NUMBER: usize = 9; -pub(crate) const IDX_STATE_ROUND_STARTED_AT: usize = 10; -pub(crate) const IDX_STATE_ROUND_STATUS: usize = 11; +pub(crate) const IDX_PARAM_NUMBER : usize = 0; +pub(crate) const IDX_PARAM_PLAY_PERIOD : usize = 1; + +pub(crate) const IDX_RESULT_LAST_WINNING_NUMBER : usize = 2; +pub(crate) const IDX_RESULT_ROUND_NUMBER : usize = 3; +pub(crate) const IDX_RESULT_ROUND_STARTED_AT : usize = 4; +pub(crate) const IDX_RESULT_ROUND_STATUS : usize = 5; + +pub(crate) const IDX_STATE_BETS : usize = 6; +pub(crate) const IDX_STATE_LAST_WINNING_NUMBER : usize = 7; +pub(crate) const IDX_STATE_PLAY_PERIOD : usize = 8; +pub(crate) const IDX_STATE_ROUND_NUMBER : usize = 9; +pub(crate) const IDX_STATE_ROUND_STARTED_AT : usize = 10; +pub(crate) const IDX_STATE_ROUND_STATUS : usize = 11; pub const KEY_MAP_LEN: usize = 12; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ - PARAM_NUMBER, - PARAM_PLAY_PERIOD, - RESULT_LAST_WINNING_NUMBER, - RESULT_ROUND_NUMBER, - RESULT_ROUND_STARTED_AT, - RESULT_ROUND_STATUS, - STATE_BETS, - STATE_LAST_WINNING_NUMBER, - STATE_PLAY_PERIOD, - STATE_ROUND_NUMBER, - STATE_ROUND_STARTED_AT, - STATE_ROUND_STATUS, + PARAM_NUMBER, + PARAM_PLAY_PERIOD, + RESULT_LAST_WINNING_NUMBER, + RESULT_ROUND_NUMBER, + RESULT_ROUND_STARTED_AT, + RESULT_ROUND_STATUS, + STATE_BETS, + STATE_LAST_WINNING_NUMBER, + STATE_PLAY_PERIOD, + STATE_ROUND_NUMBER, + STATE_ROUND_STARTED_AT, + STATE_ROUND_STATUS, ]; pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; @@ -50,5 +50,3 @@ pub fn idx_map(idx: usize) -> Key32 { IDX_MAP[idx] } } - -// @formatter:on diff --git a/contracts/wasm/fairroulette/src/lib.rs b/contracts/wasm/fairroulette/src/lib.rs index 86a275e671..753003c506 100644 --- a/contracts/wasm/fairroulette/src/lib.rs +++ b/contracts/wasm/fairroulette/src/lib.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] #![allow(unused_imports)] @@ -15,6 +13,7 @@ use wasmlib::*; use wasmlib::host::*; use crate::consts::*; +use crate::events::*; use crate::keys::*; use crate::params::*; use crate::results::*; @@ -22,6 +21,7 @@ use crate::state::*; mod consts; mod contract; +mod events; mod keys; mod params; mod results; @@ -32,15 +32,15 @@ mod fairroulette; #[no_mangle] fn on_load() { let exports = ScExports::new(); - exports.add_func(FUNC_FORCE_PAYOUT, func_force_payout_thunk); - exports.add_func(FUNC_FORCE_RESET, func_force_reset_thunk); - exports.add_func(FUNC_PAY_WINNERS, func_pay_winners_thunk); - exports.add_func(FUNC_PLACE_BET, func_place_bet_thunk); - exports.add_func(FUNC_PLAY_PERIOD, func_play_period_thunk); + exports.add_func(FUNC_FORCE_PAYOUT, func_force_payout_thunk); + exports.add_func(FUNC_FORCE_RESET, func_force_reset_thunk); + exports.add_func(FUNC_PAY_WINNERS, func_pay_winners_thunk); + exports.add_func(FUNC_PLACE_BET, func_place_bet_thunk); + exports.add_func(FUNC_PLAY_PERIOD, func_play_period_thunk); exports.add_view(VIEW_LAST_WINNING_NUMBER, view_last_winning_number_thunk); - exports.add_view(VIEW_ROUND_NUMBER, view_round_number_thunk); - exports.add_view(VIEW_ROUND_STARTED_AT, view_round_started_at_thunk); - exports.add_view(VIEW_ROUND_STATUS, view_round_status_thunk); + exports.add_view(VIEW_ROUND_NUMBER, view_round_number_thunk); + exports.add_view(VIEW_ROUND_STARTED_AT, view_round_started_at_thunk); + exports.add_view(VIEW_ROUND_STATUS, view_round_status_thunk); unsafe { for i in 0..KEY_MAP_LEN { @@ -50,176 +50,188 @@ fn on_load() { } pub struct ForcePayoutContext { - state: MutableFairRouletteState, + events: FairRouletteEvents, + state: MutableFairRouletteState, } fn func_force_payout_thunk(ctx: &ScFuncContext) { - ctx.log("fairroulette.funcForcePayout"); - // only SC creator can restart the round forcefully - ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); + ctx.log("fairroulette.funcForcePayout"); + + // only SC creator can restart the round forcefully + ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); - let f = ForcePayoutContext { - state: MutableFairRouletteState { - id: OBJ_ID_STATE, - }, - }; - func_force_payout(ctx, &f); - ctx.log("fairroulette.funcForcePayout ok"); + let f = ForcePayoutContext { + events: FairRouletteEvents {}, + state: MutableFairRouletteState { + id: OBJ_ID_STATE, + }, + }; + func_force_payout(ctx, &f); + ctx.log("fairroulette.funcForcePayout ok"); } pub struct ForceResetContext { - state: MutableFairRouletteState, + events: FairRouletteEvents, + state: MutableFairRouletteState, } fn func_force_reset_thunk(ctx: &ScFuncContext) { - ctx.log("fairroulette.funcForceReset"); - // only SC creator can restart the round forcefully - ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); + ctx.log("fairroulette.funcForceReset"); - let f = ForceResetContext { - state: MutableFairRouletteState { - id: OBJ_ID_STATE, - }, - }; - func_force_reset(ctx, &f); - ctx.log("fairroulette.funcForceReset ok"); + // only SC creator can restart the round forcefully + ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); + + let f = ForceResetContext { + events: FairRouletteEvents {}, + state: MutableFairRouletteState { + id: OBJ_ID_STATE, + }, + }; + func_force_reset(ctx, &f); + ctx.log("fairroulette.funcForceReset ok"); } pub struct PayWinnersContext { - state: MutableFairRouletteState, + events: FairRouletteEvents, + state: MutableFairRouletteState, } fn func_pay_winners_thunk(ctx: &ScFuncContext) { - ctx.log("fairroulette.funcPayWinners"); - // only SC itself can invoke this function - ctx.require(ctx.caller() == ctx.account_id(), "no permission"); + ctx.log("fairroulette.funcPayWinners"); + + // only SC itself can invoke this function + ctx.require(ctx.caller() == ctx.account_id(), "no permission"); - let f = PayWinnersContext { - state: MutableFairRouletteState { - id: OBJ_ID_STATE, - }, - }; - func_pay_winners(ctx, &f); - ctx.log("fairroulette.funcPayWinners ok"); + let f = PayWinnersContext { + events: FairRouletteEvents {}, + state: MutableFairRouletteState { + id: OBJ_ID_STATE, + }, + }; + func_pay_winners(ctx, &f); + ctx.log("fairroulette.funcPayWinners ok"); } pub struct PlaceBetContext { - params: ImmutablePlaceBetParams, - state: MutableFairRouletteState, + events: FairRouletteEvents, + params: ImmutablePlaceBetParams, + state: MutableFairRouletteState, } fn func_place_bet_thunk(ctx: &ScFuncContext) { - ctx.log("fairroulette.funcPlaceBet"); - let f = PlaceBetContext { - params: ImmutablePlaceBetParams { - id: OBJ_ID_PARAMS, - }, - state: MutableFairRouletteState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.number().exists(), "missing mandatory number"); - func_place_bet(ctx, &f); - ctx.log("fairroulette.funcPlaceBet ok"); + ctx.log("fairroulette.funcPlaceBet"); + let f = PlaceBetContext { + events: FairRouletteEvents {}, + params: ImmutablePlaceBetParams { + id: OBJ_ID_PARAMS, + }, + state: MutableFairRouletteState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.number().exists(), "missing mandatory number"); + func_place_bet(ctx, &f); + ctx.log("fairroulette.funcPlaceBet ok"); } pub struct PlayPeriodContext { - params: ImmutablePlayPeriodParams, - state: MutableFairRouletteState, + events: FairRouletteEvents, + params: ImmutablePlayPeriodParams, + state: MutableFairRouletteState, } fn func_play_period_thunk(ctx: &ScFuncContext) { - ctx.log("fairroulette.funcPlayPeriod"); - // only SC creator can update the play period - ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); - - let f = PlayPeriodContext { - params: ImmutablePlayPeriodParams { - id: OBJ_ID_PARAMS, - }, - state: MutableFairRouletteState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.play_period().exists(), "missing mandatory playPeriod"); - func_play_period(ctx, &f); - ctx.log("fairroulette.funcPlayPeriod ok"); + ctx.log("fairroulette.funcPlayPeriod"); + + // only SC creator can update the play period + ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); + + let f = PlayPeriodContext { + events: FairRouletteEvents {}, + params: ImmutablePlayPeriodParams { + id: OBJ_ID_PARAMS, + }, + state: MutableFairRouletteState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.play_period().exists(), "missing mandatory playPeriod"); + func_play_period(ctx, &f); + ctx.log("fairroulette.funcPlayPeriod ok"); } pub struct LastWinningNumberContext { - results: MutableLastWinningNumberResults, - state: ImmutableFairRouletteState, + results: MutableLastWinningNumberResults, + state: ImmutableFairRouletteState, } fn view_last_winning_number_thunk(ctx: &ScViewContext) { - ctx.log("fairroulette.viewLastWinningNumber"); - let f = LastWinningNumberContext { - results: MutableLastWinningNumberResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableFairRouletteState { - id: OBJ_ID_STATE, - }, - }; - view_last_winning_number(ctx, &f); - ctx.log("fairroulette.viewLastWinningNumber ok"); + ctx.log("fairroulette.viewLastWinningNumber"); + let f = LastWinningNumberContext { + results: MutableLastWinningNumberResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableFairRouletteState { + id: OBJ_ID_STATE, + }, + }; + view_last_winning_number(ctx, &f); + ctx.log("fairroulette.viewLastWinningNumber ok"); } pub struct RoundNumberContext { - results: MutableRoundNumberResults, - state: ImmutableFairRouletteState, + results: MutableRoundNumberResults, + state: ImmutableFairRouletteState, } fn view_round_number_thunk(ctx: &ScViewContext) { - ctx.log("fairroulette.viewRoundNumber"); - let f = RoundNumberContext { - results: MutableRoundNumberResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableFairRouletteState { - id: OBJ_ID_STATE, - }, - }; - view_round_number(ctx, &f); - ctx.log("fairroulette.viewRoundNumber ok"); + ctx.log("fairroulette.viewRoundNumber"); + let f = RoundNumberContext { + results: MutableRoundNumberResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableFairRouletteState { + id: OBJ_ID_STATE, + }, + }; + view_round_number(ctx, &f); + ctx.log("fairroulette.viewRoundNumber ok"); } pub struct RoundStartedAtContext { - results: MutableRoundStartedAtResults, - state: ImmutableFairRouletteState, + results: MutableRoundStartedAtResults, + state: ImmutableFairRouletteState, } fn view_round_started_at_thunk(ctx: &ScViewContext) { - ctx.log("fairroulette.viewRoundStartedAt"); - let f = RoundStartedAtContext { - results: MutableRoundStartedAtResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableFairRouletteState { - id: OBJ_ID_STATE, - }, - }; - view_round_started_at(ctx, &f); - ctx.log("fairroulette.viewRoundStartedAt ok"); + ctx.log("fairroulette.viewRoundStartedAt"); + let f = RoundStartedAtContext { + results: MutableRoundStartedAtResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableFairRouletteState { + id: OBJ_ID_STATE, + }, + }; + view_round_started_at(ctx, &f); + ctx.log("fairroulette.viewRoundStartedAt ok"); } pub struct RoundStatusContext { - results: MutableRoundStatusResults, - state: ImmutableFairRouletteState, + results: MutableRoundStatusResults, + state: ImmutableFairRouletteState, } fn view_round_status_thunk(ctx: &ScViewContext) { - ctx.log("fairroulette.viewRoundStatus"); - let f = RoundStatusContext { - results: MutableRoundStatusResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableFairRouletteState { - id: OBJ_ID_STATE, - }, - }; - view_round_status(ctx, &f); - ctx.log("fairroulette.viewRoundStatus ok"); -} - -// @formatter:on + ctx.log("fairroulette.viewRoundStatus"); + let f = RoundStatusContext { + results: MutableRoundStatusResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableFairRouletteState { + id: OBJ_ID_STATE, + }, + }; + view_round_status(ctx, &f); + ctx.log("fairroulette.viewRoundStatus ok"); +} diff --git a/contracts/wasm/fairroulette/src/params.rs b/contracts/wasm/fairroulette/src/params.rs index c5457a29a3..34de8c2ed4 100644 --- a/contracts/wasm/fairroulette/src/params.rs +++ b/contracts/wasm/fairroulette/src/params.rs @@ -13,6 +13,7 @@ use wasmlib::host::*; use crate::*; use crate::keys::*; +use crate::structs::*; #[derive(Clone, Copy)] pub struct ImmutablePlaceBetParams { @@ -21,8 +22,8 @@ pub struct ImmutablePlaceBetParams { impl ImmutablePlaceBetParams { pub fn number(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_NUMBER)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_NUMBER)) + } } #[derive(Clone, Copy)] @@ -32,8 +33,8 @@ pub struct MutablePlaceBetParams { impl MutablePlaceBetParams { pub fn number(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_NUMBER)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_NUMBER)) + } } #[derive(Clone, Copy)] @@ -43,8 +44,8 @@ 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, idx_map(IDX_PARAM_PLAY_PERIOD)) + } } #[derive(Clone, Copy)] @@ -54,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, idx_map(IDX_PARAM_PLAY_PERIOD)) + } } diff --git a/contracts/wasm/fairroulette/src/results.rs b/contracts/wasm/fairroulette/src/results.rs index ac407245b1..2b6d0b4360 100644 --- a/contracts/wasm/fairroulette/src/results.rs +++ b/contracts/wasm/fairroulette/src/results.rs @@ -22,8 +22,8 @@ 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, idx_map(IDX_RESULT_LAST_WINNING_NUMBER)) + } } #[derive(Clone, Copy)] @@ -33,8 +33,8 @@ 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, idx_map(IDX_RESULT_LAST_WINNING_NUMBER)) + } } #[derive(Clone, Copy)] @@ -44,8 +44,8 @@ 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, idx_map(IDX_RESULT_ROUND_NUMBER)) + } } #[derive(Clone, Copy)] @@ -55,8 +55,8 @@ 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, idx_map(IDX_RESULT_ROUND_NUMBER)) + } } #[derive(Clone, Copy)] @@ -66,8 +66,8 @@ 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, idx_map(IDX_RESULT_ROUND_STARTED_AT)) + } } #[derive(Clone, Copy)] @@ -77,8 +77,8 @@ 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, idx_map(IDX_RESULT_ROUND_STARTED_AT)) + } } #[derive(Clone, Copy)] @@ -88,8 +88,8 @@ 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, idx_map(IDX_RESULT_ROUND_STATUS)) + } } #[derive(Clone, Copy)] @@ -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, idx_map(IDX_RESULT_ROUND_STATUS)) + } } diff --git a/contracts/wasm/fairroulette/src/state.rs b/contracts/wasm/fairroulette/src/state.rs index f67c00ce16..7277b6f457 100644 --- a/contracts/wasm/fairroulette/src/state.rs +++ b/contracts/wasm/fairroulette/src/state.rs @@ -16,7 +16,7 @@ use crate::keys::*; use crate::structs::*; pub struct ArrayOfImmutableBet { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfImmutableBet { @@ -24,9 +24,9 @@ impl ArrayOfImmutableBet { get_length(self.obj_id) } - pub fn get_bet(&self, index: i32) -> ImmutableBet { - ImmutableBet { obj_id: self.obj_id, key_id: Key32(index) } - } + pub fn get_bet(&self, index: i32) -> ImmutableBet { + ImmutableBet { obj_id: self.obj_id, key_id: Key32(index) } + } } #[derive(Clone, Copy)] @@ -36,33 +36,33 @@ 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); - ArrayOfImmutableBet { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, idx_map(IDX_STATE_BETS), 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, idx_map(IDX_STATE_LAST_WINNING_NUMBER)) + } pub fn play_period(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_STATE_PLAY_PERIOD)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_STATE_PLAY_PERIOD)) + } pub fn round_number(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_ROUND_NUMBER)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_STATE_ROUND_NUMBER)) + } pub fn round_started_at(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_STATE_ROUND_STARTED_AT)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_STATE_ROUND_STARTED_AT)) + } pub fn round_status(&self) -> ScImmutableInt16 { - ScImmutableInt16::new(self.id, idx_map(IDX_STATE_ROUND_STATUS)) - } + ScImmutableInt16::new(self.id, idx_map(IDX_STATE_ROUND_STATUS)) + } } pub struct ArrayOfMutableBet { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfMutableBet { @@ -74,9 +74,9 @@ impl ArrayOfMutableBet { get_length(self.obj_id) } - pub fn get_bet(&self, index: i32) -> MutableBet { - MutableBet { obj_id: self.obj_id, key_id: Key32(index) } - } + pub fn get_bet(&self, index: i32) -> MutableBet { + MutableBet { obj_id: self.obj_id, key_id: Key32(index) } + } } #[derive(Clone, Copy)] @@ -86,27 +86,27 @@ pub struct MutableFairRouletteState { impl MutableFairRouletteState { pub fn bets(&self) -> ArrayOfMutableBet { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_BETS), TYPE_ARRAY | TYPE_BYTES); - ArrayOfMutableBet { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, idx_map(IDX_STATE_BETS), 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, idx_map(IDX_STATE_LAST_WINNING_NUMBER)) + } pub fn play_period(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_STATE_PLAY_PERIOD)) - } + ScMutableInt32::new(self.id, idx_map(IDX_STATE_PLAY_PERIOD)) + } pub fn round_number(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_ROUND_NUMBER)) - } + ScMutableInt64::new(self.id, idx_map(IDX_STATE_ROUND_NUMBER)) + } pub fn round_started_at(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_STATE_ROUND_STARTED_AT)) - } + ScMutableInt32::new(self.id, idx_map(IDX_STATE_ROUND_STARTED_AT)) + } pub fn round_status(&self) -> ScMutableInt16 { - ScMutableInt16::new(self.id, idx_map(IDX_STATE_ROUND_STATUS)) - } + ScMutableInt16::new(self.id, idx_map(IDX_STATE_ROUND_STATUS)) + } } diff --git a/contracts/wasm/fairroulette/src/structs.rs b/contracts/wasm/fairroulette/src/structs.rs index 335bea0497..501d719fbf 100644 --- a/contracts/wasm/fairroulette/src/structs.rs +++ b/contracts/wasm/fairroulette/src/structs.rs @@ -5,34 +5,33 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] +#![allow(unused_imports)] use wasmlib::*; use wasmlib::host::*; pub struct Bet { - pub amount: i64, - pub better: ScAgentID, - pub number: i64, + pub amount : i64, + pub better : ScAgentID, + pub number : i64, } impl Bet { pub fn from_bytes(bytes: &[u8]) -> Bet { let mut decode = BytesDecoder::new(bytes); Bet { - amount: decode.int64(), - better: decode.agent_id(), - number: decode.int64(), + amount : decode.int64(), + better : decode.agent_id(), + number : decode.int64(), } } pub fn to_bytes(&self) -> Vec { let mut encode = BytesEncoder::new(); - encode.int64(self.amount); - encode.agent_id(&self.better); - encode.int64(self.number); + encode.int64(self.amount); + encode.agent_id(&self.better); + encode.int64(self.number); return encode.data(); } } @@ -58,6 +57,10 @@ pub struct MutableBet { } impl MutableBet { + 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) } @@ -70,5 +73,3 @@ impl MutableBet { Bet::from_bytes(&get_bytes(self.obj_id, self.key_id, TYPE_BYTES)) } } - -// @formatter:on diff --git a/contracts/wasm/fairroulette/test/fairroulette_bg.wasm b/contracts/wasm/fairroulette/test/fairroulette_bg.wasm index 40dc5968cc..ce7b3e910f 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/consts.ts b/contracts/wasm/fairroulette/ts/fairroulette/consts.ts index 45f2a3828f..d930b586af 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/consts.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/consts.ts @@ -5,10 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; -export const ScName = "fairroulette"; -export const HScName = new wasmlib.ScHname(0xdf79d138); +export const ScName = "fairroulette"; +export const ScDescription = ""; +export const HScName = new wasmlib.ScHname(0xdf79d138); export const ParamNumber = "number"; export const ParamPlayPeriod = "playPeriod"; diff --git a/contracts/wasm/fairroulette/ts/fairroulette/contract.ts b/contracts/wasm/fairroulette/ts/fairroulette/contract.ts index 601fcc7be7..c612394c71 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/contract.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/contract.ts @@ -5,108 +5,109 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ForcePayoutCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncForcePayout); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncForcePayout); } export class ForcePayoutContext { - state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); + events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); + state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); } export class ForceResetCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncForceReset); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncForceReset); } export class ForceResetContext { - state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); + events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); + state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); } export class PayWinnersCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPayWinners); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPayWinners); } export class PayWinnersContext { - state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); + events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); + state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); } export class PlaceBetCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPlaceBet); - params: sc.MutablePlaceBetParams = new sc.MutablePlaceBetParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPlaceBet); + params: sc.MutablePlaceBetParams = new sc.MutablePlaceBetParams(); } export class PlaceBetContext { - params: sc.ImmutablePlaceBetParams = new sc.ImmutablePlaceBetParams(); - state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); + events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); + params: sc.ImmutablePlaceBetParams = new sc.ImmutablePlaceBetParams(); + state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); } export class PlayPeriodCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPlayPeriod); - params: sc.MutablePlayPeriodParams = new sc.MutablePlayPeriodParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPlayPeriod); + params: sc.MutablePlayPeriodParams = new sc.MutablePlayPeriodParams(); } export class PlayPeriodContext { - params: sc.ImmutablePlayPeriodParams = new sc.ImmutablePlayPeriodParams(); - state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); + events: sc.FairRouletteEvents = new sc.FairRouletteEvents(); + params: sc.ImmutablePlayPeriodParams = new sc.ImmutablePlayPeriodParams(); + state: sc.MutableFairRouletteState = new sc.MutableFairRouletteState(); } export class LastWinningNumberCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewLastWinningNumber); - results: sc.ImmutableLastWinningNumberResults = new sc.ImmutableLastWinningNumberResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewLastWinningNumber); + results: sc.ImmutableLastWinningNumberResults = new sc.ImmutableLastWinningNumberResults(); } export class LastWinningNumberContext { - results: sc.MutableLastWinningNumberResults = new sc.MutableLastWinningNumberResults(); - state: sc.ImmutableFairRouletteState = new sc.ImmutableFairRouletteState(); + results: sc.MutableLastWinningNumberResults = new sc.MutableLastWinningNumberResults(); + state: sc.ImmutableFairRouletteState = new sc.ImmutableFairRouletteState(); } export class RoundNumberCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewRoundNumber); - results: sc.ImmutableRoundNumberResults = new sc.ImmutableRoundNumberResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewRoundNumber); + results: sc.ImmutableRoundNumberResults = new sc.ImmutableRoundNumberResults(); } export class RoundNumberContext { - results: sc.MutableRoundNumberResults = new sc.MutableRoundNumberResults(); - state: sc.ImmutableFairRouletteState = new sc.ImmutableFairRouletteState(); + results: sc.MutableRoundNumberResults = new sc.MutableRoundNumberResults(); + state: sc.ImmutableFairRouletteState = new sc.ImmutableFairRouletteState(); } export class RoundStartedAtCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewRoundStartedAt); - results: sc.ImmutableRoundStartedAtResults = new sc.ImmutableRoundStartedAtResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewRoundStartedAt); + results: sc.ImmutableRoundStartedAtResults = new sc.ImmutableRoundStartedAtResults(); } export class RoundStartedAtContext { - results: sc.MutableRoundStartedAtResults = new sc.MutableRoundStartedAtResults(); - state: sc.ImmutableFairRouletteState = new sc.ImmutableFairRouletteState(); + results: sc.MutableRoundStartedAtResults = new sc.MutableRoundStartedAtResults(); + state: sc.ImmutableFairRouletteState = new sc.ImmutableFairRouletteState(); } export class RoundStatusCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewRoundStatus); - results: sc.ImmutableRoundStatusResults = new sc.ImmutableRoundStatusResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewRoundStatus); + results: sc.ImmutableRoundStatusResults = new sc.ImmutableRoundStatusResults(); } export class RoundStatusContext { - results: sc.MutableRoundStatusResults = new sc.MutableRoundStatusResults(); - state: sc.ImmutableFairRouletteState = new sc.ImmutableFairRouletteState(); + results: sc.MutableRoundStatusResults = new sc.MutableRoundStatusResults(); + state: sc.ImmutableFairRouletteState = new sc.ImmutableFairRouletteState(); } export class ScFuncs { - static forcePayout(ctx: wasmlib.ScFuncCallContext): ForcePayoutCall { - let f = new ForcePayoutCall(); - return f; + return new ForcePayoutCall(); } static forceReset(ctx: wasmlib.ScFuncCallContext): ForceResetCall { - let f = new ForceResetCall(); - return f; + return new ForceResetCall(); } static payWinners(ctx: wasmlib.ScFuncCallContext): PayWinnersCall { - let f = new PayWinnersCall(); - return f; + return new PayWinnersCall(); } static placeBet(ctx: wasmlib.ScFuncCallContext): PlaceBetCall { diff --git a/contracts/wasm/fairroulette/ts/fairroulette/events.ts b/contracts/wasm/fairroulette/ts/fairroulette/events.ts new file mode 100644 index 0000000000..bef3fbce6f --- /dev/null +++ b/contracts/wasm/fairroulette/ts/fairroulette/events.ts @@ -0,0 +1,48 @@ +// 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 FairRouletteEvents { + + bet(address: wasmlib.ScAddress, amount: i64, number: i64): void { + new wasmlib.EventEncoder("fairroulette.bet"). + address(address). + int64(amount). + int64(number). + emit(); + } + + payout(address: wasmlib.ScAddress, amount: i64): void { + new wasmlib.EventEncoder("fairroulette.payout"). + address(address). + int64(amount). + emit(); + } + + round(number: i64): void { + new wasmlib.EventEncoder("fairroulette.round"). + int64(number). + emit(); + } + + start(): void { + new wasmlib.EventEncoder("fairroulette.start"). + emit(); + } + + stop(): void { + new wasmlib.EventEncoder("fairroulette.stop"). + emit(); + } + + winner(number: i64): void { + new wasmlib.EventEncoder("fairroulette.winner"). + int64(number). + emit(); + } +} diff --git a/contracts/wasm/fairroulette/ts/fairroulette/fairroulette.ts b/contracts/wasm/fairroulette/ts/fairroulette/fairroulette.ts index 83db2978ca..6319c393de 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/fairroulette.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/fairroulette.ts @@ -77,11 +77,7 @@ export function funcPlaceBet(ctx: wasmlib.ScFuncContext, f: sc.PlaceBetContext): // of serializing the bet struct into a bytes representation. bets.getBet(betNr).setValue(bet); - ctx.event("fairroulette.bet.placed " + - bet.better.address().toString() + " " + - bet.amount.toString() + " " + - bet.number.toString() - ); + f.events.bet(bet.better.address(), bet.amount, bet.number); // Was this the first bet of this round? if (betNr == 0) { @@ -104,15 +100,12 @@ export function funcPlaceBet(ctx: wasmlib.ScFuncContext, f: sc.PlaceBetContext): let timestamp = (ctx.timestamp() / NANO_TIME_DIVIDER) as i32; f.state.roundStartedAt().setValue(timestamp); - ctx.event("fairroulette.round.state " + - f.state.roundStatus().toString() + " " + - timestamp.toString() - ); + f.events.start(); let roundNumber = f.state.roundNumber(); roundNumber.setValue(roundNumber.value() + 1); - ctx.event("fairroulette.round.number " + roundNumber.toString()); + f.events.round(roundNumber.value()); // And now for our next trick we post a delayed request to ourselves on the Tangle. // We are requesting to call the 'payWinners' function, but delay it for the playPeriod @@ -136,7 +129,7 @@ export function funcPayWinners(ctx: wasmlib.ScFuncContext, f: sc.PayWinnersConte // generator will use the next 8 bytes from the hash as its random Int64 number and once // it runs out of data it simply hashes the previous hash for a next pseudo-random sequence. // Here we determine the winning number for this round in the range of 1 thru MAX_NUMBER. - let winningNumber: i64 = ctx.utility().random(MAX_NUMBER - 1) + 1; + let winningNumber: i64 = ctx.random(MAX_NUMBER - 1) + 1; // Save the last winning number in state storage under 'lastWinningNumber' so that there // is (limited) time for people to call the 'getLastWinningNumber' View to verify the last @@ -181,7 +174,7 @@ export function funcPayWinners(ctx: wasmlib.ScFuncContext, f: sc.PayWinnersConte // so that the 'bets' array becomes available for when the next betting round ends. bets.clear(); - ctx.event("fairroulette.round.winningNumber " + winningNumber.toString()); + f.events.winner(winningNumber); // Did we have any winners at all? if (winners.length == 0) { @@ -224,10 +217,7 @@ export function funcPayWinners(ctx: wasmlib.ScFuncContext, f: sc.PayWinnersConte } // Announce who got sent what as event. - ctx.event("fairroulette.payout " + - bet.better.address().toString() + " " + - payout.toString() - ); + f.events.payout(bet.better.address(), payout); } // This is where we transfer the remainder after payout to the creator of the smart contract. @@ -243,7 +233,7 @@ export function funcPayWinners(ctx: wasmlib.ScFuncContext, f: sc.PayWinnersConte // Set round status to 0, send out event to notify that the round has ended f.state.roundStatus().setValue(0); - ctx.event("fairroulette.round.state " + f.state.roundStatus().toString()); + f.events.stop(); } export function funcForceReset(ctx: wasmlib.ScFuncContext, f: sc.ForceResetContext): void { @@ -256,7 +246,7 @@ export function funcForceReset(ctx: wasmlib.ScFuncContext, f: sc.ForceResetConte // Set round status to 0, send out event to notify that the round has ended f.state.roundStatus().setValue(0); - ctx.event("fairroulette.round.state +" + f.state.roundStatus().toString()); + f.events.stop(); } // 'playPeriod' can be used by the contract creator to set the length of a betting round diff --git a/contracts/wasm/fairroulette/ts/fairroulette/index.ts b/contracts/wasm/fairroulette/ts/fairroulette/index.ts index d6151e8562..a14f6af431 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/index.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/index.ts @@ -9,6 +9,7 @@ export * from "./fairroulette"; export * from "./consts"; export * from "./contract"; +export * from "./events"; export * from "./keys"; export * from "./lib"; export * from "./params"; diff --git a/contracts/wasm/fairroulette/ts/fairroulette/keys.ts b/contracts/wasm/fairroulette/ts/fairroulette/keys.ts index c458464b29..46895b797f 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/keys.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/keys.ts @@ -5,35 +5,37 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; -export const IdxParamNumber = 0; -export const IdxParamPlayPeriod = 1; +export const IdxParamNumber = 0; +export const IdxParamPlayPeriod = 1; + export const IdxResultLastWinningNumber = 2; export const IdxResultRoundNumber = 3; export const IdxResultRoundStartedAt = 4; export const IdxResultRoundStatus = 5; -export const IdxStateBets = 6; -export const IdxStateLastWinningNumber = 7; -export const IdxStatePlayPeriod = 8; -export const IdxStateRoundNumber = 9; -export const IdxStateRoundStartedAt = 10; -export const IdxStateRoundStatus = 11; + +export const IdxStateBets = 6; +export const IdxStateLastWinningNumber = 7; +export const IdxStatePlayPeriod = 8; +export const IdxStateRoundNumber = 9; +export const IdxStateRoundStartedAt = 10; +export const IdxStateRoundStatus = 11; export let keyMap: string[] = [ - sc.ParamNumber, - sc.ParamPlayPeriod, - sc.ResultLastWinningNumber, - sc.ResultRoundNumber, - sc.ResultRoundStartedAt, - sc.ResultRoundStatus, - sc.StateBets, - sc.StateLastWinningNumber, - sc.StatePlayPeriod, - sc.StateRoundNumber, - sc.StateRoundStartedAt, - sc.StateRoundStatus, + sc.ParamNumber, + sc.ParamPlayPeriod, + sc.ResultLastWinningNumber, + sc.ResultRoundNumber, + sc.ResultRoundStartedAt, + sc.ResultRoundStatus, + sc.StateBets, + sc.StateLastWinningNumber, + sc.StatePlayPeriod, + sc.StateRoundNumber, + sc.StateRoundStartedAt, + sc.StateRoundStatus, ]; export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/fairroulette/ts/fairroulette/lib.ts b/contracts/wasm/fairroulette/ts/fairroulette/lib.ts index 46d913ab04..e19135eaba 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/lib.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/lib.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export function on_call(index: i32): void { @@ -14,15 +14,15 @@ export function on_call(index: i32): void { export function on_load(): void { let exports = new wasmlib.ScExports(); - exports.addFunc(sc.FuncForcePayout, funcForcePayoutThunk); - exports.addFunc(sc.FuncForceReset, funcForceResetThunk); - exports.addFunc(sc.FuncPayWinners, funcPayWinnersThunk); - exports.addFunc(sc.FuncPlaceBet, funcPlaceBetThunk); - exports.addFunc(sc.FuncPlayPeriod, funcPlayPeriodThunk); + exports.addFunc(sc.FuncForcePayout, funcForcePayoutThunk); + exports.addFunc(sc.FuncForceReset, funcForceResetThunk); + exports.addFunc(sc.FuncPayWinners, funcPayWinnersThunk); + exports.addFunc(sc.FuncPlaceBet, funcPlaceBetThunk); + exports.addFunc(sc.FuncPlayPeriod, funcPlayPeriodThunk); exports.addView(sc.ViewLastWinningNumber, viewLastWinningNumberThunk); - exports.addView(sc.ViewRoundNumber, viewRoundNumberThunk); - exports.addView(sc.ViewRoundStartedAt, viewRoundStartedAtThunk); - exports.addView(sc.ViewRoundStatus, viewRoundStatusThunk); + exports.addView(sc.ViewRoundNumber, viewRoundNumberThunk); + exports.addView(sc.ViewRoundStartedAt, viewRoundStartedAtThunk); + exports.addView(sc.ViewRoundStatus, viewRoundStatusThunk); for (let i = 0; i < sc.keyMap.length; i++) { sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); @@ -30,93 +30,97 @@ export function on_load(): void { } function funcForcePayoutThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("fairroulette.funcForcePayout"); - // only SC creator can restart the round forcefully - ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + ctx.log("fairroulette.funcForcePayout"); - let f = new sc.ForcePayoutContext(); + // only SC creator can restart the round forcefully + ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + + let f = new sc.ForcePayoutContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcForcePayout(ctx, f); - ctx.log("fairroulette.funcForcePayout ok"); + sc.funcForcePayout(ctx, f); + ctx.log("fairroulette.funcForcePayout ok"); } function funcForceResetThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("fairroulette.funcForceReset"); - // only SC creator can restart the round forcefully - ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + ctx.log("fairroulette.funcForceReset"); + + // only SC creator can restart the round forcefully + ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); - let f = new sc.ForceResetContext(); + let f = new sc.ForceResetContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcForceReset(ctx, f); - ctx.log("fairroulette.funcForceReset ok"); + sc.funcForceReset(ctx, f); + ctx.log("fairroulette.funcForceReset ok"); } function funcPayWinnersThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("fairroulette.funcPayWinners"); - // only SC itself can invoke this function - ctx.require(ctx.caller().equals(ctx.accountID()), "no permission"); + ctx.log("fairroulette.funcPayWinners"); - let f = new sc.PayWinnersContext(); + // only SC itself can invoke this function + ctx.require(ctx.caller().equals(ctx.accountID()), "no permission"); + + let f = new sc.PayWinnersContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcPayWinners(ctx, f); - ctx.log("fairroulette.funcPayWinners ok"); + sc.funcPayWinners(ctx, f); + ctx.log("fairroulette.funcPayWinners ok"); } function funcPlaceBetThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("fairroulette.funcPlaceBet"); - let f = new sc.PlaceBetContext(); + ctx.log("fairroulette.funcPlaceBet"); + let f = new sc.PlaceBetContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.number().exists(), "missing mandatory number") - sc.funcPlaceBet(ctx, f); - ctx.log("fairroulette.funcPlaceBet ok"); + ctx.require(f.params.number().exists(), "missing mandatory number"); + sc.funcPlaceBet(ctx, f); + ctx.log("fairroulette.funcPlaceBet ok"); } function funcPlayPeriodThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("fairroulette.funcPlayPeriod"); - // only SC creator can update the play period - ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + ctx.log("fairroulette.funcPlayPeriod"); + + // only SC creator can update the play period + ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); - let f = new sc.PlayPeriodContext(); + let f = new sc.PlayPeriodContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.playPeriod().exists(), "missing mandatory playPeriod") - sc.funcPlayPeriod(ctx, f); - ctx.log("fairroulette.funcPlayPeriod ok"); + ctx.require(f.params.playPeriod().exists(), "missing mandatory playPeriod"); + sc.funcPlayPeriod(ctx, f); + ctx.log("fairroulette.funcPlayPeriod ok"); } function viewLastWinningNumberThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("fairroulette.viewLastWinningNumber"); - let f = new sc.LastWinningNumberContext(); + ctx.log("fairroulette.viewLastWinningNumber"); + let f = new sc.LastWinningNumberContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewLastWinningNumber(ctx, f); - ctx.log("fairroulette.viewLastWinningNumber ok"); + sc.viewLastWinningNumber(ctx, f); + ctx.log("fairroulette.viewLastWinningNumber ok"); } function viewRoundNumberThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("fairroulette.viewRoundNumber"); - let f = new sc.RoundNumberContext(); + ctx.log("fairroulette.viewRoundNumber"); + let f = new sc.RoundNumberContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewRoundNumber(ctx, f); - ctx.log("fairroulette.viewRoundNumber ok"); + sc.viewRoundNumber(ctx, f); + ctx.log("fairroulette.viewRoundNumber ok"); } function viewRoundStartedAtThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("fairroulette.viewRoundStartedAt"); - let f = new sc.RoundStartedAtContext(); + ctx.log("fairroulette.viewRoundStartedAt"); + let f = new sc.RoundStartedAtContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewRoundStartedAt(ctx, f); - ctx.log("fairroulette.viewRoundStartedAt ok"); + sc.viewRoundStartedAt(ctx, f); + ctx.log("fairroulette.viewRoundStartedAt ok"); } function viewRoundStatusThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("fairroulette.viewRoundStatus"); - let f = new sc.RoundStatusContext(); + ctx.log("fairroulette.viewRoundStatus"); + let f = new sc.RoundStatusContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewRoundStatus(ctx, f); - ctx.log("fairroulette.viewRoundStatus ok"); + sc.viewRoundStatus(ctx, f); + ctx.log("fairroulette.viewRoundStatus ok"); } diff --git a/contracts/wasm/fairroulette/ts/fairroulette/params.ts b/contracts/wasm/fairroulette/ts/fairroulette/params.ts index a79831a801..d4640d30e3 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/params.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/params.ts @@ -5,33 +5,29 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxParamNumber]); + } } 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, sc.idxMap[sc.IdxParamNumber]); + } } 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, sc.idxMap[sc.IdxParamPlayPeriod]); + } } 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, sc.idxMap[sc.IdxParamPlayPeriod]); + } } diff --git a/contracts/wasm/fairroulette/ts/fairroulette/results.ts b/contracts/wasm/fairroulette/ts/fairroulette/results.ts index 6ac963982b..8a55504a12 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/results.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/results.ts @@ -5,61 +5,53 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxResultLastWinningNumber]); + } } 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, sc.idxMap[sc.IdxResultLastWinningNumber]); + } } 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, sc.idxMap[sc.IdxResultRoundNumber]); + } } 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, sc.idxMap[sc.IdxResultRoundNumber]); + } } 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, sc.idxMap[sc.IdxResultRoundStartedAt]); + } } 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, sc.idxMap[sc.IdxResultRoundStartedAt]); + } } 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, sc.idxMap[sc.IdxResultRoundStatus]); + } } 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, sc.idxMap[sc.IdxResultRoundStatus]); + } } diff --git a/contracts/wasm/fairroulette/ts/fairroulette/state.ts b/contracts/wasm/fairroulette/ts/fairroulette/state.ts index 622f56cf8a..08059c1fc0 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/state.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/state.ts @@ -5,11 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ArrayOfImmutableBet { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -19,41 +19,40 @@ export class ArrayOfImmutableBet { return wasmlib.getLength(this.objID); } - getBet(index: i32): sc.ImmutableBet { - return new sc.ImmutableBet(this.objID, new wasmlib.Key32(index)); - } + getBet(index: i32): sc.ImmutableBet { + return new sc.ImmutableBet(this.objID, new wasmlib.Key32(index)); + } } 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); - return new sc.ArrayOfImmutableBet(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBets], 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, sc.idxMap[sc.IdxStateLastWinningNumber]); + } playPeriod(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxStatePlayPeriod]); - } + return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxStatePlayPeriod]); + } roundNumber(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateRoundNumber]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateRoundNumber]); + } roundStartedAt(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxStateRoundStartedAt]); - } + return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxStateRoundStartedAt]); + } roundStatus(): wasmlib.ScImmutableInt16 { - return new wasmlib.ScImmutableInt16(this.mapID, sc.idxMap[sc.IdxStateRoundStatus]); - } + return new wasmlib.ScImmutableInt16(this.mapID, sc.idxMap[sc.IdxStateRoundStatus]); + } } export class ArrayOfMutableBet { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -67,35 +66,34 @@ export class ArrayOfMutableBet { return wasmlib.getLength(this.objID); } - getBet(index: i32): sc.MutableBet { - return new sc.MutableBet(this.objID, new wasmlib.Key32(index)); - } + getBet(index: i32): sc.MutableBet { + return new sc.MutableBet(this.objID, new wasmlib.Key32(index)); + } } export class MutableFairRouletteState extends wasmlib.ScMapID { - bets(): sc.ArrayOfMutableBet { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBets], wasmlib.TYPE_ARRAY|wasmlib.TYPE_BYTES); - return new sc.ArrayOfMutableBet(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateBets], 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, sc.idxMap[sc.IdxStateLastWinningNumber]); + } playPeriod(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxStatePlayPeriod]); - } + return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxStatePlayPeriod]); + } roundNumber(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateRoundNumber]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateRoundNumber]); + } roundStartedAt(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxStateRoundStartedAt]); - } + return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxStateRoundStartedAt]); + } roundStatus(): wasmlib.ScMutableInt16 { - return new wasmlib.ScMutableInt16(this.mapID, sc.idxMap[sc.IdxStateRoundStatus]); - } + return new wasmlib.ScMutableInt16(this.mapID, sc.idxMap[sc.IdxStateRoundStatus]); + } } diff --git a/contracts/wasm/fairroulette/ts/fairroulette/structs.ts b/contracts/wasm/fairroulette/ts/fairroulette/structs.ts index 4f5e2d41ed..a0c749f141 100644 --- a/contracts/wasm/fairroulette/ts/fairroulette/structs.ts +++ b/contracts/wasm/fairroulette/ts/fairroulette/structs.ts @@ -5,12 +5,12 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export class Bet { - amount: i64 = 0; - better: wasmlib.ScAgentID = new wasmlib.ScAgentID(); - number: i64 = 0; + amount : i64 = 0; + better : wasmlib.ScAgentID = new wasmlib.ScAgentID(); + number : i64 = 0; static fromBytes(bytes: u8[]): Bet { let decode = new wasmlib.BytesDecoder(bytes); @@ -24,9 +24,9 @@ export class Bet { bytes(): u8[] { return new wasmlib.BytesEncoder(). - int64(this.amount). - agentID(this.better). - int64(this.number). + int64(this.amount). + agentID(this.better). + int64(this.number). data(); } } @@ -45,7 +45,7 @@ export class ImmutableBet { } value(): Bet { - return Bet.fromBytes(wasmlib.getBytes(this.objID, this.keyID,wasmlib. TYPE_BYTES)); + return Bet.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); } } @@ -58,6 +58,10 @@ export class MutableBet { 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); } @@ -67,6 +71,6 @@ export class MutableBet { } value(): Bet { - return Bet.fromBytes(wasmlib.getBytes(this.objID, this.keyID,wasmlib. TYPE_BYTES)); + return Bet.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); } } diff --git a/contracts/wasm/go_build.cmd b/contracts/wasm/go_build.cmd index feeee21a1b..69285a482e 100644 --- a/contracts/wasm/go_build.cmd +++ b/contracts/wasm/go_build.cmd @@ -1,6 +1,6 @@ @echo off cd %1 -if not exist schema.yaml goto :xit +if not exist schema.yaml if not exist schema.json goto :xit echo Building %1 schema -go %2 echo compiling %1_go.wasm diff --git a/contracts/wasm/helloworld/go/helloworld/consts.go b/contracts/wasm/helloworld/go/helloworld/consts.go index 8a2c2473ee..bb14625014 100644 --- a/contracts/wasm/helloworld/go/helloworld/consts.go +++ b/contracts/wasm/helloworld/go/helloworld/consts.go @@ -15,7 +15,9 @@ const ( HScName = wasmlib.ScHname(0x0683223c) ) -const ResultHelloWorld = wasmlib.Key("helloWorld") +const ( + ResultHelloWorld = "helloWorld" +) const ( FuncHelloWorld = "helloWorld" diff --git a/contracts/wasm/helloworld/go/helloworld/keys.go b/contracts/wasm/helloworld/go/helloworld/keys.go index cfb0975574..149a75fad1 100644 --- a/contracts/wasm/helloworld/go/helloworld/keys.go +++ b/contracts/wasm/helloworld/go/helloworld/keys.go @@ -9,7 +9,9 @@ package helloworld import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" -const IdxResultHelloWorld = 0 +const ( + IdxResultHelloWorld = 0 +) const keyMapLen = 1 diff --git a/contracts/wasm/helloworld/src/consts.rs b/contracts/wasm/helloworld/src/consts.rs index bf53414060..e875648233 100644 --- a/contracts/wasm/helloworld/src/consts.rs +++ b/contracts/wasm/helloworld/src/consts.rs @@ -5,22 +5,18 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; -pub const SC_NAME: &str = "helloworld"; -pub const SC_DESCRIPTION: &str = "The ubiquitous hello world demo"; -pub const HSC_NAME: ScHname = ScHname(0x0683223c); - -pub const RESULT_HELLO_WORLD: &str = "helloWorld"; +pub const SC_NAME : &str = "helloworld"; +pub const SC_DESCRIPTION : &str = "The ubiquitous hello world demo"; +pub const HSC_NAME : ScHname = ScHname(0x0683223c); -pub const FUNC_HELLO_WORLD: &str = "helloWorld"; -pub const VIEW_GET_HELLO_WORLD: &str = "getHelloWorld"; +pub const RESULT_HELLO_WORLD : &str = "helloWorld"; -pub const HFUNC_HELLO_WORLD: ScHname = ScHname(0x9d042e65); -pub const HVIEW_GET_HELLO_WORLD: ScHname = ScHname(0x210439ce); +pub const FUNC_HELLO_WORLD : &str = "helloWorld"; +pub const VIEW_GET_HELLO_WORLD : &str = "getHelloWorld"; -// @formatter:on +pub const HFUNC_HELLO_WORLD : ScHname = ScHname(0x9d042e65); +pub const HVIEW_GET_HELLO_WORLD : ScHname = ScHname(0x210439ce); diff --git a/contracts/wasm/helloworld/src/contract.rs b/contracts/wasm/helloworld/src/contract.rs index 1a1534a38f..ca5b365fd9 100644 --- a/contracts/wasm/helloworld/src/contract.rs +++ b/contracts/wasm/helloworld/src/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -17,12 +15,12 @@ use crate::consts::*; use crate::results::*; pub struct HelloWorldCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct GetHelloWorldCall { - pub func: ScView, - pub results: ImmutableGetHelloWorldResults, + pub func: ScView, + pub results: ImmutableGetHelloWorldResults, } pub struct ScFuncs { @@ -34,14 +32,13 @@ impl ScFuncs { func: ScFunc::new(HSC_NAME, HFUNC_HELLO_WORLD), } } + pub fn get_hello_world(_ctx: & dyn ScViewCallContext) -> GetHelloWorldCall { let mut f = GetHelloWorldCall { - func: ScView::new(HSC_NAME, HVIEW_GET_HELLO_WORLD), + func: ScView::new(HSC_NAME, HVIEW_GET_HELLO_WORLD), results: ImmutableGetHelloWorldResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/contracts/wasm/helloworld/src/keys.rs b/contracts/wasm/helloworld/src/keys.rs index f536b56688..468a469a19 100644 --- a/contracts/wasm/helloworld/src/keys.rs +++ b/contracts/wasm/helloworld/src/keys.rs @@ -5,20 +5,20 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use crate::*; -pub(crate) const IDX_RESULT_HELLO_WORLD: usize = 0; + +pub(crate) const IDX_RESULT_HELLO_WORLD : usize = 0; + pub const KEY_MAP_LEN: usize = 1; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ - RESULT_HELLO_WORLD, + RESULT_HELLO_WORLD, ]; pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; @@ -28,5 +28,3 @@ pub fn idx_map(idx: usize) -> Key32 { IDX_MAP[idx] } } - -// @formatter:on diff --git a/contracts/wasm/helloworld/src/lib.rs b/contracts/wasm/helloworld/src/lib.rs index 931b312fdf..80bb927a85 100644 --- a/contracts/wasm/helloworld/src/lib.rs +++ b/contracts/wasm/helloworld/src/lib.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] #![allow(unused_imports)] @@ -29,7 +27,7 @@ mod helloworld; #[no_mangle] fn on_load() { let exports = ScExports::new(); - exports.add_func(FUNC_HELLO_WORLD, func_hello_world_thunk); + exports.add_func(FUNC_HELLO_WORLD, func_hello_world_thunk); exports.add_view(VIEW_GET_HELLO_WORLD, view_get_hello_world_thunk); unsafe { @@ -40,37 +38,35 @@ fn on_load() { } pub struct HelloWorldContext { - state: MutableHelloWorldState, + state: MutableHelloWorldState, } fn func_hello_world_thunk(ctx: &ScFuncContext) { - ctx.log("helloworld.funcHelloWorld"); - let f = HelloWorldContext { - state: MutableHelloWorldState { - id: OBJ_ID_STATE, - }, - }; - func_hello_world(ctx, &f); - ctx.log("helloworld.funcHelloWorld ok"); + ctx.log("helloworld.funcHelloWorld"); + let f = HelloWorldContext { + state: MutableHelloWorldState { + id: OBJ_ID_STATE, + }, + }; + func_hello_world(ctx, &f); + ctx.log("helloworld.funcHelloWorld ok"); } pub struct GetHelloWorldContext { - results: MutableGetHelloWorldResults, - state: ImmutableHelloWorldState, + results: MutableGetHelloWorldResults, + state: ImmutableHelloWorldState, } fn view_get_hello_world_thunk(ctx: &ScViewContext) { - ctx.log("helloworld.viewGetHelloWorld"); - let f = GetHelloWorldContext { - results: MutableGetHelloWorldResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableHelloWorldState { - id: OBJ_ID_STATE, - }, - }; - view_get_hello_world(ctx, &f); - ctx.log("helloworld.viewGetHelloWorld ok"); + ctx.log("helloworld.viewGetHelloWorld"); + let f = GetHelloWorldContext { + results: MutableGetHelloWorldResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableHelloWorldState { + id: OBJ_ID_STATE, + }, + }; + view_get_hello_world(ctx, &f); + ctx.log("helloworld.viewGetHelloWorld ok"); } - -// @formatter:on diff --git a/contracts/wasm/helloworld/src/results.rs b/contracts/wasm/helloworld/src/results.rs index 295e6b726b..d17c7c68e5 100644 --- a/contracts/wasm/helloworld/src/results.rs +++ b/contracts/wasm/helloworld/src/results.rs @@ -21,8 +21,8 @@ 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, idx_map(IDX_RESULT_HELLO_WORLD)) + } } #[derive(Clone, Copy)] @@ -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, idx_map(IDX_RESULT_HELLO_WORLD)) + } } diff --git a/contracts/wasm/helloworld/test/helloworld_bg.wasm b/contracts/wasm/helloworld/test/helloworld_bg.wasm index 8af77e238c..b31d3d581c 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/consts.ts b/contracts/wasm/helloworld/ts/helloworld/consts.ts index d93bd75a35..d52c7a618a 100644 --- a/contracts/wasm/helloworld/ts/helloworld/consts.ts +++ b/contracts/wasm/helloworld/ts/helloworld/consts.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export const ScName = "helloworld"; export const ScDescription = "The ubiquitous hello world demo"; diff --git a/contracts/wasm/helloworld/ts/helloworld/contract.ts b/contracts/wasm/helloworld/ts/helloworld/contract.ts index ac9276f39a..3740f30ca3 100644 --- a/contracts/wasm/helloworld/ts/helloworld/contract.ts +++ b/contracts/wasm/helloworld/ts/helloworld/contract.ts @@ -5,32 +5,30 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class HelloWorldCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncHelloWorld); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncHelloWorld); } export class HelloWorldContext { - state: sc.MutableHelloWorldState = new sc.MutableHelloWorldState(); + state: sc.MutableHelloWorldState = new sc.MutableHelloWorldState(); } export class GetHelloWorldCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetHelloWorld); - results: sc.ImmutableGetHelloWorldResults = new sc.ImmutableGetHelloWorldResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetHelloWorld); + results: sc.ImmutableGetHelloWorldResults = new sc.ImmutableGetHelloWorldResults(); } export class GetHelloWorldContext { - results: sc.MutableGetHelloWorldResults = new sc.MutableGetHelloWorldResults(); - state: sc.ImmutableHelloWorldState = new sc.ImmutableHelloWorldState(); + results: sc.MutableGetHelloWorldResults = new sc.MutableGetHelloWorldResults(); + state: sc.ImmutableHelloWorldState = new sc.ImmutableHelloWorldState(); } export class ScFuncs { - static helloWorld(ctx: wasmlib.ScFuncCallContext): HelloWorldCall { - let f = new HelloWorldCall(); - return f; + return new HelloWorldCall(); } static getHelloWorld(ctx: wasmlib.ScViewCallContext): GetHelloWorldCall { diff --git a/contracts/wasm/helloworld/ts/helloworld/keys.ts b/contracts/wasm/helloworld/ts/helloworld/keys.ts index b8d49c07ea..7fb73b33ec 100644 --- a/contracts/wasm/helloworld/ts/helloworld/keys.ts +++ b/contracts/wasm/helloworld/ts/helloworld/keys.ts @@ -5,13 +5,15 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; + export const IdxResultHelloWorld = 0; + export let keyMap: string[] = [ - sc.ResultHelloWorld, + sc.ResultHelloWorld, ]; export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/helloworld/ts/helloworld/lib.ts b/contracts/wasm/helloworld/ts/helloworld/lib.ts index be19e8e7dc..c70f64e037 100644 --- a/contracts/wasm/helloworld/ts/helloworld/lib.ts +++ b/contracts/wasm/helloworld/ts/helloworld/lib.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export function on_call(index: i32): void { @@ -14,7 +14,7 @@ export function on_call(index: i32): void { export function on_load(): void { let exports = new wasmlib.ScExports(); - exports.addFunc(sc.FuncHelloWorld, funcHelloWorldThunk); + exports.addFunc(sc.FuncHelloWorld, funcHelloWorldThunk); exports.addView(sc.ViewGetHelloWorld, viewGetHelloWorldThunk); for (let i = 0; i < sc.keyMap.length; i++) { @@ -23,18 +23,18 @@ export function on_load(): void { } function funcHelloWorldThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("helloworld.funcHelloWorld"); - let f = new sc.HelloWorldContext(); + ctx.log("helloworld.funcHelloWorld"); + let f = new sc.HelloWorldContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcHelloWorld(ctx, f); - ctx.log("helloworld.funcHelloWorld ok"); + sc.funcHelloWorld(ctx, f); + ctx.log("helloworld.funcHelloWorld ok"); } function viewGetHelloWorldThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("helloworld.viewGetHelloWorld"); - let f = new sc.GetHelloWorldContext(); + ctx.log("helloworld.viewGetHelloWorld"); + let f = new sc.GetHelloWorldContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewGetHelloWorld(ctx, f); - ctx.log("helloworld.viewGetHelloWorld ok"); + sc.viewGetHelloWorld(ctx, f); + ctx.log("helloworld.viewGetHelloWorld ok"); } diff --git a/contracts/wasm/helloworld/ts/helloworld/results.ts b/contracts/wasm/helloworld/ts/helloworld/results.ts index 2497774190..8af55ab264 100644 --- a/contracts/wasm/helloworld/ts/helloworld/results.ts +++ b/contracts/wasm/helloworld/ts/helloworld/results.ts @@ -5,19 +5,17 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxResultHelloWorld]); + } } 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, sc.idxMap[sc.IdxResultHelloWorld]); + } } diff --git a/contracts/wasm/helloworld/ts/helloworld/state.ts b/contracts/wasm/helloworld/ts/helloworld/state.ts index 2fc69e22f8..d8026bdce6 100644 --- a/contracts/wasm/helloworld/ts/helloworld/state.ts +++ b/contracts/wasm/helloworld/ts/helloworld/state.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ImmutableHelloWorldState extends wasmlib.ScMapID { diff --git a/contracts/wasm/inccounter/go/inccounter/consts.go b/contracts/wasm/inccounter/go/inccounter/consts.go index 9b4c883fa5..86b738973e 100644 --- a/contracts/wasm/inccounter/go/inccounter/consts.go +++ b/contracts/wasm/inccounter/go/inccounter/consts.go @@ -10,22 +10,25 @@ package inccounter import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" const ( - ScName = "inccounter" - HScName = wasmlib.ScHname(0xaf2438e9) + ScName = "inccounter" + ScDescription = "" + HScName = wasmlib.ScHname(0xaf2438e9) ) const ( - ParamCounter = wasmlib.Key("counter") - ParamDelay = wasmlib.Key("delay") - ParamDummy = wasmlib.Key("dummy") - ParamNumRepeats = wasmlib.Key("numRepeats") + ParamCounter = "counter" + ParamDelay = "delay" + ParamDummy = "dummy" + ParamNumRepeats = "numRepeats" ) -const ResultCounter = wasmlib.Key("counter") +const ( + ResultCounter = "counter" +) const ( - StateCounter = wasmlib.Key("counter") - StateNumRepeats = wasmlib.Key("numRepeats") + StateCounter = "counter" + StateNumRepeats = "numRepeats" ) const ( diff --git a/contracts/wasm/inccounter/go/inccounter/keys.go b/contracts/wasm/inccounter/go/inccounter/keys.go index 47800369d6..1741cdd8f9 100644 --- a/contracts/wasm/inccounter/go/inccounter/keys.go +++ b/contracts/wasm/inccounter/go/inccounter/keys.go @@ -14,7 +14,9 @@ const ( IdxParamDelay = 1 IdxParamDummy = 2 IdxParamNumRepeats = 3 - IdxResultCounter = 4 + + IdxResultCounter = 4 + IdxStateCounter = 5 IdxStateNumRepeats = 6 ) diff --git a/contracts/wasm/inccounter/src/consts.rs b/contracts/wasm/inccounter/src/consts.rs index c39d066e5f..e1590fc5ba 100644 --- a/contracts/wasm/inccounter/src/consts.rs +++ b/contracts/wasm/inccounter/src/consts.rs @@ -5,53 +5,50 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; -pub const SC_NAME: &str = "inccounter"; -pub const HSC_NAME: ScHname = ScHname(0xaf2438e9); - -pub const PARAM_COUNTER: &str = "counter"; -pub const PARAM_DELAY: &str = "delay"; -pub const PARAM_DUMMY: &str = "dummy"; -pub const PARAM_NUM_REPEATS: &str = "numRepeats"; - -pub const RESULT_COUNTER: &str = "counter"; - -pub const STATE_COUNTER: &str = "counter"; -pub const STATE_NUM_REPEATS: &str = "numRepeats"; - -pub const FUNC_CALL_INCREMENT: &str = "callIncrement"; -pub const FUNC_CALL_INCREMENT_RECURSE5X: &str = "callIncrementRecurse5x"; -pub const FUNC_ENDLESS_LOOP: &str = "endlessLoop"; -pub const FUNC_INCREMENT: &str = "increment"; -pub const FUNC_INCREMENT_WITH_DELAY: &str = "incrementWithDelay"; -pub const FUNC_INIT: &str = "init"; -pub const FUNC_LOCAL_STATE_INTERNAL_CALL: &str = "localStateInternalCall"; -pub const FUNC_LOCAL_STATE_POST: &str = "localStatePost"; -pub const FUNC_LOCAL_STATE_SANDBOX_CALL: &str = "localStateSandboxCall"; -pub const FUNC_POST_INCREMENT: &str = "postIncrement"; -pub const FUNC_REPEAT_MANY: &str = "repeatMany"; -pub const FUNC_TEST_LEB128: &str = "testLeb128"; -pub const FUNC_WHEN_MUST_INCREMENT: &str = "whenMustIncrement"; -pub const VIEW_GET_COUNTER: &str = "getCounter"; - -pub const HFUNC_CALL_INCREMENT: ScHname = ScHname(0xeb5dcacd); -pub const HFUNC_CALL_INCREMENT_RECURSE5X: ScHname = ScHname(0x8749fbff); -pub const HFUNC_ENDLESS_LOOP: ScHname = ScHname(0x365f0929); -pub const HFUNC_INCREMENT: ScHname = ScHname(0xd351bd12); -pub const HFUNC_INCREMENT_WITH_DELAY: ScHname = ScHname(0xa235bba7); -pub const HFUNC_INIT: ScHname = ScHname(0x1f44d644); -pub const HFUNC_LOCAL_STATE_INTERNAL_CALL: ScHname = ScHname(0xecfc5d33); -pub const HFUNC_LOCAL_STATE_POST: ScHname = ScHname(0x3fd54d13); -pub const HFUNC_LOCAL_STATE_SANDBOX_CALL: ScHname = ScHname(0x7bd22c53); -pub const HFUNC_POST_INCREMENT: ScHname = ScHname(0x81c772f5); -pub const HFUNC_REPEAT_MANY: ScHname = ScHname(0x4ff450d3); -pub const HFUNC_TEST_LEB128: ScHname = ScHname(0xd8364cb9); -pub const HFUNC_WHEN_MUST_INCREMENT: ScHname = ScHname(0xb4c3e7a6); -pub const HVIEW_GET_COUNTER: ScHname = ScHname(0xb423e607); - -// @formatter:on +pub const SC_NAME : &str = "inccounter"; +pub const SC_DESCRIPTION : &str = ""; +pub const HSC_NAME : ScHname = ScHname(0xaf2438e9); + +pub const PARAM_COUNTER : &str = "counter"; +pub const PARAM_DELAY : &str = "delay"; +pub const PARAM_DUMMY : &str = "dummy"; +pub const PARAM_NUM_REPEATS : &str = "numRepeats"; + +pub const RESULT_COUNTER : &str = "counter"; + +pub const STATE_COUNTER : &str = "counter"; +pub const STATE_NUM_REPEATS : &str = "numRepeats"; + +pub const FUNC_CALL_INCREMENT : &str = "callIncrement"; +pub const FUNC_CALL_INCREMENT_RECURSE5X : &str = "callIncrementRecurse5x"; +pub const FUNC_ENDLESS_LOOP : &str = "endlessLoop"; +pub const FUNC_INCREMENT : &str = "increment"; +pub const FUNC_INCREMENT_WITH_DELAY : &str = "incrementWithDelay"; +pub const FUNC_INIT : &str = "init"; +pub const FUNC_LOCAL_STATE_INTERNAL_CALL : &str = "localStateInternalCall"; +pub const FUNC_LOCAL_STATE_POST : &str = "localStatePost"; +pub const FUNC_LOCAL_STATE_SANDBOX_CALL : &str = "localStateSandboxCall"; +pub const FUNC_POST_INCREMENT : &str = "postIncrement"; +pub const FUNC_REPEAT_MANY : &str = "repeatMany"; +pub const FUNC_TEST_LEB128 : &str = "testLeb128"; +pub const FUNC_WHEN_MUST_INCREMENT : &str = "whenMustIncrement"; +pub const VIEW_GET_COUNTER : &str = "getCounter"; + +pub const HFUNC_CALL_INCREMENT : ScHname = ScHname(0xeb5dcacd); +pub const HFUNC_CALL_INCREMENT_RECURSE5X : ScHname = ScHname(0x8749fbff); +pub const HFUNC_ENDLESS_LOOP : ScHname = ScHname(0x365f0929); +pub const HFUNC_INCREMENT : ScHname = ScHname(0xd351bd12); +pub const HFUNC_INCREMENT_WITH_DELAY : ScHname = ScHname(0xa235bba7); +pub const HFUNC_INIT : ScHname = ScHname(0x1f44d644); +pub const HFUNC_LOCAL_STATE_INTERNAL_CALL : ScHname = ScHname(0xecfc5d33); +pub const HFUNC_LOCAL_STATE_POST : ScHname = ScHname(0x3fd54d13); +pub const HFUNC_LOCAL_STATE_SANDBOX_CALL : ScHname = ScHname(0x7bd22c53); +pub const HFUNC_POST_INCREMENT : ScHname = ScHname(0x81c772f5); +pub const HFUNC_REPEAT_MANY : ScHname = ScHname(0x4ff450d3); +pub const HFUNC_TEST_LEB128 : ScHname = ScHname(0xd8364cb9); +pub const HFUNC_WHEN_MUST_INCREMENT : ScHname = ScHname(0xb4c3e7a6); +pub const HVIEW_GET_COUNTER : ScHname = ScHname(0xb423e607); diff --git a/contracts/wasm/inccounter/src/contract.rs b/contracts/wasm/inccounter/src/contract.rs index d716771803..5f5c59845c 100644 --- a/contracts/wasm/inccounter/src/contract.rs +++ b/contracts/wasm/inccounter/src/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -18,64 +16,64 @@ use crate::params::*; use crate::results::*; pub struct CallIncrementCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct CallIncrementRecurse5xCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct EndlessLoopCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct IncrementCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct IncrementWithDelayCall { - pub func: ScFunc, - pub params: MutableIncrementWithDelayParams, + pub func: ScFunc, + pub params: MutableIncrementWithDelayParams, } pub struct InitCall { - pub func: ScInitFunc, - pub params: MutableInitParams, + pub func: ScInitFunc, + pub params: MutableInitParams, } pub struct LocalStateInternalCallCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct LocalStatePostCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct LocalStateSandboxCallCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct PostIncrementCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct RepeatManyCall { - pub func: ScFunc, - pub params: MutableRepeatManyParams, + pub func: ScFunc, + pub params: MutableRepeatManyParams, } pub struct TestLeb128Call { - pub func: ScFunc, + pub func: ScFunc, } pub struct WhenMustIncrementCall { - pub func: ScFunc, - pub params: MutableWhenMustIncrementParams, + pub func: ScFunc, + pub params: MutableWhenMustIncrementParams, } pub struct GetCounterCall { - pub func: ScView, - pub results: ImmutableGetCounterResults, + pub func: ScView, + pub results: ImmutableGetCounterResults, } pub struct ScFuncs { @@ -87,86 +85,97 @@ impl ScFuncs { func: ScFunc::new(HSC_NAME, HFUNC_CALL_INCREMENT), } } + pub fn call_increment_recurse5x(_ctx: & dyn ScFuncCallContext) -> CallIncrementRecurse5xCall { CallIncrementRecurse5xCall { func: ScFunc::new(HSC_NAME, HFUNC_CALL_INCREMENT_RECURSE5X), } } + pub fn endless_loop(_ctx: & dyn ScFuncCallContext) -> EndlessLoopCall { EndlessLoopCall { func: ScFunc::new(HSC_NAME, HFUNC_ENDLESS_LOOP), } } + pub fn increment(_ctx: & dyn ScFuncCallContext) -> IncrementCall { IncrementCall { func: ScFunc::new(HSC_NAME, HFUNC_INCREMENT), } } + pub fn increment_with_delay(_ctx: & dyn ScFuncCallContext) -> IncrementWithDelayCall { let mut f = IncrementWithDelayCall { - func: ScFunc::new(HSC_NAME, HFUNC_INCREMENT_WITH_DELAY), + func: ScFunc::new(HSC_NAME, HFUNC_INCREMENT_WITH_DELAY), params: MutableIncrementWithDelayParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn init(_ctx: & dyn ScFuncCallContext) -> InitCall { let mut f = InitCall { - func: ScInitFunc::new(HSC_NAME, HFUNC_INIT), + func: ScInitFunc::new(HSC_NAME, HFUNC_INIT), params: MutableInitParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn local_state_internal_call(_ctx: & dyn ScFuncCallContext) -> LocalStateInternalCallCall { LocalStateInternalCallCall { func: ScFunc::new(HSC_NAME, HFUNC_LOCAL_STATE_INTERNAL_CALL), } } + pub fn local_state_post(_ctx: & dyn ScFuncCallContext) -> LocalStatePostCall { LocalStatePostCall { func: ScFunc::new(HSC_NAME, HFUNC_LOCAL_STATE_POST), } } + pub fn local_state_sandbox_call(_ctx: & dyn ScFuncCallContext) -> LocalStateSandboxCallCall { LocalStateSandboxCallCall { func: ScFunc::new(HSC_NAME, HFUNC_LOCAL_STATE_SANDBOX_CALL), } } + pub fn post_increment(_ctx: & dyn ScFuncCallContext) -> PostIncrementCall { PostIncrementCall { func: ScFunc::new(HSC_NAME, HFUNC_POST_INCREMENT), } } + pub fn repeat_many(_ctx: & dyn ScFuncCallContext) -> RepeatManyCall { let mut f = RepeatManyCall { - func: ScFunc::new(HSC_NAME, HFUNC_REPEAT_MANY), + func: ScFunc::new(HSC_NAME, HFUNC_REPEAT_MANY), params: MutableRepeatManyParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn test_leb128(_ctx: & dyn ScFuncCallContext) -> TestLeb128Call { TestLeb128Call { func: ScFunc::new(HSC_NAME, HFUNC_TEST_LEB128), } } + pub fn when_must_increment(_ctx: & dyn ScFuncCallContext) -> WhenMustIncrementCall { let mut f = WhenMustIncrementCall { - func: ScFunc::new(HSC_NAME, HFUNC_WHEN_MUST_INCREMENT), + func: ScFunc::new(HSC_NAME, HFUNC_WHEN_MUST_INCREMENT), params: MutableWhenMustIncrementParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn get_counter(_ctx: & dyn ScViewCallContext) -> GetCounterCall { let mut f = GetCounterCall { - func: ScView::new(HSC_NAME, HVIEW_GET_COUNTER), + func: ScView::new(HSC_NAME, HVIEW_GET_COUNTER), results: ImmutableGetCounterResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/contracts/wasm/inccounter/src/keys.rs b/contracts/wasm/inccounter/src/keys.rs index 8cf9bce6bf..cdbc2c396b 100644 --- a/contracts/wasm/inccounter/src/keys.rs +++ b/contracts/wasm/inccounter/src/keys.rs @@ -5,32 +5,32 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use crate::*; -pub(crate) const IDX_PARAM_COUNTER: usize = 0; -pub(crate) const IDX_PARAM_DELAY: usize = 1; -pub(crate) const IDX_PARAM_DUMMY: usize = 2; -pub(crate) const IDX_PARAM_NUM_REPEATS: usize = 3; -pub(crate) const IDX_RESULT_COUNTER: usize = 4; -pub(crate) const IDX_STATE_COUNTER: usize = 5; -pub(crate) const IDX_STATE_NUM_REPEATS: usize = 6; +pub(crate) const IDX_PARAM_COUNTER : usize = 0; +pub(crate) const IDX_PARAM_DELAY : usize = 1; +pub(crate) const IDX_PARAM_DUMMY : usize = 2; +pub(crate) const IDX_PARAM_NUM_REPEATS : usize = 3; + +pub(crate) const IDX_RESULT_COUNTER : usize = 4; + +pub(crate) const IDX_STATE_COUNTER : usize = 5; +pub(crate) const IDX_STATE_NUM_REPEATS : usize = 6; pub const KEY_MAP_LEN: usize = 7; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ - PARAM_COUNTER, - PARAM_DELAY, - PARAM_DUMMY, - PARAM_NUM_REPEATS, - RESULT_COUNTER, - STATE_COUNTER, - STATE_NUM_REPEATS, + PARAM_COUNTER, + PARAM_DELAY, + PARAM_DUMMY, + PARAM_NUM_REPEATS, + RESULT_COUNTER, + STATE_COUNTER, + STATE_NUM_REPEATS, ]; pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; @@ -40,5 +40,3 @@ pub fn idx_map(idx: usize) -> Key32 { IDX_MAP[idx] } } - -// @formatter:on diff --git a/contracts/wasm/inccounter/src/lib.rs b/contracts/wasm/inccounter/src/lib.rs index 9b7e552473..e29777eda3 100644 --- a/contracts/wasm/inccounter/src/lib.rs +++ b/contracts/wasm/inccounter/src/lib.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] #![allow(unused_imports)] @@ -31,20 +29,20 @@ mod inccounter; #[no_mangle] fn on_load() { let exports = ScExports::new(); - exports.add_func(FUNC_CALL_INCREMENT, func_call_increment_thunk); - exports.add_func(FUNC_CALL_INCREMENT_RECURSE5X, func_call_increment_recurse5x_thunk); - exports.add_func(FUNC_ENDLESS_LOOP, func_endless_loop_thunk); - exports.add_func(FUNC_INCREMENT, func_increment_thunk); - exports.add_func(FUNC_INCREMENT_WITH_DELAY, func_increment_with_delay_thunk); - exports.add_func(FUNC_INIT, func_init_thunk); + exports.add_func(FUNC_CALL_INCREMENT, func_call_increment_thunk); + exports.add_func(FUNC_CALL_INCREMENT_RECURSE5X, func_call_increment_recurse5x_thunk); + exports.add_func(FUNC_ENDLESS_LOOP, func_endless_loop_thunk); + exports.add_func(FUNC_INCREMENT, func_increment_thunk); + exports.add_func(FUNC_INCREMENT_WITH_DELAY, func_increment_with_delay_thunk); + exports.add_func(FUNC_INIT, func_init_thunk); exports.add_func(FUNC_LOCAL_STATE_INTERNAL_CALL, func_local_state_internal_call_thunk); - exports.add_func(FUNC_LOCAL_STATE_POST, func_local_state_post_thunk); - exports.add_func(FUNC_LOCAL_STATE_SANDBOX_CALL, func_local_state_sandbox_call_thunk); - exports.add_func(FUNC_POST_INCREMENT, func_post_increment_thunk); - exports.add_func(FUNC_REPEAT_MANY, func_repeat_many_thunk); - exports.add_func(FUNC_TEST_LEB128, func_test_leb128_thunk); - exports.add_func(FUNC_WHEN_MUST_INCREMENT, func_when_must_increment_thunk); - exports.add_view(VIEW_GET_COUNTER, view_get_counter_thunk); + exports.add_func(FUNC_LOCAL_STATE_POST, func_local_state_post_thunk); + exports.add_func(FUNC_LOCAL_STATE_SANDBOX_CALL, func_local_state_sandbox_call_thunk); + exports.add_func(FUNC_POST_INCREMENT, func_post_increment_thunk); + exports.add_func(FUNC_REPEAT_MANY, func_repeat_many_thunk); + exports.add_func(FUNC_TEST_LEB128, func_test_leb128_thunk); + exports.add_func(FUNC_WHEN_MUST_INCREMENT, func_when_must_increment_thunk); + exports.add_view(VIEW_GET_COUNTER, view_get_counter_thunk); unsafe { for i in 0..KEY_MAP_LEN { @@ -54,234 +52,232 @@ fn on_load() { } pub struct CallIncrementContext { - state: MutableIncCounterState, + state: MutableIncCounterState, } fn func_call_increment_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcCallIncrement"); - let f = CallIncrementContext { - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_call_increment(ctx, &f); - ctx.log("inccounter.funcCallIncrement ok"); + ctx.log("inccounter.funcCallIncrement"); + let f = CallIncrementContext { + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_call_increment(ctx, &f); + ctx.log("inccounter.funcCallIncrement ok"); } pub struct CallIncrementRecurse5xContext { - state: MutableIncCounterState, + state: MutableIncCounterState, } fn func_call_increment_recurse5x_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcCallIncrementRecurse5x"); - let f = CallIncrementRecurse5xContext { - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_call_increment_recurse5x(ctx, &f); - ctx.log("inccounter.funcCallIncrementRecurse5x ok"); + ctx.log("inccounter.funcCallIncrementRecurse5x"); + let f = CallIncrementRecurse5xContext { + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_call_increment_recurse5x(ctx, &f); + ctx.log("inccounter.funcCallIncrementRecurse5x ok"); } pub struct EndlessLoopContext { - state: MutableIncCounterState, + state: MutableIncCounterState, } fn func_endless_loop_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcEndlessLoop"); - let f = EndlessLoopContext { - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_endless_loop(ctx, &f); - ctx.log("inccounter.funcEndlessLoop ok"); + ctx.log("inccounter.funcEndlessLoop"); + let f = EndlessLoopContext { + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_endless_loop(ctx, &f); + ctx.log("inccounter.funcEndlessLoop ok"); } pub struct IncrementContext { - state: MutableIncCounterState, + state: MutableIncCounterState, } fn func_increment_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcIncrement"); - let f = IncrementContext { - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_increment(ctx, &f); - ctx.log("inccounter.funcIncrement ok"); + ctx.log("inccounter.funcIncrement"); + let f = IncrementContext { + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_increment(ctx, &f); + ctx.log("inccounter.funcIncrement ok"); } pub struct IncrementWithDelayContext { - params: ImmutableIncrementWithDelayParams, - state: MutableIncCounterState, + params: ImmutableIncrementWithDelayParams, + state: MutableIncCounterState, } fn func_increment_with_delay_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcIncrementWithDelay"); - let f = IncrementWithDelayContext { - params: ImmutableIncrementWithDelayParams { - id: OBJ_ID_PARAMS, - }, - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.delay().exists(), "missing mandatory delay"); - func_increment_with_delay(ctx, &f); - ctx.log("inccounter.funcIncrementWithDelay ok"); + ctx.log("inccounter.funcIncrementWithDelay"); + let f = IncrementWithDelayContext { + params: ImmutableIncrementWithDelayParams { + id: OBJ_ID_PARAMS, + }, + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.delay().exists(), "missing mandatory delay"); + func_increment_with_delay(ctx, &f); + ctx.log("inccounter.funcIncrementWithDelay ok"); } pub struct InitContext { - params: ImmutableInitParams, - state: MutableIncCounterState, + params: ImmutableInitParams, + state: MutableIncCounterState, } fn func_init_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcInit"); - let f = InitContext { - params: ImmutableInitParams { - id: OBJ_ID_PARAMS, - }, - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_init(ctx, &f); - ctx.log("inccounter.funcInit ok"); + ctx.log("inccounter.funcInit"); + let f = InitContext { + params: ImmutableInitParams { + id: OBJ_ID_PARAMS, + }, + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_init(ctx, &f); + ctx.log("inccounter.funcInit ok"); } pub struct LocalStateInternalCallContext { - state: MutableIncCounterState, + state: MutableIncCounterState, } fn func_local_state_internal_call_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcLocalStateInternalCall"); - let f = LocalStateInternalCallContext { - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_local_state_internal_call(ctx, &f); - ctx.log("inccounter.funcLocalStateInternalCall ok"); + ctx.log("inccounter.funcLocalStateInternalCall"); + let f = LocalStateInternalCallContext { + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_local_state_internal_call(ctx, &f); + ctx.log("inccounter.funcLocalStateInternalCall ok"); } pub struct LocalStatePostContext { - state: MutableIncCounterState, + state: MutableIncCounterState, } fn func_local_state_post_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcLocalStatePost"); - let f = LocalStatePostContext { - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_local_state_post(ctx, &f); - ctx.log("inccounter.funcLocalStatePost ok"); + ctx.log("inccounter.funcLocalStatePost"); + let f = LocalStatePostContext { + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_local_state_post(ctx, &f); + ctx.log("inccounter.funcLocalStatePost ok"); } pub struct LocalStateSandboxCallContext { - state: MutableIncCounterState, + state: MutableIncCounterState, } fn func_local_state_sandbox_call_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcLocalStateSandboxCall"); - let f = LocalStateSandboxCallContext { - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_local_state_sandbox_call(ctx, &f); - ctx.log("inccounter.funcLocalStateSandboxCall ok"); + ctx.log("inccounter.funcLocalStateSandboxCall"); + let f = LocalStateSandboxCallContext { + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_local_state_sandbox_call(ctx, &f); + ctx.log("inccounter.funcLocalStateSandboxCall ok"); } pub struct PostIncrementContext { - state: MutableIncCounterState, + state: MutableIncCounterState, } fn func_post_increment_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcPostIncrement"); - let f = PostIncrementContext { - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_post_increment(ctx, &f); - ctx.log("inccounter.funcPostIncrement ok"); + ctx.log("inccounter.funcPostIncrement"); + let f = PostIncrementContext { + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_post_increment(ctx, &f); + ctx.log("inccounter.funcPostIncrement ok"); } pub struct RepeatManyContext { - params: ImmutableRepeatManyParams, - state: MutableIncCounterState, + params: ImmutableRepeatManyParams, + state: MutableIncCounterState, } fn func_repeat_many_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcRepeatMany"); - let f = RepeatManyContext { - params: ImmutableRepeatManyParams { - id: OBJ_ID_PARAMS, - }, - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_repeat_many(ctx, &f); - ctx.log("inccounter.funcRepeatMany ok"); + ctx.log("inccounter.funcRepeatMany"); + let f = RepeatManyContext { + params: ImmutableRepeatManyParams { + id: OBJ_ID_PARAMS, + }, + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_repeat_many(ctx, &f); + ctx.log("inccounter.funcRepeatMany ok"); } pub struct TestLeb128Context { - state: MutableIncCounterState, + state: MutableIncCounterState, } fn func_test_leb128_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcTestLeb128"); - let f = TestLeb128Context { - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_test_leb128(ctx, &f); - ctx.log("inccounter.funcTestLeb128 ok"); + ctx.log("inccounter.funcTestLeb128"); + let f = TestLeb128Context { + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_test_leb128(ctx, &f); + ctx.log("inccounter.funcTestLeb128 ok"); } pub struct WhenMustIncrementContext { - params: ImmutableWhenMustIncrementParams, - state: MutableIncCounterState, + params: ImmutableWhenMustIncrementParams, + state: MutableIncCounterState, } fn func_when_must_increment_thunk(ctx: &ScFuncContext) { - ctx.log("inccounter.funcWhenMustIncrement"); - let f = WhenMustIncrementContext { - params: ImmutableWhenMustIncrementParams { - id: OBJ_ID_PARAMS, - }, - state: MutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - func_when_must_increment(ctx, &f); - ctx.log("inccounter.funcWhenMustIncrement ok"); + ctx.log("inccounter.funcWhenMustIncrement"); + let f = WhenMustIncrementContext { + params: ImmutableWhenMustIncrementParams { + id: OBJ_ID_PARAMS, + }, + state: MutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + func_when_must_increment(ctx, &f); + ctx.log("inccounter.funcWhenMustIncrement ok"); } pub struct GetCounterContext { - results: MutableGetCounterResults, - state: ImmutableIncCounterState, + results: MutableGetCounterResults, + state: ImmutableIncCounterState, } fn view_get_counter_thunk(ctx: &ScViewContext) { - ctx.log("inccounter.viewGetCounter"); - let f = GetCounterContext { - results: MutableGetCounterResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableIncCounterState { - id: OBJ_ID_STATE, - }, - }; - view_get_counter(ctx, &f); - ctx.log("inccounter.viewGetCounter ok"); + ctx.log("inccounter.viewGetCounter"); + let f = GetCounterContext { + results: MutableGetCounterResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableIncCounterState { + id: OBJ_ID_STATE, + }, + }; + view_get_counter(ctx, &f); + ctx.log("inccounter.viewGetCounter ok"); } - -// @formatter:on diff --git a/contracts/wasm/inccounter/src/params.rs b/contracts/wasm/inccounter/src/params.rs index 9bb39748fd..edcb169d0a 100644 --- a/contracts/wasm/inccounter/src/params.rs +++ b/contracts/wasm/inccounter/src/params.rs @@ -21,8 +21,8 @@ pub struct ImmutableIncrementWithDelayParams { impl ImmutableIncrementWithDelayParams { pub fn delay(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_DELAY)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_DELAY)) + } } #[derive(Clone, Copy)] @@ -32,8 +32,8 @@ pub struct MutableIncrementWithDelayParams { impl MutableIncrementWithDelayParams { pub fn delay(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_DELAY)) - } + ScMutableInt32::new(self.id, idx_map(IDX_PARAM_DELAY)) + } } #[derive(Clone, Copy)] @@ -43,8 +43,8 @@ pub struct ImmutableInitParams { impl ImmutableInitParams { pub fn counter(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_COUNTER)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_COUNTER)) + } } #[derive(Clone, Copy)] @@ -54,8 +54,8 @@ pub struct MutableInitParams { impl MutableInitParams { pub fn counter(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_COUNTER)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_COUNTER)) + } } #[derive(Clone, Copy)] @@ -65,8 +65,8 @@ 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, idx_map(IDX_PARAM_NUM_REPEATS)) + } } #[derive(Clone, Copy)] @@ -76,8 +76,8 @@ 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, idx_map(IDX_PARAM_NUM_REPEATS)) + } } #[derive(Clone, Copy)] @@ -87,8 +87,8 @@ pub struct ImmutableWhenMustIncrementParams { impl ImmutableWhenMustIncrementParams { pub fn dummy(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_DUMMY)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_DUMMY)) + } } #[derive(Clone, Copy)] @@ -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, idx_map(IDX_PARAM_DUMMY)) + } } diff --git a/contracts/wasm/inccounter/src/results.rs b/contracts/wasm/inccounter/src/results.rs index e0c8a90478..74b1aa5bdd 100644 --- a/contracts/wasm/inccounter/src/results.rs +++ b/contracts/wasm/inccounter/src/results.rs @@ -21,8 +21,8 @@ pub struct ImmutableGetCounterResults { impl ImmutableGetCounterResults { pub fn counter(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_COUNTER)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_COUNTER)) + } } #[derive(Clone, Copy)] @@ -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, idx_map(IDX_RESULT_COUNTER)) + } } diff --git a/contracts/wasm/inccounter/src/state.rs b/contracts/wasm/inccounter/src/state.rs index 76f83ab4b9..36d65f563f 100644 --- a/contracts/wasm/inccounter/src/state.rs +++ b/contracts/wasm/inccounter/src/state.rs @@ -21,12 +21,12 @@ pub struct ImmutableIncCounterState { impl ImmutableIncCounterState { pub fn counter(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) + } pub fn num_repeats(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_NUM_REPEATS)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_STATE_NUM_REPEATS)) + } } #[derive(Clone, Copy)] @@ -36,10 +36,10 @@ pub struct MutableIncCounterState { impl MutableIncCounterState { pub fn counter(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) - } + ScMutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) + } pub fn num_repeats(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_NUM_REPEATS)) - } + ScMutableInt64::new(self.id, idx_map(IDX_STATE_NUM_REPEATS)) + } } diff --git a/contracts/wasm/inccounter/test/inccounter_bg.wasm b/contracts/wasm/inccounter/test/inccounter_bg.wasm index bb828e396a..c577e6e18f 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/test/inccounter_test.go b/contracts/wasm/inccounter/test/inccounter_test.go index fc44b3f16a..0cae80b4ab 100644 --- a/contracts/wasm/inccounter/test/inccounter_test.go +++ b/contracts/wasm/inccounter/test/inccounter_test.go @@ -108,11 +108,6 @@ func TestIncrementLocalStateInternalCall(t *testing.T) { } func TestIncrementLocalStateSandboxCall(t *testing.T) { - // TODO need to save globals for TypeScript Wasm for this to succeed - if *wasmsolo.TsWasm { - t.SkipNow() - } - ctx := setupTest(t) localStateSandboxCall := inccounter.ScFuncs.LocalStateSandboxCall(ctx) @@ -131,11 +126,6 @@ func TestIncrementLocalStateSandboxCall(t *testing.T) { } func TestIncrementLocalStatePost(t *testing.T) { - // TODO need to save globals for TypeScript Wasm for this to succeed - if *wasmsolo.TsWasm { - t.SkipNow() - } - ctx := setupTest(t) localStatePost := inccounter.ScFuncs.LocalStatePost(ctx) @@ -163,35 +153,25 @@ func TestLeb128(t *testing.T) { testLeb128 := inccounter.ScFuncs.TestLeb128(ctx) testLeb128.Func.TransferIotas(1).Post() require.NoError(t, ctx.Err) - - //res, err := chain.CallView( - // ScName, wasmproc.ViewCopyAllState, - //) - //require.NoError(t, err) - //keys := make([]string, 0) - //for key := range res { - // keys = append(keys, string(key)) - //} - //sort.Strings(keys) - //for _, key := range keys { - // fmt.Printf("%s: %v\n", key, res[kv.Key(key)]) - //} } func TestLoop(t *testing.T) { - if *wasmsolo.GoDebug || wasmhost.DisableWasmTimeout { - // no timeout possible with WasmGoVM - // because goroutines cannot be killed + if *wasmsolo.GoDebug || *wasmsolo.GoWasmEdge { + // no timeout possible because goroutines cannot be killed + // or because there is no way to interrupt the Wasm code t.SkipNow() } ctx := setupTest(t) + save := wasmhost.DisableWasmTimeout + wasmhost.DisableWasmTimeout = false wasmhost.WasmTimeout = 1 * time.Second endlessLoop := inccounter.ScFuncs.EndlessLoop(ctx) endlessLoop.Func.TransferIotas(1).Post() require.Error(t, ctx.Err) require.Contains(t, ctx.Err.Error(), "interrupt") + wasmhost.DisableWasmTimeout = save inccounter.ScFuncs.Increment(ctx).Func.TransferIotas(1).Post() require.NoError(t, ctx.Err) diff --git a/contracts/wasm/inccounter/ts/inccounter/consts.ts b/contracts/wasm/inccounter/ts/inccounter/consts.ts index ef54d18fec..ca522a8a58 100644 --- a/contracts/wasm/inccounter/ts/inccounter/consts.ts +++ b/contracts/wasm/inccounter/ts/inccounter/consts.ts @@ -5,10 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; -export const ScName = "inccounter"; -export const HScName = new wasmlib.ScHname(0xaf2438e9); +export const ScName = "inccounter"; +export const ScDescription = ""; +export const HScName = new wasmlib.ScHname(0xaf2438e9); export const ParamCounter = "counter"; export const ParamDelay = "delay"; diff --git a/contracts/wasm/inccounter/ts/inccounter/contract.ts b/contracts/wasm/inccounter/ts/inccounter/contract.ts index 99b1df9558..497a9052cc 100644 --- a/contracts/wasm/inccounter/ts/inccounter/contract.ts +++ b/contracts/wasm/inccounter/ts/inccounter/contract.ts @@ -5,151 +5,146 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class CallIncrementCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncCallIncrement); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncCallIncrement); } export class CallIncrementContext { - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class CallIncrementRecurse5xCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncCallIncrementRecurse5x); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncCallIncrementRecurse5x); } export class CallIncrementRecurse5xContext { - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class EndlessLoopCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncEndlessLoop); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncEndlessLoop); } export class EndlessLoopContext { - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class IncrementCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncIncrement); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncIncrement); } export class IncrementContext { - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class IncrementWithDelayCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncIncrementWithDelay); - params: sc.MutableIncrementWithDelayParams = new sc.MutableIncrementWithDelayParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncIncrementWithDelay); + params: sc.MutableIncrementWithDelayParams = new sc.MutableIncrementWithDelayParams(); } export class IncrementWithDelayContext { - params: sc.ImmutableIncrementWithDelayParams = new sc.ImmutableIncrementWithDelayParams(); - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + params: sc.ImmutableIncrementWithDelayParams = new sc.ImmutableIncrementWithDelayParams(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class InitCall { - func: wasmlib.ScInitFunc = new wasmlib.ScInitFunc(sc.HScName, sc.HFuncInit); - params: sc.MutableInitParams = new sc.MutableInitParams(); + func: wasmlib.ScInitFunc = new wasmlib.ScInitFunc(sc.HScName, sc.HFuncInit); + params: sc.MutableInitParams = new sc.MutableInitParams(); } export class InitContext { - params: sc.ImmutableInitParams = new sc.ImmutableInitParams(); - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + params: sc.ImmutableInitParams = new sc.ImmutableInitParams(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class LocalStateInternalCallCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncLocalStateInternalCall); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncLocalStateInternalCall); } export class LocalStateInternalCallContext { - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class LocalStatePostCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncLocalStatePost); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncLocalStatePost); } export class LocalStatePostContext { - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class LocalStateSandboxCallCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncLocalStateSandboxCall); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncLocalStateSandboxCall); } export class LocalStateSandboxCallContext { - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class PostIncrementCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPostIncrement); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPostIncrement); } export class PostIncrementContext { - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class RepeatManyCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncRepeatMany); - params: sc.MutableRepeatManyParams = new sc.MutableRepeatManyParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncRepeatMany); + params: sc.MutableRepeatManyParams = new sc.MutableRepeatManyParams(); } export class RepeatManyContext { - params: sc.ImmutableRepeatManyParams = new sc.ImmutableRepeatManyParams(); - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + params: sc.ImmutableRepeatManyParams = new sc.ImmutableRepeatManyParams(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class TestLeb128Call { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestLeb128); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestLeb128); } export class TestLeb128Context { - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class WhenMustIncrementCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncWhenMustIncrement); - params: sc.MutableWhenMustIncrementParams = new sc.MutableWhenMustIncrementParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncWhenMustIncrement); + params: sc.MutableWhenMustIncrementParams = new sc.MutableWhenMustIncrementParams(); } export class WhenMustIncrementContext { - params: sc.ImmutableWhenMustIncrementParams = new sc.ImmutableWhenMustIncrementParams(); - state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); + params: sc.ImmutableWhenMustIncrementParams = new sc.ImmutableWhenMustIncrementParams(); + state: sc.MutableIncCounterState = new sc.MutableIncCounterState(); } export class GetCounterCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetCounter); - results: sc.ImmutableGetCounterResults = new sc.ImmutableGetCounterResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetCounter); + results: sc.ImmutableGetCounterResults = new sc.ImmutableGetCounterResults(); } export class GetCounterContext { - results: sc.MutableGetCounterResults = new sc.MutableGetCounterResults(); - state: sc.ImmutableIncCounterState = new sc.ImmutableIncCounterState(); + results: sc.MutableGetCounterResults = new sc.MutableGetCounterResults(); + state: sc.ImmutableIncCounterState = new sc.ImmutableIncCounterState(); } export class ScFuncs { - static callIncrement(ctx: wasmlib.ScFuncCallContext): CallIncrementCall { - let f = new CallIncrementCall(); - return f; + return new CallIncrementCall(); } static callIncrementRecurse5x(ctx: wasmlib.ScFuncCallContext): CallIncrementRecurse5xCall { - let f = new CallIncrementRecurse5xCall(); - return f; + return new CallIncrementRecurse5xCall(); } static endlessLoop(ctx: wasmlib.ScFuncCallContext): EndlessLoopCall { - let f = new EndlessLoopCall(); - return f; + return new EndlessLoopCall(); } static increment(ctx: wasmlib.ScFuncCallContext): IncrementCall { - let f = new IncrementCall(); - return f; + return new IncrementCall(); } static incrementWithDelay(ctx: wasmlib.ScFuncCallContext): IncrementWithDelayCall { @@ -165,23 +160,19 @@ export class ScFuncs { } static localStateInternalCall(ctx: wasmlib.ScFuncCallContext): LocalStateInternalCallCall { - let f = new LocalStateInternalCallCall(); - return f; + return new LocalStateInternalCallCall(); } static localStatePost(ctx: wasmlib.ScFuncCallContext): LocalStatePostCall { - let f = new LocalStatePostCall(); - return f; + return new LocalStatePostCall(); } static localStateSandboxCall(ctx: wasmlib.ScFuncCallContext): LocalStateSandboxCallCall { - let f = new LocalStateSandboxCallCall(); - return f; + return new LocalStateSandboxCallCall(); } static postIncrement(ctx: wasmlib.ScFuncCallContext): PostIncrementCall { - let f = new PostIncrementCall(); - return f; + return new PostIncrementCall(); } static repeatMany(ctx: wasmlib.ScFuncCallContext): RepeatManyCall { @@ -191,8 +182,7 @@ export class ScFuncs { } static testLeb128(ctx: wasmlib.ScFuncCallContext): TestLeb128Call { - let f = new TestLeb128Call(); - return f; + return new TestLeb128Call(); } static whenMustIncrement(ctx: wasmlib.ScFuncCallContext): WhenMustIncrementCall { diff --git a/contracts/wasm/inccounter/ts/inccounter/keys.ts b/contracts/wasm/inccounter/ts/inccounter/keys.ts index 6c9deca9bc..94e03bd1c1 100644 --- a/contracts/wasm/inccounter/ts/inccounter/keys.ts +++ b/contracts/wasm/inccounter/ts/inccounter/keys.ts @@ -5,25 +5,27 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export const IdxParamCounter = 0; export const IdxParamDelay = 1; export const IdxParamDummy = 2; export const IdxParamNumRepeats = 3; -export const IdxResultCounter = 4; + +export const IdxResultCounter = 4; + export const IdxStateCounter = 5; export const IdxStateNumRepeats = 6; export let keyMap: string[] = [ - sc.ParamCounter, - sc.ParamDelay, - sc.ParamDummy, - sc.ParamNumRepeats, - sc.ResultCounter, - sc.StateCounter, - sc.StateNumRepeats, + sc.ParamCounter, + sc.ParamDelay, + sc.ParamDummy, + sc.ParamNumRepeats, + sc.ResultCounter, + sc.StateCounter, + sc.StateNumRepeats, ]; export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/inccounter/ts/inccounter/lib.ts b/contracts/wasm/inccounter/ts/inccounter/lib.ts index 991f71f494..59d72dbea3 100644 --- a/contracts/wasm/inccounter/ts/inccounter/lib.ts +++ b/contracts/wasm/inccounter/ts/inccounter/lib.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export function on_call(index: i32): void { @@ -14,20 +14,20 @@ export function on_call(index: i32): void { export function on_load(): void { let exports = new wasmlib.ScExports(); - exports.addFunc(sc.FuncCallIncrement, funcCallIncrementThunk); + exports.addFunc(sc.FuncCallIncrement, funcCallIncrementThunk); exports.addFunc(sc.FuncCallIncrementRecurse5x, funcCallIncrementRecurse5xThunk); - exports.addFunc(sc.FuncEndlessLoop, funcEndlessLoopThunk); - exports.addFunc(sc.FuncIncrement, funcIncrementThunk); - exports.addFunc(sc.FuncIncrementWithDelay, funcIncrementWithDelayThunk); - exports.addFunc(sc.FuncInit, funcInitThunk); + exports.addFunc(sc.FuncEndlessLoop, funcEndlessLoopThunk); + exports.addFunc(sc.FuncIncrement, funcIncrementThunk); + exports.addFunc(sc.FuncIncrementWithDelay, funcIncrementWithDelayThunk); + exports.addFunc(sc.FuncInit, funcInitThunk); exports.addFunc(sc.FuncLocalStateInternalCall, funcLocalStateInternalCallThunk); - exports.addFunc(sc.FuncLocalStatePost, funcLocalStatePostThunk); - exports.addFunc(sc.FuncLocalStateSandboxCall, funcLocalStateSandboxCallThunk); - exports.addFunc(sc.FuncPostIncrement, funcPostIncrementThunk); - exports.addFunc(sc.FuncRepeatMany, funcRepeatManyThunk); - exports.addFunc(sc.FuncTestLeb128, funcTestLeb128Thunk); - exports.addFunc(sc.FuncWhenMustIncrement, funcWhenMustIncrementThunk); - exports.addView(sc.ViewGetCounter, viewGetCounterThunk); + exports.addFunc(sc.FuncLocalStatePost, funcLocalStatePostThunk); + exports.addFunc(sc.FuncLocalStateSandboxCall, funcLocalStateSandboxCallThunk); + exports.addFunc(sc.FuncPostIncrement, funcPostIncrementThunk); + exports.addFunc(sc.FuncRepeatMany, funcRepeatManyThunk); + exports.addFunc(sc.FuncTestLeb128, funcTestLeb128Thunk); + exports.addFunc(sc.FuncWhenMustIncrement, funcWhenMustIncrementThunk); + exports.addView(sc.ViewGetCounter, viewGetCounterThunk); for (let i = 0; i < sc.keyMap.length; i++) { sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); @@ -35,119 +35,119 @@ export function on_load(): void { } function funcCallIncrementThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcCallIncrement"); - let f = new sc.CallIncrementContext(); + ctx.log("inccounter.funcCallIncrement"); + let f = new sc.CallIncrementContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcCallIncrement(ctx, f); - ctx.log("inccounter.funcCallIncrement ok"); + sc.funcCallIncrement(ctx, f); + ctx.log("inccounter.funcCallIncrement ok"); } function funcCallIncrementRecurse5xThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcCallIncrementRecurse5x"); - let f = new sc.CallIncrementRecurse5xContext(); + ctx.log("inccounter.funcCallIncrementRecurse5x"); + let f = new sc.CallIncrementRecurse5xContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcCallIncrementRecurse5x(ctx, f); - ctx.log("inccounter.funcCallIncrementRecurse5x ok"); + sc.funcCallIncrementRecurse5x(ctx, f); + ctx.log("inccounter.funcCallIncrementRecurse5x ok"); } function funcEndlessLoopThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcEndlessLoop"); - let f = new sc.EndlessLoopContext(); + ctx.log("inccounter.funcEndlessLoop"); + let f = new sc.EndlessLoopContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcEndlessLoop(ctx, f); - ctx.log("inccounter.funcEndlessLoop ok"); + sc.funcEndlessLoop(ctx, f); + ctx.log("inccounter.funcEndlessLoop ok"); } function funcIncrementThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcIncrement"); - let f = new sc.IncrementContext(); + ctx.log("inccounter.funcIncrement"); + let f = new sc.IncrementContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcIncrement(ctx, f); - ctx.log("inccounter.funcIncrement ok"); + sc.funcIncrement(ctx, f); + ctx.log("inccounter.funcIncrement ok"); } function funcIncrementWithDelayThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcIncrementWithDelay"); - let f = new sc.IncrementWithDelayContext(); + ctx.log("inccounter.funcIncrementWithDelay"); + let f = new sc.IncrementWithDelayContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.delay().exists(), "missing mandatory delay") - sc.funcIncrementWithDelay(ctx, f); - ctx.log("inccounter.funcIncrementWithDelay ok"); + ctx.require(f.params.delay().exists(), "missing mandatory delay"); + sc.funcIncrementWithDelay(ctx, f); + ctx.log("inccounter.funcIncrementWithDelay ok"); } function funcInitThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcInit"); - let f = new sc.InitContext(); + ctx.log("inccounter.funcInit"); + let f = new sc.InitContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcInit(ctx, f); - ctx.log("inccounter.funcInit ok"); + sc.funcInit(ctx, f); + ctx.log("inccounter.funcInit ok"); } function funcLocalStateInternalCallThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcLocalStateInternalCall"); - let f = new sc.LocalStateInternalCallContext(); + ctx.log("inccounter.funcLocalStateInternalCall"); + let f = new sc.LocalStateInternalCallContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcLocalStateInternalCall(ctx, f); - ctx.log("inccounter.funcLocalStateInternalCall ok"); + sc.funcLocalStateInternalCall(ctx, f); + ctx.log("inccounter.funcLocalStateInternalCall ok"); } function funcLocalStatePostThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcLocalStatePost"); - let f = new sc.LocalStatePostContext(); + ctx.log("inccounter.funcLocalStatePost"); + let f = new sc.LocalStatePostContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcLocalStatePost(ctx, f); - ctx.log("inccounter.funcLocalStatePost ok"); + sc.funcLocalStatePost(ctx, f); + ctx.log("inccounter.funcLocalStatePost ok"); } function funcLocalStateSandboxCallThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcLocalStateSandboxCall"); - let f = new sc.LocalStateSandboxCallContext(); + ctx.log("inccounter.funcLocalStateSandboxCall"); + let f = new sc.LocalStateSandboxCallContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcLocalStateSandboxCall(ctx, f); - ctx.log("inccounter.funcLocalStateSandboxCall ok"); + sc.funcLocalStateSandboxCall(ctx, f); + ctx.log("inccounter.funcLocalStateSandboxCall ok"); } function funcPostIncrementThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcPostIncrement"); - let f = new sc.PostIncrementContext(); + ctx.log("inccounter.funcPostIncrement"); + let f = new sc.PostIncrementContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcPostIncrement(ctx, f); - ctx.log("inccounter.funcPostIncrement ok"); + sc.funcPostIncrement(ctx, f); + ctx.log("inccounter.funcPostIncrement ok"); } function funcRepeatManyThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcRepeatMany"); - let f = new sc.RepeatManyContext(); + ctx.log("inccounter.funcRepeatMany"); + let f = new sc.RepeatManyContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcRepeatMany(ctx, f); - ctx.log("inccounter.funcRepeatMany ok"); + sc.funcRepeatMany(ctx, f); + ctx.log("inccounter.funcRepeatMany ok"); } function funcTestLeb128Thunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcTestLeb128"); - let f = new sc.TestLeb128Context(); + ctx.log("inccounter.funcTestLeb128"); + let f = new sc.TestLeb128Context(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcTestLeb128(ctx, f); - ctx.log("inccounter.funcTestLeb128 ok"); + sc.funcTestLeb128(ctx, f); + ctx.log("inccounter.funcTestLeb128 ok"); } function funcWhenMustIncrementThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("inccounter.funcWhenMustIncrement"); - let f = new sc.WhenMustIncrementContext(); + ctx.log("inccounter.funcWhenMustIncrement"); + let f = new sc.WhenMustIncrementContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcWhenMustIncrement(ctx, f); - ctx.log("inccounter.funcWhenMustIncrement ok"); + sc.funcWhenMustIncrement(ctx, f); + ctx.log("inccounter.funcWhenMustIncrement ok"); } function viewGetCounterThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("inccounter.viewGetCounter"); - let f = new sc.GetCounterContext(); + ctx.log("inccounter.viewGetCounter"); + let f = new sc.GetCounterContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewGetCounter(ctx, f); - ctx.log("inccounter.viewGetCounter ok"); + sc.viewGetCounter(ctx, f); + ctx.log("inccounter.viewGetCounter ok"); } diff --git a/contracts/wasm/inccounter/ts/inccounter/params.ts b/contracts/wasm/inccounter/ts/inccounter/params.ts index 539fd9dc65..7d4de79561 100644 --- a/contracts/wasm/inccounter/ts/inccounter/params.ts +++ b/contracts/wasm/inccounter/ts/inccounter/params.ts @@ -5,61 +5,53 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxParamDelay]); + } } 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, sc.idxMap[sc.IdxParamDelay]); + } } export class ImmutableInitParams extends wasmlib.ScMapID { - counter(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamCounter]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamCounter]); + } } export class MutableInitParams extends wasmlib.ScMapID { - counter(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamCounter]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamCounter]); + } } 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, sc.idxMap[sc.IdxParamNumRepeats]); + } } 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, sc.idxMap[sc.IdxParamNumRepeats]); + } } 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, sc.idxMap[sc.IdxParamDummy]); + } } 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, sc.idxMap[sc.IdxParamDummy]); + } } diff --git a/contracts/wasm/inccounter/ts/inccounter/results.ts b/contracts/wasm/inccounter/ts/inccounter/results.ts index 7d2c0a489b..db9dc68924 100644 --- a/contracts/wasm/inccounter/ts/inccounter/results.ts +++ b/contracts/wasm/inccounter/ts/inccounter/results.ts @@ -5,19 +5,17 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxResultCounter]); + } } 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, sc.idxMap[sc.IdxResultCounter]); + } } diff --git a/contracts/wasm/inccounter/ts/inccounter/state.ts b/contracts/wasm/inccounter/ts/inccounter/state.ts index be2ff82d28..d292899376 100644 --- a/contracts/wasm/inccounter/ts/inccounter/state.ts +++ b/contracts/wasm/inccounter/ts/inccounter/state.ts @@ -5,27 +5,25 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxStateCounter]); + } numRepeats(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateNumRepeats]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateNumRepeats]); + } } export class MutableIncCounterState extends wasmlib.ScMapID { - counter(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateCounter]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateCounter]); + } numRepeats(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateNumRepeats]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateNumRepeats]); + } } diff --git a/contracts/wasm/rust_build.cmd b/contracts/wasm/rust_build.cmd index 1ede3fd3e6..f152c0d98d 100644 --- a/contracts/wasm/rust_build.cmd +++ b/contracts/wasm/rust_build.cmd @@ -1,6 +1,6 @@ @echo off cd %1 -if not exist schema.yaml goto :xit +if not exist schema.yaml if not exist schema.json goto :xit echo Building %1 schema -rust %2 echo compiling %1_bg.wasm diff --git a/contracts/wasm/testcore/go/testcore/consts.go b/contracts/wasm/testcore/go/testcore/consts.go index 678fc04456..d1e82b1b9c 100644 --- a/contracts/wasm/testcore/go/testcore/consts.go +++ b/contracts/wasm/testcore/go/testcore/consts.go @@ -16,45 +16,47 @@ const ( ) const ( - ParamAddress = wasmlib.Key("address") - ParamAgentID = wasmlib.Key("agentID") - ParamCaller = wasmlib.Key("caller") - ParamChainID = wasmlib.Key("chainID") - ParamChainOwnerID = wasmlib.Key("chainOwnerID") - ParamContractCreator = wasmlib.Key("contractCreator") - ParamContractID = wasmlib.Key("contractID") - ParamCounter = wasmlib.Key("counter") - ParamFail = wasmlib.Key("initFailParam") - ParamHash = wasmlib.Key("Hash") - ParamHname = wasmlib.Key("Hname") - ParamHnameContract = wasmlib.Key("hnameContract") - ParamHnameEP = wasmlib.Key("hnameEP") - ParamHnameZero = wasmlib.Key("Hname-0") - ParamInt64 = wasmlib.Key("int64") - ParamInt64Zero = wasmlib.Key("int64-0") - ParamIntValue = wasmlib.Key("intParamValue") - ParamName = wasmlib.Key("intParamName") - ParamProgHash = wasmlib.Key("progHash") - ParamString = wasmlib.Key("string") - ParamStringZero = wasmlib.Key("string-0") - ParamVarName = wasmlib.Key("varName") + ParamAddress = "address" + ParamAgentID = "agentID" + ParamCaller = "caller" + ParamChainID = "chainID" + ParamChainOwnerID = "chainOwnerID" + ParamContractCreator = "contractCreator" + ParamContractID = "contractID" + ParamCounter = "counter" + ParamFail = "initFailParam" + ParamHash = "Hash" + ParamHname = "Hname" + ParamHnameContract = "hnameContract" + ParamHnameEP = "hnameEP" + ParamHnameZero = "Hname-0" + ParamInt64 = "int64" + ParamInt64Zero = "int64-0" + ParamIntValue = "intParamValue" + ParamName = "intParamName" + ParamProgHash = "progHash" + ParamString = "string" + ParamStringZero = "string-0" + ParamVarName = "varName" ) const ( - ResultChainOwnerID = wasmlib.Key("chainOwnerID") - ResultCounter = wasmlib.Key("counter") - ResultIntValue = wasmlib.Key("intParamValue") - ResultMintedColor = wasmlib.Key("mintedColor") - ResultMintedSupply = wasmlib.Key("mintedSupply") - ResultSandboxCall = wasmlib.Key("sandboxCall") + ResultChainOwnerID = "chainOwnerID" + ResultCounter = "counter" + ResultIntValue = "intParamValue" + ResultMintedColor = "mintedColor" + ResultMintedSupply = "mintedSupply" + ResultSandboxCall = "sandboxCall" + ResultValues = "this" + ResultVars = "this" ) const ( - StateCounter = wasmlib.Key("counter") - StateHnameEP = wasmlib.Key("hnameEP") - StateInts = wasmlib.Key("ints") - StateMintedColor = wasmlib.Key("mintedColor") - StateMintedSupply = wasmlib.Key("mintedSupply") + StateCounter = "counter" + StateHnameEP = "hnameEP" + StateInts = "ints" + StateMintedColor = "mintedColor" + StateMintedSupply = "mintedSupply" ) const ( diff --git a/contracts/wasm/testcore/go/testcore/keys.go b/contracts/wasm/testcore/go/testcore/keys.go index eeed6a32d3..bf75b33824 100644 --- a/contracts/wasm/testcore/go/testcore/keys.go +++ b/contracts/wasm/testcore/go/testcore/keys.go @@ -32,20 +32,24 @@ const ( IdxParamString = 19 IdxParamStringZero = 20 IdxParamVarName = 21 - IdxResultChainOwnerID = 22 - IdxResultCounter = 23 - IdxResultIntValue = 24 - IdxResultMintedColor = 25 - IdxResultMintedSupply = 26 - IdxResultSandboxCall = 27 - IdxStateCounter = 28 - IdxStateHnameEP = 29 - IdxStateInts = 30 - IdxStateMintedColor = 31 - IdxStateMintedSupply = 32 + + IdxResultChainOwnerID = 22 + IdxResultCounter = 23 + IdxResultIntValue = 24 + IdxResultMintedColor = 25 + IdxResultMintedSupply = 26 + IdxResultSandboxCall = 27 + IdxResultValues = 28 + IdxResultVars = 29 + + IdxStateCounter = 30 + IdxStateHnameEP = 31 + IdxStateInts = 32 + IdxStateMintedColor = 33 + IdxStateMintedSupply = 34 ) -const keyMapLen = 33 +const keyMapLen = 35 var keyMap = [keyMapLen]wasmlib.Key{ ParamAddress, @@ -76,6 +80,8 @@ var keyMap = [keyMapLen]wasmlib.Key{ ResultMintedColor, ResultMintedSupply, ResultSandboxCall, + ResultValues, + ResultVars, StateCounter, StateHnameEP, StateInts, diff --git a/contracts/wasm/testcore/go/testcore/testcore.go b/contracts/wasm/testcore/go/testcore/testcore.go index 7d83b31df4..9537c6374a 100644 --- a/contracts/wasm/testcore/go/testcore/testcore.go +++ b/contracts/wasm/testcore/go/testcore/testcore.go @@ -40,9 +40,9 @@ func funcCallOnChain(ctx wasmlib.ScFuncContext, f *CallOnChainContext) { counter.SetValue(counter.Value() + 1) params := wasmlib.NewScMutableMap() - params.GetInt64(ParamIntValue).SetValue(paramIn) + params.GetInt64(wasmlib.Key(ParamIntValue)).SetValue(paramIn) ret := ctx.Call(hnameContract, hnameEP, params, nil) - retVal := ret.GetInt64(ResultIntValue).Value() + retVal := ret.GetInt64(wasmlib.Key(ResultIntValue)).Value() f.Results.IntValue().SetValue(retVal) } diff --git a/contracts/wasm/testcore/src/consts.rs b/contracts/wasm/testcore/src/consts.rs index d4898fa9ae..efff63eec3 100644 --- a/contracts/wasm/testcore/src/consts.rs +++ b/contracts/wasm/testcore/src/consts.rs @@ -5,116 +5,114 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; -pub const SC_NAME: &str = "testcore"; -pub const SC_DESCRIPTION: &str = "Core test for ISCP wasmlib Rust/Wasm library"; -pub const HSC_NAME: ScHname = ScHname(0x370d33ad); - -pub const PARAM_ADDRESS: &str = "address"; -pub const PARAM_AGENT_ID: &str = "agentID"; -pub const PARAM_CALLER: &str = "caller"; -pub const PARAM_CHAIN_ID: &str = "chainID"; -pub const PARAM_CHAIN_OWNER_ID: &str = "chainOwnerID"; -pub const PARAM_CONTRACT_CREATOR: &str = "contractCreator"; -pub const PARAM_CONTRACT_ID: &str = "contractID"; -pub const PARAM_COUNTER: &str = "counter"; -pub const PARAM_FAIL: &str = "initFailParam"; -pub const PARAM_HASH: &str = "Hash"; -pub const PARAM_HNAME: &str = "Hname"; -pub const PARAM_HNAME_CONTRACT: &str = "hnameContract"; -pub const PARAM_HNAME_EP: &str = "hnameEP"; -pub const PARAM_HNAME_ZERO: &str = "Hname-0"; -pub const PARAM_INT64: &str = "int64"; -pub const PARAM_INT64_ZERO: &str = "int64-0"; -pub const PARAM_INT_VALUE: &str = "intParamValue"; -pub const PARAM_NAME: &str = "intParamName"; -pub const PARAM_PROG_HASH: &str = "progHash"; -pub const PARAM_STRING: &str = "string"; -pub const PARAM_STRING_ZERO: &str = "string-0"; -pub const PARAM_VAR_NAME: &str = "varName"; +pub const SC_NAME : &str = "testcore"; +pub const SC_DESCRIPTION : &str = "Core test for ISCP wasmlib Rust/Wasm library"; +pub const HSC_NAME : ScHname = ScHname(0x370d33ad); -pub const RESULT_CHAIN_OWNER_ID: &str = "chainOwnerID"; -pub const RESULT_COUNTER: &str = "counter"; -pub const RESULT_INT_VALUE: &str = "intParamValue"; -pub const RESULT_MINTED_COLOR: &str = "mintedColor"; -pub const RESULT_MINTED_SUPPLY: &str = "mintedSupply"; -pub const RESULT_SANDBOX_CALL: &str = "sandboxCall"; +pub const PARAM_ADDRESS : &str = "address"; +pub const PARAM_AGENT_ID : &str = "agentID"; +pub const PARAM_CALLER : &str = "caller"; +pub const PARAM_CHAIN_ID : &str = "chainID"; +pub const PARAM_CHAIN_OWNER_ID : &str = "chainOwnerID"; +pub const PARAM_CONTRACT_CREATOR : &str = "contractCreator"; +pub const PARAM_CONTRACT_ID : &str = "contractID"; +pub const PARAM_COUNTER : &str = "counter"; +pub const PARAM_FAIL : &str = "initFailParam"; +pub const PARAM_HASH : &str = "Hash"; +pub const PARAM_HNAME : &str = "Hname"; +pub const PARAM_HNAME_CONTRACT : &str = "hnameContract"; +pub const PARAM_HNAME_EP : &str = "hnameEP"; +pub const PARAM_HNAME_ZERO : &str = "Hname-0"; +pub const PARAM_INT64 : &str = "int64"; +pub const PARAM_INT64_ZERO : &str = "int64-0"; +pub const PARAM_INT_VALUE : &str = "intParamValue"; +pub const PARAM_NAME : &str = "intParamName"; +pub const PARAM_PROG_HASH : &str = "progHash"; +pub const PARAM_STRING : &str = "string"; +pub const PARAM_STRING_ZERO : &str = "string-0"; +pub const PARAM_VAR_NAME : &str = "varName"; -pub const STATE_COUNTER: &str = "counter"; -pub const STATE_HNAME_EP: &str = "hnameEP"; -pub const STATE_INTS: &str = "ints"; -pub const STATE_MINTED_COLOR: &str = "mintedColor"; -pub const STATE_MINTED_SUPPLY: &str = "mintedSupply"; +pub const RESULT_CHAIN_OWNER_ID : &str = "chainOwnerID"; +pub const RESULT_COUNTER : &str = "counter"; +pub const RESULT_INT_VALUE : &str = "intParamValue"; +pub const RESULT_MINTED_COLOR : &str = "mintedColor"; +pub const RESULT_MINTED_SUPPLY : &str = "mintedSupply"; +pub const RESULT_SANDBOX_CALL : &str = "sandboxCall"; +pub const RESULT_VALUES : &str = "this"; +pub const RESULT_VARS : &str = "this"; -pub const FUNC_CALL_ON_CHAIN: &str = "callOnChain"; -pub const FUNC_CHECK_CONTEXT_FROM_FULL_EP: &str = "checkContextFromFullEP"; -pub const FUNC_DO_NOTHING: &str = "doNothing"; -pub const FUNC_GET_MINTED_SUPPLY: &str = "getMintedSupply"; -pub const FUNC_INC_COUNTER: &str = "incCounter"; -pub const FUNC_INIT: &str = "init"; -pub const FUNC_PASS_TYPES_FULL: &str = "passTypesFull"; -pub const FUNC_RUN_RECURSION: &str = "runRecursion"; -pub const FUNC_SEND_TO_ADDRESS: &str = "sendToAddress"; -pub const FUNC_SET_INT: &str = "setInt"; -pub const FUNC_SPAWN: &str = "spawn"; -pub const FUNC_TEST_BLOCK_CONTEXT1: &str = "testBlockContext1"; -pub const FUNC_TEST_BLOCK_CONTEXT2: &str = "testBlockContext2"; -pub const FUNC_TEST_CALL_PANIC_FULL_EP: &str = "testCallPanicFullEP"; -pub const FUNC_TEST_CALL_PANIC_VIEW_EP_FROM_FULL: &str = "testCallPanicViewEPFromFull"; -pub const FUNC_TEST_CHAIN_OWNER_ID_FULL: &str = "testChainOwnerIDFull"; -pub const FUNC_TEST_EVENT_LOG_DEPLOY: &str = "testEventLogDeploy"; -pub const FUNC_TEST_EVENT_LOG_EVENT_DATA: &str = "testEventLogEventData"; -pub const FUNC_TEST_EVENT_LOG_GENERIC_DATA: &str = "testEventLogGenericData"; -pub const FUNC_TEST_PANIC_FULL_EP: &str = "testPanicFullEP"; -pub const FUNC_WITHDRAW_TO_CHAIN: &str = "withdrawToChain"; -pub const VIEW_CHECK_CONTEXT_FROM_VIEW_EP: &str = "checkContextFromViewEP"; -pub const VIEW_FIBONACCI: &str = "fibonacci"; -pub const VIEW_GET_COUNTER: &str = "getCounter"; -pub const VIEW_GET_INT: &str = "getInt"; -pub const VIEW_GET_STRING_VALUE: &str = "getStringValue"; -pub const VIEW_JUST_VIEW: &str = "justView"; -pub const VIEW_PASS_TYPES_VIEW: &str = "passTypesView"; -pub const VIEW_TEST_CALL_PANIC_VIEW_EP_FROM_VIEW: &str = "testCallPanicViewEPFromView"; -pub const VIEW_TEST_CHAIN_OWNER_ID_VIEW: &str = "testChainOwnerIDView"; -pub const VIEW_TEST_PANIC_VIEW_EP: &str = "testPanicViewEP"; -pub const VIEW_TEST_SANDBOX_CALL: &str = "testSandboxCall"; +pub const STATE_COUNTER : &str = "counter"; +pub const STATE_HNAME_EP : &str = "hnameEP"; +pub const STATE_INTS : &str = "ints"; +pub const STATE_MINTED_COLOR : &str = "mintedColor"; +pub const STATE_MINTED_SUPPLY : &str = "mintedSupply"; -pub const HFUNC_CALL_ON_CHAIN: ScHname = ScHname(0x95a3d123); -pub const HFUNC_CHECK_CONTEXT_FROM_FULL_EP: ScHname = ScHname(0xa56c24ba); -pub const HFUNC_DO_NOTHING: ScHname = ScHname(0xdda4a6de); -pub const HFUNC_GET_MINTED_SUPPLY: ScHname = ScHname(0x0c2d113c); -pub const HFUNC_INC_COUNTER: ScHname = ScHname(0x7b287419); -pub const HFUNC_INIT: ScHname = ScHname(0x1f44d644); -pub const HFUNC_PASS_TYPES_FULL: ScHname = ScHname(0x733ea0ea); -pub const HFUNC_RUN_RECURSION: ScHname = ScHname(0x833425fd); -pub const HFUNC_SEND_TO_ADDRESS: ScHname = ScHname(0x63ce4634); -pub const HFUNC_SET_INT: ScHname = ScHname(0x62056f74); -pub const HFUNC_SPAWN: ScHname = ScHname(0xec929d12); -pub const HFUNC_TEST_BLOCK_CONTEXT1: ScHname = ScHname(0x796d4136); -pub const HFUNC_TEST_BLOCK_CONTEXT2: ScHname = ScHname(0x758b0452); -pub const HFUNC_TEST_CALL_PANIC_FULL_EP: ScHname = ScHname(0x4c878834); -pub const HFUNC_TEST_CALL_PANIC_VIEW_EP_FROM_FULL: ScHname = ScHname(0xfd7e8c1d); -pub const HFUNC_TEST_CHAIN_OWNER_ID_FULL: ScHname = ScHname(0x2aff1167); -pub const HFUNC_TEST_EVENT_LOG_DEPLOY: ScHname = ScHname(0x96ff760a); -pub const HFUNC_TEST_EVENT_LOG_EVENT_DATA: ScHname = ScHname(0x0efcf939); -pub const HFUNC_TEST_EVENT_LOG_GENERIC_DATA: ScHname = ScHname(0x6a16629d); -pub const HFUNC_TEST_PANIC_FULL_EP: ScHname = ScHname(0x24fdef07); -pub const HFUNC_WITHDRAW_TO_CHAIN: ScHname = ScHname(0x437bc026); -pub const HVIEW_CHECK_CONTEXT_FROM_VIEW_EP: ScHname = ScHname(0x88ff0167); -pub const HVIEW_FIBONACCI: ScHname = ScHname(0x7940873c); -pub const HVIEW_GET_COUNTER: ScHname = ScHname(0xb423e607); -pub const HVIEW_GET_INT: ScHname = ScHname(0x1887e5ef); -pub const HVIEW_GET_STRING_VALUE: ScHname = ScHname(0xcf0a4d32); -pub const HVIEW_JUST_VIEW: ScHname = ScHname(0x33b8972e); -pub const HVIEW_PASS_TYPES_VIEW: ScHname = ScHname(0x1a5b87ea); -pub const HVIEW_TEST_CALL_PANIC_VIEW_EP_FROM_VIEW: ScHname = ScHname(0x91b10c99); -pub const HVIEW_TEST_CHAIN_OWNER_ID_VIEW: ScHname = ScHname(0x26586c33); -pub const HVIEW_TEST_PANIC_VIEW_EP: ScHname = ScHname(0x22bc4d72); -pub const HVIEW_TEST_SANDBOX_CALL: ScHname = ScHname(0x42d72b63); +pub const FUNC_CALL_ON_CHAIN : &str = "callOnChain"; +pub const FUNC_CHECK_CONTEXT_FROM_FULL_EP : &str = "checkContextFromFullEP"; +pub const FUNC_DO_NOTHING : &str = "doNothing"; +pub const FUNC_GET_MINTED_SUPPLY : &str = "getMintedSupply"; +pub const FUNC_INC_COUNTER : &str = "incCounter"; +pub const FUNC_INIT : &str = "init"; +pub const FUNC_PASS_TYPES_FULL : &str = "passTypesFull"; +pub const FUNC_RUN_RECURSION : &str = "runRecursion"; +pub const FUNC_SEND_TO_ADDRESS : &str = "sendToAddress"; +pub const FUNC_SET_INT : &str = "setInt"; +pub const FUNC_SPAWN : &str = "spawn"; +pub const FUNC_TEST_BLOCK_CONTEXT1 : &str = "testBlockContext1"; +pub const FUNC_TEST_BLOCK_CONTEXT2 : &str = "testBlockContext2"; +pub const FUNC_TEST_CALL_PANIC_FULL_EP : &str = "testCallPanicFullEP"; +pub const FUNC_TEST_CALL_PANIC_VIEW_EP_FROM_FULL : &str = "testCallPanicViewEPFromFull"; +pub const FUNC_TEST_CHAIN_OWNER_ID_FULL : &str = "testChainOwnerIDFull"; +pub const FUNC_TEST_EVENT_LOG_DEPLOY : &str = "testEventLogDeploy"; +pub const FUNC_TEST_EVENT_LOG_EVENT_DATA : &str = "testEventLogEventData"; +pub const FUNC_TEST_EVENT_LOG_GENERIC_DATA : &str = "testEventLogGenericData"; +pub const FUNC_TEST_PANIC_FULL_EP : &str = "testPanicFullEP"; +pub const FUNC_WITHDRAW_TO_CHAIN : &str = "withdrawToChain"; +pub const VIEW_CHECK_CONTEXT_FROM_VIEW_EP : &str = "checkContextFromViewEP"; +pub const VIEW_FIBONACCI : &str = "fibonacci"; +pub const VIEW_GET_COUNTER : &str = "getCounter"; +pub const VIEW_GET_INT : &str = "getInt"; +pub const VIEW_GET_STRING_VALUE : &str = "getStringValue"; +pub const VIEW_JUST_VIEW : &str = "justView"; +pub const VIEW_PASS_TYPES_VIEW : &str = "passTypesView"; +pub const VIEW_TEST_CALL_PANIC_VIEW_EP_FROM_VIEW : &str = "testCallPanicViewEPFromView"; +pub const VIEW_TEST_CHAIN_OWNER_ID_VIEW : &str = "testChainOwnerIDView"; +pub const VIEW_TEST_PANIC_VIEW_EP : &str = "testPanicViewEP"; +pub const VIEW_TEST_SANDBOX_CALL : &str = "testSandboxCall"; -// @formatter:on +pub const HFUNC_CALL_ON_CHAIN : ScHname = ScHname(0x95a3d123); +pub const HFUNC_CHECK_CONTEXT_FROM_FULL_EP : ScHname = ScHname(0xa56c24ba); +pub const HFUNC_DO_NOTHING : ScHname = ScHname(0xdda4a6de); +pub const HFUNC_GET_MINTED_SUPPLY : ScHname = ScHname(0x0c2d113c); +pub const HFUNC_INC_COUNTER : ScHname = ScHname(0x7b287419); +pub const HFUNC_INIT : ScHname = ScHname(0x1f44d644); +pub const HFUNC_PASS_TYPES_FULL : ScHname = ScHname(0x733ea0ea); +pub const HFUNC_RUN_RECURSION : ScHname = ScHname(0x833425fd); +pub const HFUNC_SEND_TO_ADDRESS : ScHname = ScHname(0x63ce4634); +pub const HFUNC_SET_INT : ScHname = ScHname(0x62056f74); +pub const HFUNC_SPAWN : ScHname = ScHname(0xec929d12); +pub const HFUNC_TEST_BLOCK_CONTEXT1 : ScHname = ScHname(0x796d4136); +pub const HFUNC_TEST_BLOCK_CONTEXT2 : ScHname = ScHname(0x758b0452); +pub const HFUNC_TEST_CALL_PANIC_FULL_EP : ScHname = ScHname(0x4c878834); +pub const HFUNC_TEST_CALL_PANIC_VIEW_EP_FROM_FULL : ScHname = ScHname(0xfd7e8c1d); +pub const HFUNC_TEST_CHAIN_OWNER_ID_FULL : ScHname = ScHname(0x2aff1167); +pub const HFUNC_TEST_EVENT_LOG_DEPLOY : ScHname = ScHname(0x96ff760a); +pub const HFUNC_TEST_EVENT_LOG_EVENT_DATA : ScHname = ScHname(0x0efcf939); +pub const HFUNC_TEST_EVENT_LOG_GENERIC_DATA : ScHname = ScHname(0x6a16629d); +pub const HFUNC_TEST_PANIC_FULL_EP : ScHname = ScHname(0x24fdef07); +pub const HFUNC_WITHDRAW_TO_CHAIN : ScHname = ScHname(0x437bc026); +pub const HVIEW_CHECK_CONTEXT_FROM_VIEW_EP : ScHname = ScHname(0x88ff0167); +pub const HVIEW_FIBONACCI : ScHname = ScHname(0x7940873c); +pub const HVIEW_GET_COUNTER : ScHname = ScHname(0xb423e607); +pub const HVIEW_GET_INT : ScHname = ScHname(0x1887e5ef); +pub const HVIEW_GET_STRING_VALUE : ScHname = ScHname(0xcf0a4d32); +pub const HVIEW_JUST_VIEW : ScHname = ScHname(0x33b8972e); +pub const HVIEW_PASS_TYPES_VIEW : ScHname = ScHname(0x1a5b87ea); +pub const HVIEW_TEST_CALL_PANIC_VIEW_EP_FROM_VIEW : ScHname = ScHname(0x91b10c99); +pub const HVIEW_TEST_CHAIN_OWNER_ID_VIEW : ScHname = ScHname(0x26586c33); +pub const HVIEW_TEST_PANIC_VIEW_EP : ScHname = ScHname(0x22bc4d72); +pub const HVIEW_TEST_SANDBOX_CALL : ScHname = ScHname(0x42d72b63); diff --git a/contracts/wasm/testcore/src/contract.rs b/contracts/wasm/testcore/src/contract.rs index f8d4384296..a00e5b9eeb 100644 --- a/contracts/wasm/testcore/src/contract.rs +++ b/contracts/wasm/testcore/src/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -18,156 +16,156 @@ use crate::params::*; use crate::results::*; pub struct CallOnChainCall { - pub func: ScFunc, - pub params: MutableCallOnChainParams, - pub results: ImmutableCallOnChainResults, + pub func: ScFunc, + pub params: MutableCallOnChainParams, + pub results: ImmutableCallOnChainResults, } pub struct CheckContextFromFullEPCall { - pub func: ScFunc, - pub params: MutableCheckContextFromFullEPParams, + pub func: ScFunc, + pub params: MutableCheckContextFromFullEPParams, } pub struct DoNothingCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct GetMintedSupplyCall { - pub func: ScFunc, - pub results: ImmutableGetMintedSupplyResults, + pub func: ScFunc, + pub results: ImmutableGetMintedSupplyResults, } pub struct IncCounterCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct InitCall { - pub func: ScInitFunc, - pub params: MutableInitParams, + pub func: ScInitFunc, + pub params: MutableInitParams, } pub struct PassTypesFullCall { - pub func: ScFunc, - pub params: MutablePassTypesFullParams, + pub func: ScFunc, + pub params: MutablePassTypesFullParams, } pub struct RunRecursionCall { - pub func: ScFunc, - pub params: MutableRunRecursionParams, - pub results: ImmutableRunRecursionResults, + pub func: ScFunc, + pub params: MutableRunRecursionParams, + pub results: ImmutableRunRecursionResults, } pub struct SendToAddressCall { - pub func: ScFunc, - pub params: MutableSendToAddressParams, + pub func: ScFunc, + pub params: MutableSendToAddressParams, } pub struct SetIntCall { - pub func: ScFunc, - pub params: MutableSetIntParams, + pub func: ScFunc, + pub params: MutableSetIntParams, } pub struct SpawnCall { - pub func: ScFunc, - pub params: MutableSpawnParams, + pub func: ScFunc, + pub params: MutableSpawnParams, } pub struct TestBlockContext1Call { - pub func: ScFunc, + pub func: ScFunc, } pub struct TestBlockContext2Call { - pub func: ScFunc, + pub func: ScFunc, } pub struct TestCallPanicFullEPCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct TestCallPanicViewEPFromFullCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct TestChainOwnerIDFullCall { - pub func: ScFunc, - pub results: ImmutableTestChainOwnerIDFullResults, + pub func: ScFunc, + pub results: ImmutableTestChainOwnerIDFullResults, } pub struct TestEventLogDeployCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct TestEventLogEventDataCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct TestEventLogGenericDataCall { - pub func: ScFunc, - pub params: MutableTestEventLogGenericDataParams, + pub func: ScFunc, + pub params: MutableTestEventLogGenericDataParams, } pub struct TestPanicFullEPCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct WithdrawToChainCall { - pub func: ScFunc, - pub params: MutableWithdrawToChainParams, + pub func: ScFunc, + pub params: MutableWithdrawToChainParams, } pub struct CheckContextFromViewEPCall { - pub func: ScView, - pub params: MutableCheckContextFromViewEPParams, + pub func: ScView, + pub params: MutableCheckContextFromViewEPParams, } pub struct FibonacciCall { - pub func: ScView, - pub params: MutableFibonacciParams, - pub results: ImmutableFibonacciResults, + pub func: ScView, + pub params: MutableFibonacciParams, + pub results: ImmutableFibonacciResults, } pub struct GetCounterCall { - pub func: ScView, - pub results: ImmutableGetCounterResults, + pub func: ScView, + pub results: ImmutableGetCounterResults, } pub struct GetIntCall { - pub func: ScView, - pub params: MutableGetIntParams, - pub results: ImmutableGetIntResults, + pub func: ScView, + pub params: MutableGetIntParams, + pub results: ImmutableGetIntResults, } pub struct GetStringValueCall { - pub func: ScView, - pub params: MutableGetStringValueParams, - pub results: ImmutableGetStringValueResults, + pub func: ScView, + pub params: MutableGetStringValueParams, + pub results: ImmutableGetStringValueResults, } pub struct JustViewCall { - pub func: ScView, + pub func: ScView, } pub struct PassTypesViewCall { - pub func: ScView, - pub params: MutablePassTypesViewParams, + pub func: ScView, + pub params: MutablePassTypesViewParams, } pub struct TestCallPanicViewEPFromViewCall { - pub func: ScView, + pub func: ScView, } pub struct TestChainOwnerIDViewCall { - pub func: ScView, - pub results: ImmutableTestChainOwnerIDViewResults, + pub func: ScView, + pub results: ImmutableTestChainOwnerIDViewResults, } pub struct TestPanicViewEPCall { - pub func: ScView, + pub func: ScView, } pub struct TestSandboxCallCall { - pub func: ScView, - pub results: ImmutableTestSandboxCallResults, + pub func: ScView, + pub results: ImmutableTestSandboxCallResults, } pub struct ScFuncs { @@ -176,229 +174,258 @@ pub struct ScFuncs { impl ScFuncs { pub fn call_on_chain(_ctx: & dyn ScFuncCallContext) -> CallOnChainCall { let mut f = CallOnChainCall { - func: ScFunc::new(HSC_NAME, HFUNC_CALL_ON_CHAIN), - params: MutableCallOnChainParams { id: 0 }, + func: ScFunc::new(HSC_NAME, HFUNC_CALL_ON_CHAIN), + params: MutableCallOnChainParams { id: 0 }, results: ImmutableCallOnChainResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn check_context_from_full_ep(_ctx: & dyn ScFuncCallContext) -> CheckContextFromFullEPCall { let mut f = CheckContextFromFullEPCall { - func: ScFunc::new(HSC_NAME, HFUNC_CHECK_CONTEXT_FROM_FULL_EP), + func: ScFunc::new(HSC_NAME, HFUNC_CHECK_CONTEXT_FROM_FULL_EP), params: MutableCheckContextFromFullEPParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn do_nothing(_ctx: & dyn ScFuncCallContext) -> DoNothingCall { DoNothingCall { func: ScFunc::new(HSC_NAME, HFUNC_DO_NOTHING), } } + pub fn get_minted_supply(_ctx: & dyn ScFuncCallContext) -> GetMintedSupplyCall { let mut f = GetMintedSupplyCall { - func: ScFunc::new(HSC_NAME, HFUNC_GET_MINTED_SUPPLY), + func: ScFunc::new(HSC_NAME, HFUNC_GET_MINTED_SUPPLY), results: ImmutableGetMintedSupplyResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn inc_counter(_ctx: & dyn ScFuncCallContext) -> IncCounterCall { IncCounterCall { func: ScFunc::new(HSC_NAME, HFUNC_INC_COUNTER), } } + pub fn init(_ctx: & dyn ScFuncCallContext) -> InitCall { let mut f = InitCall { - func: ScInitFunc::new(HSC_NAME, HFUNC_INIT), + func: ScInitFunc::new(HSC_NAME, HFUNC_INIT), params: MutableInitParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn pass_types_full(_ctx: & dyn ScFuncCallContext) -> PassTypesFullCall { let mut f = PassTypesFullCall { - func: ScFunc::new(HSC_NAME, HFUNC_PASS_TYPES_FULL), + func: ScFunc::new(HSC_NAME, HFUNC_PASS_TYPES_FULL), params: MutablePassTypesFullParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn run_recursion(_ctx: & dyn ScFuncCallContext) -> RunRecursionCall { let mut f = RunRecursionCall { - func: ScFunc::new(HSC_NAME, HFUNC_RUN_RECURSION), - params: MutableRunRecursionParams { id: 0 }, + func: ScFunc::new(HSC_NAME, HFUNC_RUN_RECURSION), + params: MutableRunRecursionParams { id: 0 }, results: ImmutableRunRecursionResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn send_to_address(_ctx: & dyn ScFuncCallContext) -> SendToAddressCall { let mut f = SendToAddressCall { - func: ScFunc::new(HSC_NAME, HFUNC_SEND_TO_ADDRESS), + func: ScFunc::new(HSC_NAME, HFUNC_SEND_TO_ADDRESS), params: MutableSendToAddressParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn set_int(_ctx: & dyn ScFuncCallContext) -> SetIntCall { let mut f = SetIntCall { - func: ScFunc::new(HSC_NAME, HFUNC_SET_INT), + func: ScFunc::new(HSC_NAME, HFUNC_SET_INT), params: MutableSetIntParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn spawn(_ctx: & dyn ScFuncCallContext) -> SpawnCall { let mut f = SpawnCall { - func: ScFunc::new(HSC_NAME, HFUNC_SPAWN), + func: ScFunc::new(HSC_NAME, HFUNC_SPAWN), params: MutableSpawnParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn test_block_context1(_ctx: & dyn ScFuncCallContext) -> TestBlockContext1Call { TestBlockContext1Call { func: ScFunc::new(HSC_NAME, HFUNC_TEST_BLOCK_CONTEXT1), } } + pub fn test_block_context2(_ctx: & dyn ScFuncCallContext) -> TestBlockContext2Call { TestBlockContext2Call { func: ScFunc::new(HSC_NAME, HFUNC_TEST_BLOCK_CONTEXT2), } } + pub fn test_call_panic_full_ep(_ctx: & dyn ScFuncCallContext) -> TestCallPanicFullEPCall { TestCallPanicFullEPCall { func: ScFunc::new(HSC_NAME, HFUNC_TEST_CALL_PANIC_FULL_EP), } } + pub fn test_call_panic_view_ep_from_full(_ctx: & dyn ScFuncCallContext) -> TestCallPanicViewEPFromFullCall { TestCallPanicViewEPFromFullCall { func: ScFunc::new(HSC_NAME, HFUNC_TEST_CALL_PANIC_VIEW_EP_FROM_FULL), } } + pub fn test_chain_owner_id_full(_ctx: & dyn ScFuncCallContext) -> TestChainOwnerIDFullCall { let mut f = TestChainOwnerIDFullCall { - func: ScFunc::new(HSC_NAME, HFUNC_TEST_CHAIN_OWNER_ID_FULL), + func: ScFunc::new(HSC_NAME, HFUNC_TEST_CHAIN_OWNER_ID_FULL), results: ImmutableTestChainOwnerIDFullResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn test_event_log_deploy(_ctx: & dyn ScFuncCallContext) -> TestEventLogDeployCall { TestEventLogDeployCall { func: ScFunc::new(HSC_NAME, HFUNC_TEST_EVENT_LOG_DEPLOY), } } + pub fn test_event_log_event_data(_ctx: & dyn ScFuncCallContext) -> TestEventLogEventDataCall { TestEventLogEventDataCall { func: ScFunc::new(HSC_NAME, HFUNC_TEST_EVENT_LOG_EVENT_DATA), } } + pub fn test_event_log_generic_data(_ctx: & dyn ScFuncCallContext) -> TestEventLogGenericDataCall { let mut f = TestEventLogGenericDataCall { - func: ScFunc::new(HSC_NAME, HFUNC_TEST_EVENT_LOG_GENERIC_DATA), + func: ScFunc::new(HSC_NAME, HFUNC_TEST_EVENT_LOG_GENERIC_DATA), params: MutableTestEventLogGenericDataParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn test_panic_full_ep(_ctx: & dyn ScFuncCallContext) -> TestPanicFullEPCall { TestPanicFullEPCall { func: ScFunc::new(HSC_NAME, HFUNC_TEST_PANIC_FULL_EP), } } + pub fn withdraw_to_chain(_ctx: & dyn ScFuncCallContext) -> WithdrawToChainCall { let mut f = WithdrawToChainCall { - func: ScFunc::new(HSC_NAME, HFUNC_WITHDRAW_TO_CHAIN), + func: ScFunc::new(HSC_NAME, HFUNC_WITHDRAW_TO_CHAIN), params: MutableWithdrawToChainParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn check_context_from_view_ep(_ctx: & dyn ScViewCallContext) -> CheckContextFromViewEPCall { let mut f = CheckContextFromViewEPCall { - func: ScView::new(HSC_NAME, HVIEW_CHECK_CONTEXT_FROM_VIEW_EP), + func: ScView::new(HSC_NAME, HVIEW_CHECK_CONTEXT_FROM_VIEW_EP), params: MutableCheckContextFromViewEPParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn fibonacci(_ctx: & dyn ScViewCallContext) -> FibonacciCall { let mut f = FibonacciCall { - func: ScView::new(HSC_NAME, HVIEW_FIBONACCI), - params: MutableFibonacciParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_FIBONACCI), + params: MutableFibonacciParams { id: 0 }, results: ImmutableFibonacciResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_counter(_ctx: & dyn ScViewCallContext) -> GetCounterCall { let mut f = GetCounterCall { - func: ScView::new(HSC_NAME, HVIEW_GET_COUNTER), + func: ScView::new(HSC_NAME, HVIEW_GET_COUNTER), results: ImmutableGetCounterResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn get_int(_ctx: & dyn ScViewCallContext) -> GetIntCall { let mut f = GetIntCall { - func: ScView::new(HSC_NAME, HVIEW_GET_INT), - params: MutableGetIntParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_INT), + params: MutableGetIntParams { id: 0 }, results: ImmutableGetIntResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_string_value(_ctx: & dyn ScViewCallContext) -> GetStringValueCall { let mut f = GetStringValueCall { - func: ScView::new(HSC_NAME, HVIEW_GET_STRING_VALUE), - params: MutableGetStringValueParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_STRING_VALUE), + params: MutableGetStringValueParams { id: 0 }, results: ImmutableGetStringValueResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn just_view(_ctx: & dyn ScViewCallContext) -> JustViewCall { JustViewCall { func: ScView::new(HSC_NAME, HVIEW_JUST_VIEW), } } + pub fn pass_types_view(_ctx: & dyn ScViewCallContext) -> PassTypesViewCall { let mut f = PassTypesViewCall { - func: ScView::new(HSC_NAME, HVIEW_PASS_TYPES_VIEW), + func: ScView::new(HSC_NAME, HVIEW_PASS_TYPES_VIEW), params: MutablePassTypesViewParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn test_call_panic_view_ep_from_view(_ctx: & dyn ScViewCallContext) -> TestCallPanicViewEPFromViewCall { TestCallPanicViewEPFromViewCall { func: ScView::new(HSC_NAME, HVIEW_TEST_CALL_PANIC_VIEW_EP_FROM_VIEW), } } + pub fn test_chain_owner_id_view(_ctx: & dyn ScViewCallContext) -> TestChainOwnerIDViewCall { let mut f = TestChainOwnerIDViewCall { - func: ScView::new(HSC_NAME, HVIEW_TEST_CHAIN_OWNER_ID_VIEW), + func: ScView::new(HSC_NAME, HVIEW_TEST_CHAIN_OWNER_ID_VIEW), results: ImmutableTestChainOwnerIDViewResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn test_panic_view_ep(_ctx: & dyn ScViewCallContext) -> TestPanicViewEPCall { TestPanicViewEPCall { func: ScView::new(HSC_NAME, HVIEW_TEST_PANIC_VIEW_EP), } } + pub fn test_sandbox_call(_ctx: & dyn ScViewCallContext) -> TestSandboxCallCall { let mut f = TestSandboxCallCall { - func: ScView::new(HSC_NAME, HVIEW_TEST_SANDBOX_CALL), + func: ScView::new(HSC_NAME, HVIEW_TEST_SANDBOX_CALL), results: ImmutableTestSandboxCallResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/contracts/wasm/testcore/src/keys.rs b/contracts/wasm/testcore/src/keys.rs index 9d7429fc93..3144450f06 100644 --- a/contracts/wasm/testcore/src/keys.rs +++ b/contracts/wasm/testcore/src/keys.rs @@ -5,84 +5,88 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use crate::*; -pub(crate) const IDX_PARAM_ADDRESS: usize = 0; -pub(crate) const IDX_PARAM_AGENT_ID: usize = 1; -pub(crate) const IDX_PARAM_CALLER: usize = 2; -pub(crate) const IDX_PARAM_CHAIN_ID: usize = 3; -pub(crate) const IDX_PARAM_CHAIN_OWNER_ID: usize = 4; -pub(crate) const IDX_PARAM_CONTRACT_CREATOR: usize = 5; -pub(crate) const IDX_PARAM_CONTRACT_ID: usize = 6; -pub(crate) const IDX_PARAM_COUNTER: usize = 7; -pub(crate) const IDX_PARAM_FAIL: usize = 8; -pub(crate) const IDX_PARAM_HASH: usize = 9; -pub(crate) const IDX_PARAM_HNAME: usize = 10; -pub(crate) const IDX_PARAM_HNAME_CONTRACT: usize = 11; -pub(crate) const IDX_PARAM_HNAME_EP: usize = 12; -pub(crate) const IDX_PARAM_HNAME_ZERO: usize = 13; -pub(crate) const IDX_PARAM_INT64: usize = 14; -pub(crate) const IDX_PARAM_INT64_ZERO: usize = 15; -pub(crate) const IDX_PARAM_INT_VALUE: usize = 16; -pub(crate) const IDX_PARAM_NAME: usize = 17; -pub(crate) const IDX_PARAM_PROG_HASH: usize = 18; -pub(crate) const IDX_PARAM_STRING: usize = 19; -pub(crate) const IDX_PARAM_STRING_ZERO: usize = 20; -pub(crate) const IDX_PARAM_VAR_NAME: usize = 21; -pub(crate) const IDX_RESULT_CHAIN_OWNER_ID: usize = 22; -pub(crate) const IDX_RESULT_COUNTER: usize = 23; -pub(crate) const IDX_RESULT_INT_VALUE: usize = 24; -pub(crate) const IDX_RESULT_MINTED_COLOR: usize = 25; -pub(crate) const IDX_RESULT_MINTED_SUPPLY: usize = 26; -pub(crate) const IDX_RESULT_SANDBOX_CALL: usize = 27; -pub(crate) const IDX_STATE_COUNTER: usize = 28; -pub(crate) const IDX_STATE_HNAME_EP: usize = 29; -pub(crate) const IDX_STATE_INTS: usize = 30; -pub(crate) const IDX_STATE_MINTED_COLOR: usize = 31; -pub(crate) const IDX_STATE_MINTED_SUPPLY: usize = 32; +pub(crate) const IDX_PARAM_ADDRESS : usize = 0; +pub(crate) const IDX_PARAM_AGENT_ID : usize = 1; +pub(crate) const IDX_PARAM_CALLER : usize = 2; +pub(crate) const IDX_PARAM_CHAIN_ID : usize = 3; +pub(crate) const IDX_PARAM_CHAIN_OWNER_ID : usize = 4; +pub(crate) const IDX_PARAM_CONTRACT_CREATOR : usize = 5; +pub(crate) const IDX_PARAM_CONTRACT_ID : usize = 6; +pub(crate) const IDX_PARAM_COUNTER : usize = 7; +pub(crate) const IDX_PARAM_FAIL : usize = 8; +pub(crate) const IDX_PARAM_HASH : usize = 9; +pub(crate) const IDX_PARAM_HNAME : usize = 10; +pub(crate) const IDX_PARAM_HNAME_CONTRACT : usize = 11; +pub(crate) const IDX_PARAM_HNAME_EP : usize = 12; +pub(crate) const IDX_PARAM_HNAME_ZERO : usize = 13; +pub(crate) const IDX_PARAM_INT64 : usize = 14; +pub(crate) const IDX_PARAM_INT64_ZERO : usize = 15; +pub(crate) const IDX_PARAM_INT_VALUE : usize = 16; +pub(crate) const IDX_PARAM_NAME : usize = 17; +pub(crate) const IDX_PARAM_PROG_HASH : usize = 18; +pub(crate) const IDX_PARAM_STRING : usize = 19; +pub(crate) const IDX_PARAM_STRING_ZERO : usize = 20; +pub(crate) const IDX_PARAM_VAR_NAME : usize = 21; + +pub(crate) const IDX_RESULT_CHAIN_OWNER_ID : usize = 22; +pub(crate) const IDX_RESULT_COUNTER : usize = 23; +pub(crate) const IDX_RESULT_INT_VALUE : usize = 24; +pub(crate) const IDX_RESULT_MINTED_COLOR : usize = 25; +pub(crate) const IDX_RESULT_MINTED_SUPPLY : usize = 26; +pub(crate) const IDX_RESULT_SANDBOX_CALL : usize = 27; +pub(crate) const IDX_RESULT_VALUES : usize = 28; +pub(crate) const IDX_RESULT_VARS : usize = 29; -pub const KEY_MAP_LEN: usize = 33; +pub(crate) const IDX_STATE_COUNTER : usize = 30; +pub(crate) const IDX_STATE_HNAME_EP : usize = 31; +pub(crate) const IDX_STATE_INTS : usize = 32; +pub(crate) const IDX_STATE_MINTED_COLOR : usize = 33; +pub(crate) const IDX_STATE_MINTED_SUPPLY : usize = 34; + +pub const KEY_MAP_LEN: usize = 35; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ - PARAM_ADDRESS, - PARAM_AGENT_ID, - PARAM_CALLER, - PARAM_CHAIN_ID, - PARAM_CHAIN_OWNER_ID, - PARAM_CONTRACT_CREATOR, - PARAM_CONTRACT_ID, - PARAM_COUNTER, - PARAM_FAIL, - PARAM_HASH, - PARAM_HNAME, - PARAM_HNAME_CONTRACT, - PARAM_HNAME_EP, - PARAM_HNAME_ZERO, - PARAM_INT64, - PARAM_INT64_ZERO, - PARAM_INT_VALUE, - PARAM_NAME, - PARAM_PROG_HASH, - PARAM_STRING, - PARAM_STRING_ZERO, - PARAM_VAR_NAME, - RESULT_CHAIN_OWNER_ID, - RESULT_COUNTER, - RESULT_INT_VALUE, - RESULT_MINTED_COLOR, - RESULT_MINTED_SUPPLY, - RESULT_SANDBOX_CALL, - STATE_COUNTER, - STATE_HNAME_EP, - STATE_INTS, - STATE_MINTED_COLOR, - STATE_MINTED_SUPPLY, + PARAM_ADDRESS, + PARAM_AGENT_ID, + PARAM_CALLER, + PARAM_CHAIN_ID, + PARAM_CHAIN_OWNER_ID, + PARAM_CONTRACT_CREATOR, + PARAM_CONTRACT_ID, + PARAM_COUNTER, + PARAM_FAIL, + PARAM_HASH, + PARAM_HNAME, + PARAM_HNAME_CONTRACT, + PARAM_HNAME_EP, + PARAM_HNAME_ZERO, + PARAM_INT64, + PARAM_INT64_ZERO, + PARAM_INT_VALUE, + PARAM_NAME, + PARAM_PROG_HASH, + PARAM_STRING, + PARAM_STRING_ZERO, + PARAM_VAR_NAME, + RESULT_CHAIN_OWNER_ID, + RESULT_COUNTER, + RESULT_INT_VALUE, + RESULT_MINTED_COLOR, + RESULT_MINTED_SUPPLY, + RESULT_SANDBOX_CALL, + RESULT_VALUES, + RESULT_VARS, + STATE_COUNTER, + STATE_HNAME_EP, + STATE_INTS, + STATE_MINTED_COLOR, + STATE_MINTED_SUPPLY, ]; pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; @@ -92,5 +96,3 @@ pub fn idx_map(idx: usize) -> Key32 { IDX_MAP[idx] } } - -// @formatter:on diff --git a/contracts/wasm/testcore/src/lib.rs b/contracts/wasm/testcore/src/lib.rs index e114448688..d9e65ea0ae 100644 --- a/contracts/wasm/testcore/src/lib.rs +++ b/contracts/wasm/testcore/src/lib.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] #![allow(unused_imports)] @@ -31,38 +29,38 @@ mod testcore; #[no_mangle] fn on_load() { let exports = ScExports::new(); - exports.add_func(FUNC_CALL_ON_CHAIN, func_call_on_chain_thunk); - exports.add_func(FUNC_CHECK_CONTEXT_FROM_FULL_EP, func_check_context_from_full_ep_thunk); - exports.add_func(FUNC_DO_NOTHING, func_do_nothing_thunk); - exports.add_func(FUNC_GET_MINTED_SUPPLY, func_get_minted_supply_thunk); - exports.add_func(FUNC_INC_COUNTER, func_inc_counter_thunk); - exports.add_func(FUNC_INIT, func_init_thunk); - exports.add_func(FUNC_PASS_TYPES_FULL, func_pass_types_full_thunk); - exports.add_func(FUNC_RUN_RECURSION, func_run_recursion_thunk); - exports.add_func(FUNC_SEND_TO_ADDRESS, func_send_to_address_thunk); - exports.add_func(FUNC_SET_INT, func_set_int_thunk); - exports.add_func(FUNC_SPAWN, func_spawn_thunk); - exports.add_func(FUNC_TEST_BLOCK_CONTEXT1, func_test_block_context1_thunk); - exports.add_func(FUNC_TEST_BLOCK_CONTEXT2, func_test_block_context2_thunk); - exports.add_func(FUNC_TEST_CALL_PANIC_FULL_EP, func_test_call_panic_full_ep_thunk); + exports.add_func(FUNC_CALL_ON_CHAIN, func_call_on_chain_thunk); + exports.add_func(FUNC_CHECK_CONTEXT_FROM_FULL_EP, func_check_context_from_full_ep_thunk); + exports.add_func(FUNC_DO_NOTHING, func_do_nothing_thunk); + exports.add_func(FUNC_GET_MINTED_SUPPLY, func_get_minted_supply_thunk); + exports.add_func(FUNC_INC_COUNTER, func_inc_counter_thunk); + exports.add_func(FUNC_INIT, func_init_thunk); + exports.add_func(FUNC_PASS_TYPES_FULL, func_pass_types_full_thunk); + exports.add_func(FUNC_RUN_RECURSION, func_run_recursion_thunk); + exports.add_func(FUNC_SEND_TO_ADDRESS, func_send_to_address_thunk); + exports.add_func(FUNC_SET_INT, func_set_int_thunk); + exports.add_func(FUNC_SPAWN, func_spawn_thunk); + exports.add_func(FUNC_TEST_BLOCK_CONTEXT1, func_test_block_context1_thunk); + exports.add_func(FUNC_TEST_BLOCK_CONTEXT2, func_test_block_context2_thunk); + exports.add_func(FUNC_TEST_CALL_PANIC_FULL_EP, func_test_call_panic_full_ep_thunk); exports.add_func(FUNC_TEST_CALL_PANIC_VIEW_EP_FROM_FULL, func_test_call_panic_view_ep_from_full_thunk); - exports.add_func(FUNC_TEST_CHAIN_OWNER_ID_FULL, func_test_chain_owner_id_full_thunk); - exports.add_func(FUNC_TEST_EVENT_LOG_DEPLOY, func_test_event_log_deploy_thunk); - exports.add_func(FUNC_TEST_EVENT_LOG_EVENT_DATA, func_test_event_log_event_data_thunk); - exports.add_func(FUNC_TEST_EVENT_LOG_GENERIC_DATA, func_test_event_log_generic_data_thunk); - exports.add_func(FUNC_TEST_PANIC_FULL_EP, func_test_panic_full_ep_thunk); - exports.add_func(FUNC_WITHDRAW_TO_CHAIN, func_withdraw_to_chain_thunk); - exports.add_view(VIEW_CHECK_CONTEXT_FROM_VIEW_EP, view_check_context_from_view_ep_thunk); - exports.add_view(VIEW_FIBONACCI, view_fibonacci_thunk); - exports.add_view(VIEW_GET_COUNTER, view_get_counter_thunk); - exports.add_view(VIEW_GET_INT, view_get_int_thunk); - exports.add_view(VIEW_GET_STRING_VALUE, view_get_string_value_thunk); - exports.add_view(VIEW_JUST_VIEW, view_just_view_thunk); - exports.add_view(VIEW_PASS_TYPES_VIEW, view_pass_types_view_thunk); + exports.add_func(FUNC_TEST_CHAIN_OWNER_ID_FULL, func_test_chain_owner_id_full_thunk); + exports.add_func(FUNC_TEST_EVENT_LOG_DEPLOY, func_test_event_log_deploy_thunk); + exports.add_func(FUNC_TEST_EVENT_LOG_EVENT_DATA, func_test_event_log_event_data_thunk); + exports.add_func(FUNC_TEST_EVENT_LOG_GENERIC_DATA, func_test_event_log_generic_data_thunk); + exports.add_func(FUNC_TEST_PANIC_FULL_EP, func_test_panic_full_ep_thunk); + exports.add_func(FUNC_WITHDRAW_TO_CHAIN, func_withdraw_to_chain_thunk); + exports.add_view(VIEW_CHECK_CONTEXT_FROM_VIEW_EP, view_check_context_from_view_ep_thunk); + exports.add_view(VIEW_FIBONACCI, view_fibonacci_thunk); + exports.add_view(VIEW_GET_COUNTER, view_get_counter_thunk); + exports.add_view(VIEW_GET_INT, view_get_int_thunk); + exports.add_view(VIEW_GET_STRING_VALUE, view_get_string_value_thunk); + exports.add_view(VIEW_JUST_VIEW, view_just_view_thunk); + exports.add_view(VIEW_PASS_TYPES_VIEW, view_pass_types_view_thunk); exports.add_view(VIEW_TEST_CALL_PANIC_VIEW_EP_FROM_VIEW, view_test_call_panic_view_ep_from_view_thunk); - exports.add_view(VIEW_TEST_CHAIN_OWNER_ID_VIEW, view_test_chain_owner_id_view_thunk); - exports.add_view(VIEW_TEST_PANIC_VIEW_EP, view_test_panic_view_ep_thunk); - exports.add_view(VIEW_TEST_SANDBOX_CALL, view_test_sandbox_call_thunk); + exports.add_view(VIEW_TEST_CHAIN_OWNER_ID_VIEW, view_test_chain_owner_id_view_thunk); + exports.add_view(VIEW_TEST_PANIC_VIEW_EP, view_test_panic_view_ep_thunk); + exports.add_view(VIEW_TEST_SANDBOX_CALL, view_test_sandbox_call_thunk); unsafe { for i in 0..KEY_MAP_LEN { @@ -72,627 +70,625 @@ fn on_load() { } pub struct CallOnChainContext { - params: ImmutableCallOnChainParams, - results: MutableCallOnChainResults, - state: MutableTestCoreState, + params: ImmutableCallOnChainParams, + results: MutableCallOnChainResults, + state: MutableTestCoreState, } fn func_call_on_chain_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcCallOnChain"); - let f = CallOnChainContext { - params: ImmutableCallOnChainParams { - id: OBJ_ID_PARAMS, - }, - results: MutableCallOnChainResults { - id: OBJ_ID_RESULTS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.int_value().exists(), "missing mandatory intValue"); - func_call_on_chain(ctx, &f); - ctx.log("testcore.funcCallOnChain ok"); + ctx.log("testcore.funcCallOnChain"); + let f = CallOnChainContext { + params: ImmutableCallOnChainParams { + id: OBJ_ID_PARAMS, + }, + results: MutableCallOnChainResults { + id: OBJ_ID_RESULTS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.int_value().exists(), "missing mandatory intValue"); + func_call_on_chain(ctx, &f); + ctx.log("testcore.funcCallOnChain ok"); } pub struct CheckContextFromFullEPContext { - params: ImmutableCheckContextFromFullEPParams, - state: MutableTestCoreState, + params: ImmutableCheckContextFromFullEPParams, + state: MutableTestCoreState, } fn func_check_context_from_full_ep_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcCheckContextFromFullEP"); - let f = CheckContextFromFullEPContext { - params: ImmutableCheckContextFromFullEPParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.agent_id().exists(), "missing mandatory agentID"); - ctx.require(f.params.caller().exists(), "missing mandatory caller"); - ctx.require(f.params.chain_id().exists(), "missing mandatory chainID"); - ctx.require(f.params.chain_owner_id().exists(), "missing mandatory chainOwnerID"); - ctx.require(f.params.contract_creator().exists(), "missing mandatory contractCreator"); - func_check_context_from_full_ep(ctx, &f); - ctx.log("testcore.funcCheckContextFromFullEP ok"); + ctx.log("testcore.funcCheckContextFromFullEP"); + let f = CheckContextFromFullEPContext { + params: ImmutableCheckContextFromFullEPParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.agent_id().exists(), "missing mandatory agentID"); + ctx.require(f.params.caller().exists(), "missing mandatory caller"); + ctx.require(f.params.chain_id().exists(), "missing mandatory chainID"); + ctx.require(f.params.chain_owner_id().exists(), "missing mandatory chainOwnerID"); + ctx.require(f.params.contract_creator().exists(), "missing mandatory contractCreator"); + func_check_context_from_full_ep(ctx, &f); + ctx.log("testcore.funcCheckContextFromFullEP ok"); } pub struct DoNothingContext { - state: MutableTestCoreState, + state: MutableTestCoreState, } fn func_do_nothing_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcDoNothing"); - let f = DoNothingContext { - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_do_nothing(ctx, &f); - ctx.log("testcore.funcDoNothing ok"); + ctx.log("testcore.funcDoNothing"); + let f = DoNothingContext { + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_do_nothing(ctx, &f); + ctx.log("testcore.funcDoNothing ok"); } pub struct GetMintedSupplyContext { - results: MutableGetMintedSupplyResults, - state: MutableTestCoreState, + results: MutableGetMintedSupplyResults, + state: MutableTestCoreState, } fn func_get_minted_supply_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcGetMintedSupply"); - let f = GetMintedSupplyContext { - results: MutableGetMintedSupplyResults { - id: OBJ_ID_RESULTS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_get_minted_supply(ctx, &f); - ctx.log("testcore.funcGetMintedSupply ok"); + ctx.log("testcore.funcGetMintedSupply"); + let f = GetMintedSupplyContext { + results: MutableGetMintedSupplyResults { + id: OBJ_ID_RESULTS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_get_minted_supply(ctx, &f); + ctx.log("testcore.funcGetMintedSupply ok"); } pub struct IncCounterContext { - state: MutableTestCoreState, + state: MutableTestCoreState, } fn func_inc_counter_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcIncCounter"); - let f = IncCounterContext { - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_inc_counter(ctx, &f); - ctx.log("testcore.funcIncCounter ok"); + ctx.log("testcore.funcIncCounter"); + let f = IncCounterContext { + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_inc_counter(ctx, &f); + ctx.log("testcore.funcIncCounter ok"); } pub struct InitContext { - params: ImmutableInitParams, - state: MutableTestCoreState, + params: ImmutableInitParams, + state: MutableTestCoreState, } fn func_init_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcInit"); - let f = InitContext { - params: ImmutableInitParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_init(ctx, &f); - ctx.log("testcore.funcInit ok"); + ctx.log("testcore.funcInit"); + let f = InitContext { + params: ImmutableInitParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_init(ctx, &f); + ctx.log("testcore.funcInit ok"); } pub struct PassTypesFullContext { - params: ImmutablePassTypesFullParams, - state: MutableTestCoreState, + params: ImmutablePassTypesFullParams, + state: MutableTestCoreState, } fn func_pass_types_full_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcPassTypesFull"); - let f = PassTypesFullContext { - params: ImmutablePassTypesFullParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.address().exists(), "missing mandatory address"); - ctx.require(f.params.agent_id().exists(), "missing mandatory agentID"); - ctx.require(f.params.chain_id().exists(), "missing mandatory chainID"); - ctx.require(f.params.contract_id().exists(), "missing mandatory contractID"); - ctx.require(f.params.hash().exists(), "missing mandatory hash"); - ctx.require(f.params.hname().exists(), "missing mandatory hname"); - ctx.require(f.params.hname_zero().exists(), "missing mandatory hnameZero"); - ctx.require(f.params.int64().exists(), "missing mandatory int64"); - ctx.require(f.params.int64_zero().exists(), "missing mandatory int64Zero"); - ctx.require(f.params.string().exists(), "missing mandatory string"); - ctx.require(f.params.string_zero().exists(), "missing mandatory stringZero"); - func_pass_types_full(ctx, &f); - ctx.log("testcore.funcPassTypesFull ok"); + ctx.log("testcore.funcPassTypesFull"); + let f = PassTypesFullContext { + params: ImmutablePassTypesFullParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.address().exists(), "missing mandatory address"); + ctx.require(f.params.agent_id().exists(), "missing mandatory agentID"); + ctx.require(f.params.chain_id().exists(), "missing mandatory chainID"); + ctx.require(f.params.contract_id().exists(), "missing mandatory contractID"); + ctx.require(f.params.hash().exists(), "missing mandatory hash"); + ctx.require(f.params.hname().exists(), "missing mandatory hname"); + ctx.require(f.params.hname_zero().exists(), "missing mandatory hnameZero"); + ctx.require(f.params.int64().exists(), "missing mandatory int64"); + ctx.require(f.params.int64_zero().exists(), "missing mandatory int64Zero"); + ctx.require(f.params.string().exists(), "missing mandatory string"); + ctx.require(f.params.string_zero().exists(), "missing mandatory stringZero"); + func_pass_types_full(ctx, &f); + ctx.log("testcore.funcPassTypesFull ok"); } pub struct RunRecursionContext { - params: ImmutableRunRecursionParams, - results: MutableRunRecursionResults, - state: MutableTestCoreState, + params: ImmutableRunRecursionParams, + results: MutableRunRecursionResults, + state: MutableTestCoreState, } fn func_run_recursion_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcRunRecursion"); - let f = RunRecursionContext { - params: ImmutableRunRecursionParams { - id: OBJ_ID_PARAMS, - }, - results: MutableRunRecursionResults { - id: OBJ_ID_RESULTS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.int_value().exists(), "missing mandatory intValue"); - func_run_recursion(ctx, &f); - ctx.log("testcore.funcRunRecursion ok"); + ctx.log("testcore.funcRunRecursion"); + let f = RunRecursionContext { + params: ImmutableRunRecursionParams { + id: OBJ_ID_PARAMS, + }, + results: MutableRunRecursionResults { + id: OBJ_ID_RESULTS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.int_value().exists(), "missing mandatory intValue"); + func_run_recursion(ctx, &f); + ctx.log("testcore.funcRunRecursion ok"); } pub struct SendToAddressContext { - params: ImmutableSendToAddressParams, - state: MutableTestCoreState, + params: ImmutableSendToAddressParams, + state: MutableTestCoreState, } fn func_send_to_address_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcSendToAddress"); - ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); - - let f = SendToAddressContext { - params: ImmutableSendToAddressParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.address().exists(), "missing mandatory address"); - func_send_to_address(ctx, &f); - ctx.log("testcore.funcSendToAddress ok"); + ctx.log("testcore.funcSendToAddress"); + ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); + + let f = SendToAddressContext { + params: ImmutableSendToAddressParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.address().exists(), "missing mandatory address"); + func_send_to_address(ctx, &f); + ctx.log("testcore.funcSendToAddress ok"); } pub struct SetIntContext { - params: ImmutableSetIntParams, - state: MutableTestCoreState, + params: ImmutableSetIntParams, + state: MutableTestCoreState, } fn func_set_int_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcSetInt"); - let f = SetIntContext { - params: ImmutableSetIntParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.int_value().exists(), "missing mandatory intValue"); - ctx.require(f.params.name().exists(), "missing mandatory name"); - func_set_int(ctx, &f); - ctx.log("testcore.funcSetInt ok"); + ctx.log("testcore.funcSetInt"); + let f = SetIntContext { + params: ImmutableSetIntParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.int_value().exists(), "missing mandatory intValue"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + func_set_int(ctx, &f); + ctx.log("testcore.funcSetInt ok"); } pub struct SpawnContext { - params: ImmutableSpawnParams, - state: MutableTestCoreState, + params: ImmutableSpawnParams, + state: MutableTestCoreState, } fn func_spawn_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcSpawn"); - let f = SpawnContext { - params: ImmutableSpawnParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.prog_hash().exists(), "missing mandatory progHash"); - func_spawn(ctx, &f); - ctx.log("testcore.funcSpawn ok"); + ctx.log("testcore.funcSpawn"); + let f = SpawnContext { + params: ImmutableSpawnParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.prog_hash().exists(), "missing mandatory progHash"); + func_spawn(ctx, &f); + ctx.log("testcore.funcSpawn ok"); } pub struct TestBlockContext1Context { - state: MutableTestCoreState, + state: MutableTestCoreState, } fn func_test_block_context1_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcTestBlockContext1"); - let f = TestBlockContext1Context { - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_test_block_context1(ctx, &f); - ctx.log("testcore.funcTestBlockContext1 ok"); + ctx.log("testcore.funcTestBlockContext1"); + let f = TestBlockContext1Context { + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_test_block_context1(ctx, &f); + ctx.log("testcore.funcTestBlockContext1 ok"); } pub struct TestBlockContext2Context { - state: MutableTestCoreState, + state: MutableTestCoreState, } fn func_test_block_context2_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcTestBlockContext2"); - let f = TestBlockContext2Context { - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_test_block_context2(ctx, &f); - ctx.log("testcore.funcTestBlockContext2 ok"); + ctx.log("testcore.funcTestBlockContext2"); + let f = TestBlockContext2Context { + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_test_block_context2(ctx, &f); + ctx.log("testcore.funcTestBlockContext2 ok"); } pub struct TestCallPanicFullEPContext { - state: MutableTestCoreState, + state: MutableTestCoreState, } fn func_test_call_panic_full_ep_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcTestCallPanicFullEP"); - let f = TestCallPanicFullEPContext { - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_test_call_panic_full_ep(ctx, &f); - ctx.log("testcore.funcTestCallPanicFullEP ok"); + ctx.log("testcore.funcTestCallPanicFullEP"); + let f = TestCallPanicFullEPContext { + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_test_call_panic_full_ep(ctx, &f); + ctx.log("testcore.funcTestCallPanicFullEP ok"); } pub struct TestCallPanicViewEPFromFullContext { - state: MutableTestCoreState, + state: MutableTestCoreState, } fn func_test_call_panic_view_ep_from_full_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcTestCallPanicViewEPFromFull"); - let f = TestCallPanicViewEPFromFullContext { - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_test_call_panic_view_ep_from_full(ctx, &f); - ctx.log("testcore.funcTestCallPanicViewEPFromFull ok"); + ctx.log("testcore.funcTestCallPanicViewEPFromFull"); + let f = TestCallPanicViewEPFromFullContext { + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_test_call_panic_view_ep_from_full(ctx, &f); + ctx.log("testcore.funcTestCallPanicViewEPFromFull ok"); } pub struct TestChainOwnerIDFullContext { - results: MutableTestChainOwnerIDFullResults, - state: MutableTestCoreState, + results: MutableTestChainOwnerIDFullResults, + state: MutableTestCoreState, } fn func_test_chain_owner_id_full_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcTestChainOwnerIDFull"); - let f = TestChainOwnerIDFullContext { - results: MutableTestChainOwnerIDFullResults { - id: OBJ_ID_RESULTS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_test_chain_owner_id_full(ctx, &f); - ctx.log("testcore.funcTestChainOwnerIDFull ok"); + ctx.log("testcore.funcTestChainOwnerIDFull"); + let f = TestChainOwnerIDFullContext { + results: MutableTestChainOwnerIDFullResults { + id: OBJ_ID_RESULTS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_test_chain_owner_id_full(ctx, &f); + ctx.log("testcore.funcTestChainOwnerIDFull ok"); } pub struct TestEventLogDeployContext { - state: MutableTestCoreState, + state: MutableTestCoreState, } fn func_test_event_log_deploy_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcTestEventLogDeploy"); - let f = TestEventLogDeployContext { - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_test_event_log_deploy(ctx, &f); - ctx.log("testcore.funcTestEventLogDeploy ok"); + ctx.log("testcore.funcTestEventLogDeploy"); + let f = TestEventLogDeployContext { + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_test_event_log_deploy(ctx, &f); + ctx.log("testcore.funcTestEventLogDeploy ok"); } pub struct TestEventLogEventDataContext { - state: MutableTestCoreState, + state: MutableTestCoreState, } fn func_test_event_log_event_data_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcTestEventLogEventData"); - let f = TestEventLogEventDataContext { - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_test_event_log_event_data(ctx, &f); - ctx.log("testcore.funcTestEventLogEventData ok"); + ctx.log("testcore.funcTestEventLogEventData"); + let f = TestEventLogEventDataContext { + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_test_event_log_event_data(ctx, &f); + ctx.log("testcore.funcTestEventLogEventData ok"); } pub struct TestEventLogGenericDataContext { - params: ImmutableTestEventLogGenericDataParams, - state: MutableTestCoreState, + params: ImmutableTestEventLogGenericDataParams, + state: MutableTestCoreState, } fn func_test_event_log_generic_data_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcTestEventLogGenericData"); - let f = TestEventLogGenericDataContext { - params: ImmutableTestEventLogGenericDataParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.counter().exists(), "missing mandatory counter"); - func_test_event_log_generic_data(ctx, &f); - ctx.log("testcore.funcTestEventLogGenericData ok"); + ctx.log("testcore.funcTestEventLogGenericData"); + let f = TestEventLogGenericDataContext { + params: ImmutableTestEventLogGenericDataParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.counter().exists(), "missing mandatory counter"); + func_test_event_log_generic_data(ctx, &f); + ctx.log("testcore.funcTestEventLogGenericData ok"); } pub struct TestPanicFullEPContext { - state: MutableTestCoreState, + state: MutableTestCoreState, } fn func_test_panic_full_ep_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcTestPanicFullEP"); - let f = TestPanicFullEPContext { - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - func_test_panic_full_ep(ctx, &f); - ctx.log("testcore.funcTestPanicFullEP ok"); + ctx.log("testcore.funcTestPanicFullEP"); + let f = TestPanicFullEPContext { + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + func_test_panic_full_ep(ctx, &f); + ctx.log("testcore.funcTestPanicFullEP ok"); } pub struct WithdrawToChainContext { - params: ImmutableWithdrawToChainParams, - state: MutableTestCoreState, + params: ImmutableWithdrawToChainParams, + state: MutableTestCoreState, } fn func_withdraw_to_chain_thunk(ctx: &ScFuncContext) { - ctx.log("testcore.funcWithdrawToChain"); - let f = WithdrawToChainContext { - params: ImmutableWithdrawToChainParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.chain_id().exists(), "missing mandatory chainID"); - func_withdraw_to_chain(ctx, &f); - ctx.log("testcore.funcWithdrawToChain ok"); + ctx.log("testcore.funcWithdrawToChain"); + let f = WithdrawToChainContext { + params: ImmutableWithdrawToChainParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.chain_id().exists(), "missing mandatory chainID"); + func_withdraw_to_chain(ctx, &f); + ctx.log("testcore.funcWithdrawToChain ok"); } pub struct CheckContextFromViewEPContext { - params: ImmutableCheckContextFromViewEPParams, - state: ImmutableTestCoreState, + params: ImmutableCheckContextFromViewEPParams, + state: ImmutableTestCoreState, } fn view_check_context_from_view_ep_thunk(ctx: &ScViewContext) { - ctx.log("testcore.viewCheckContextFromViewEP"); - let f = CheckContextFromViewEPContext { - params: ImmutableCheckContextFromViewEPParams { - id: OBJ_ID_PARAMS, - }, - state: ImmutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.agent_id().exists(), "missing mandatory agentID"); - ctx.require(f.params.chain_id().exists(), "missing mandatory chainID"); - ctx.require(f.params.chain_owner_id().exists(), "missing mandatory chainOwnerID"); - ctx.require(f.params.contract_creator().exists(), "missing mandatory contractCreator"); - view_check_context_from_view_ep(ctx, &f); - ctx.log("testcore.viewCheckContextFromViewEP ok"); + ctx.log("testcore.viewCheckContextFromViewEP"); + let f = CheckContextFromViewEPContext { + params: ImmutableCheckContextFromViewEPParams { + id: OBJ_ID_PARAMS, + }, + state: ImmutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.agent_id().exists(), "missing mandatory agentID"); + ctx.require(f.params.chain_id().exists(), "missing mandatory chainID"); + ctx.require(f.params.chain_owner_id().exists(), "missing mandatory chainOwnerID"); + ctx.require(f.params.contract_creator().exists(), "missing mandatory contractCreator"); + view_check_context_from_view_ep(ctx, &f); + ctx.log("testcore.viewCheckContextFromViewEP ok"); } pub struct FibonacciContext { - params: ImmutableFibonacciParams, - results: MutableFibonacciResults, - state: ImmutableTestCoreState, + params: ImmutableFibonacciParams, + results: MutableFibonacciResults, + state: ImmutableTestCoreState, } fn view_fibonacci_thunk(ctx: &ScViewContext) { - ctx.log("testcore.viewFibonacci"); - let f = FibonacciContext { - params: ImmutableFibonacciParams { - id: OBJ_ID_PARAMS, - }, - results: MutableFibonacciResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.int_value().exists(), "missing mandatory intValue"); - view_fibonacci(ctx, &f); - ctx.log("testcore.viewFibonacci ok"); + ctx.log("testcore.viewFibonacci"); + let f = FibonacciContext { + params: ImmutableFibonacciParams { + id: OBJ_ID_PARAMS, + }, + results: MutableFibonacciResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.int_value().exists(), "missing mandatory intValue"); + view_fibonacci(ctx, &f); + ctx.log("testcore.viewFibonacci ok"); } pub struct GetCounterContext { - results: MutableGetCounterResults, - state: ImmutableTestCoreState, + results: MutableGetCounterResults, + state: ImmutableTestCoreState, } fn view_get_counter_thunk(ctx: &ScViewContext) { - ctx.log("testcore.viewGetCounter"); - let f = GetCounterContext { - results: MutableGetCounterResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - view_get_counter(ctx, &f); - ctx.log("testcore.viewGetCounter ok"); + ctx.log("testcore.viewGetCounter"); + let f = GetCounterContext { + results: MutableGetCounterResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + view_get_counter(ctx, &f); + ctx.log("testcore.viewGetCounter ok"); } pub struct GetIntContext { - params: ImmutableGetIntParams, - results: MutableGetIntResults, - state: ImmutableTestCoreState, + params: ImmutableGetIntParams, + results: MutableGetIntResults, + state: ImmutableTestCoreState, } fn view_get_int_thunk(ctx: &ScViewContext) { - ctx.log("testcore.viewGetInt"); - let f = GetIntContext { - params: ImmutableGetIntParams { - id: OBJ_ID_PARAMS, - }, - results: MutableGetIntResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.name().exists(), "missing mandatory name"); - view_get_int(ctx, &f); - ctx.log("testcore.viewGetInt ok"); + ctx.log("testcore.viewGetInt"); + let f = GetIntContext { + params: ImmutableGetIntParams { + id: OBJ_ID_PARAMS, + }, + results: MutableGetIntResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.name().exists(), "missing mandatory name"); + view_get_int(ctx, &f); + ctx.log("testcore.viewGetInt ok"); } pub struct GetStringValueContext { - params: ImmutableGetStringValueParams, - results: MutableGetStringValueResults, - state: ImmutableTestCoreState, + params: ImmutableGetStringValueParams, + results: MutableGetStringValueResults, + state: ImmutableTestCoreState, } fn view_get_string_value_thunk(ctx: &ScViewContext) { - ctx.log("testcore.viewGetStringValue"); - let f = GetStringValueContext { - params: ImmutableGetStringValueParams { - id: OBJ_ID_PARAMS, - }, - results: MutableGetStringValueResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.var_name().exists(), "missing mandatory varName"); - view_get_string_value(ctx, &f); - ctx.log("testcore.viewGetStringValue ok"); + ctx.log("testcore.viewGetStringValue"); + let f = GetStringValueContext { + params: ImmutableGetStringValueParams { + id: OBJ_ID_PARAMS, + }, + results: MutableGetStringValueResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.var_name().exists(), "missing mandatory varName"); + view_get_string_value(ctx, &f); + ctx.log("testcore.viewGetStringValue ok"); } pub struct JustViewContext { - state: ImmutableTestCoreState, + state: ImmutableTestCoreState, } fn view_just_view_thunk(ctx: &ScViewContext) { - ctx.log("testcore.viewJustView"); - let f = JustViewContext { - state: ImmutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - view_just_view(ctx, &f); - ctx.log("testcore.viewJustView ok"); + ctx.log("testcore.viewJustView"); + let f = JustViewContext { + state: ImmutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + view_just_view(ctx, &f); + ctx.log("testcore.viewJustView ok"); } pub struct PassTypesViewContext { - params: ImmutablePassTypesViewParams, - state: ImmutableTestCoreState, + params: ImmutablePassTypesViewParams, + state: ImmutableTestCoreState, } fn view_pass_types_view_thunk(ctx: &ScViewContext) { - ctx.log("testcore.viewPassTypesView"); - let f = PassTypesViewContext { - params: ImmutablePassTypesViewParams { - id: OBJ_ID_PARAMS, - }, - state: ImmutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.address().exists(), "missing mandatory address"); - ctx.require(f.params.agent_id().exists(), "missing mandatory agentID"); - ctx.require(f.params.chain_id().exists(), "missing mandatory chainID"); - ctx.require(f.params.contract_id().exists(), "missing mandatory contractID"); - ctx.require(f.params.hash().exists(), "missing mandatory hash"); - ctx.require(f.params.hname().exists(), "missing mandatory hname"); - ctx.require(f.params.hname_zero().exists(), "missing mandatory hnameZero"); - ctx.require(f.params.int64().exists(), "missing mandatory int64"); - ctx.require(f.params.int64_zero().exists(), "missing mandatory int64Zero"); - ctx.require(f.params.string().exists(), "missing mandatory string"); - ctx.require(f.params.string_zero().exists(), "missing mandatory stringZero"); - view_pass_types_view(ctx, &f); - ctx.log("testcore.viewPassTypesView ok"); + ctx.log("testcore.viewPassTypesView"); + let f = PassTypesViewContext { + params: ImmutablePassTypesViewParams { + id: OBJ_ID_PARAMS, + }, + state: ImmutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.address().exists(), "missing mandatory address"); + ctx.require(f.params.agent_id().exists(), "missing mandatory agentID"); + ctx.require(f.params.chain_id().exists(), "missing mandatory chainID"); + ctx.require(f.params.contract_id().exists(), "missing mandatory contractID"); + ctx.require(f.params.hash().exists(), "missing mandatory hash"); + ctx.require(f.params.hname().exists(), "missing mandatory hname"); + ctx.require(f.params.hname_zero().exists(), "missing mandatory hnameZero"); + ctx.require(f.params.int64().exists(), "missing mandatory int64"); + ctx.require(f.params.int64_zero().exists(), "missing mandatory int64Zero"); + ctx.require(f.params.string().exists(), "missing mandatory string"); + ctx.require(f.params.string_zero().exists(), "missing mandatory stringZero"); + view_pass_types_view(ctx, &f); + ctx.log("testcore.viewPassTypesView ok"); } pub struct TestCallPanicViewEPFromViewContext { - state: ImmutableTestCoreState, + state: ImmutableTestCoreState, } fn view_test_call_panic_view_ep_from_view_thunk(ctx: &ScViewContext) { - ctx.log("testcore.viewTestCallPanicViewEPFromView"); - let f = TestCallPanicViewEPFromViewContext { - state: ImmutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - view_test_call_panic_view_ep_from_view(ctx, &f); - ctx.log("testcore.viewTestCallPanicViewEPFromView ok"); + ctx.log("testcore.viewTestCallPanicViewEPFromView"); + let f = TestCallPanicViewEPFromViewContext { + state: ImmutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + view_test_call_panic_view_ep_from_view(ctx, &f); + ctx.log("testcore.viewTestCallPanicViewEPFromView ok"); } pub struct TestChainOwnerIDViewContext { - results: MutableTestChainOwnerIDViewResults, - state: ImmutableTestCoreState, + results: MutableTestChainOwnerIDViewResults, + state: ImmutableTestCoreState, } fn view_test_chain_owner_id_view_thunk(ctx: &ScViewContext) { - ctx.log("testcore.viewTestChainOwnerIDView"); - let f = TestChainOwnerIDViewContext { - results: MutableTestChainOwnerIDViewResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - view_test_chain_owner_id_view(ctx, &f); - ctx.log("testcore.viewTestChainOwnerIDView ok"); + ctx.log("testcore.viewTestChainOwnerIDView"); + let f = TestChainOwnerIDViewContext { + results: MutableTestChainOwnerIDViewResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + view_test_chain_owner_id_view(ctx, &f); + ctx.log("testcore.viewTestChainOwnerIDView ok"); } pub struct TestPanicViewEPContext { - state: ImmutableTestCoreState, + state: ImmutableTestCoreState, } fn view_test_panic_view_ep_thunk(ctx: &ScViewContext) { - ctx.log("testcore.viewTestPanicViewEP"); - let f = TestPanicViewEPContext { - state: ImmutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - view_test_panic_view_ep(ctx, &f); - ctx.log("testcore.viewTestPanicViewEP ok"); + ctx.log("testcore.viewTestPanicViewEP"); + let f = TestPanicViewEPContext { + state: ImmutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + view_test_panic_view_ep(ctx, &f); + ctx.log("testcore.viewTestPanicViewEP ok"); } pub struct TestSandboxCallContext { - results: MutableTestSandboxCallResults, - state: ImmutableTestCoreState, + results: MutableTestSandboxCallResults, + state: ImmutableTestCoreState, } fn view_test_sandbox_call_thunk(ctx: &ScViewContext) { - ctx.log("testcore.viewTestSandboxCall"); - let f = TestSandboxCallContext { - results: MutableTestSandboxCallResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableTestCoreState { - id: OBJ_ID_STATE, - }, - }; - view_test_sandbox_call(ctx, &f); - ctx.log("testcore.viewTestSandboxCall ok"); -} - -// @formatter:on + ctx.log("testcore.viewTestSandboxCall"); + let f = TestSandboxCallContext { + results: MutableTestSandboxCallResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestCoreState { + id: OBJ_ID_STATE, + }, + }; + view_test_sandbox_call(ctx, &f); + ctx.log("testcore.viewTestSandboxCall ok"); +} diff --git a/contracts/wasm/testcore/src/params.rs b/contracts/wasm/testcore/src/params.rs index 559caf1d68..ef58895846 100644 --- a/contracts/wasm/testcore/src/params.rs +++ b/contracts/wasm/testcore/src/params.rs @@ -21,16 +21,16 @@ 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, idx_map(IDX_PARAM_HNAME_CONTRACT)) + } pub fn hname_ep(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_EP)) - } + ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_EP)) + } pub fn int_value(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -40,16 +40,16 @@ 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, idx_map(IDX_PARAM_HNAME_CONTRACT)) + } pub fn hname_ep(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_EP)) - } + ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_EP)) + } pub fn int_value(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -59,24 +59,24 @@ 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, idx_map(IDX_PARAM_AGENT_ID)) + } pub fn caller(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CALLER)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CALLER)) + } pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) - } + ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + } pub fn chain_owner_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) + } pub fn contract_creator(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) + } } #[derive(Clone, Copy)] @@ -86,24 +86,24 @@ 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, idx_map(IDX_PARAM_AGENT_ID)) + } pub fn caller(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CALLER)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CALLER)) + } pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) - } + ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + } pub fn chain_owner_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) + } pub fn contract_creator(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) + } } #[derive(Clone, Copy)] @@ -113,8 +113,8 @@ pub struct ImmutableInitParams { impl ImmutableInitParams { pub fn fail(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_FAIL)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_FAIL)) + } } #[derive(Clone, Copy)] @@ -124,8 +124,8 @@ pub struct MutableInitParams { impl MutableInitParams { pub fn fail(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_FAIL)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_FAIL)) + } } #[derive(Clone, Copy)] @@ -135,48 +135,48 @@ pub struct ImmutablePassTypesFullParams { impl ImmutablePassTypesFullParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) - } + ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + } pub fn agent_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + } pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) - } + ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + } pub fn contract_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) + } pub fn hash(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) - } + ScImmutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + } pub fn hname(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) - } + ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + } pub fn hname_zero(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) - } + ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) + } pub fn int64(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + } pub fn int64_zero(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) + } pub fn string(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + } pub fn string_zero(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) + } } #[derive(Clone, Copy)] @@ -186,48 +186,48 @@ pub struct MutablePassTypesFullParams { impl MutablePassTypesFullParams { pub fn address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) - } + ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + } pub fn agent_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + } pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) - } + ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + } pub fn contract_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) + } pub fn hash(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) - } + ScMutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + } pub fn hname(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) - } + ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + } pub fn hname_zero(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) - } + ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) + } pub fn int64(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + } pub fn int64_zero(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) + } pub fn string(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + } pub fn string_zero(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) + } } #[derive(Clone, Copy)] @@ -237,8 +237,8 @@ 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, idx_map(IDX_PARAM_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -248,8 +248,8 @@ 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, idx_map(IDX_PARAM_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -259,8 +259,8 @@ pub struct ImmutableSendToAddressParams { impl ImmutableSendToAddressParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) - } + ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + } } #[derive(Clone, Copy)] @@ -270,8 +270,8 @@ pub struct MutableSendToAddressParams { impl MutableSendToAddressParams { pub fn address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) - } + ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + } } #[derive(Clone, Copy)] @@ -281,12 +281,12 @@ 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, idx_map(IDX_PARAM_INT_VALUE)) + } pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -296,12 +296,12 @@ 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, idx_map(IDX_PARAM_INT_VALUE)) + } pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -311,8 +311,8 @@ 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, idx_map(IDX_PARAM_PROG_HASH)) + } } #[derive(Clone, Copy)] @@ -322,8 +322,8 @@ 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, idx_map(IDX_PARAM_PROG_HASH)) + } } #[derive(Clone, Copy)] @@ -333,8 +333,8 @@ pub struct ImmutableTestEventLogGenericDataParams { impl ImmutableTestEventLogGenericDataParams { pub fn counter(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_COUNTER)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_COUNTER)) + } } #[derive(Clone, Copy)] @@ -344,8 +344,8 @@ pub struct MutableTestEventLogGenericDataParams { impl MutableTestEventLogGenericDataParams { pub fn counter(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_COUNTER)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_COUNTER)) + } } #[derive(Clone, Copy)] @@ -355,8 +355,8 @@ 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, idx_map(IDX_PARAM_CHAIN_ID)) + } } #[derive(Clone, Copy)] @@ -366,8 +366,8 @@ 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, idx_map(IDX_PARAM_CHAIN_ID)) + } } #[derive(Clone, Copy)] @@ -377,20 +377,20 @@ 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, idx_map(IDX_PARAM_AGENT_ID)) + } pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) - } + ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + } pub fn chain_owner_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) + } pub fn contract_creator(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) + } } #[derive(Clone, Copy)] @@ -400,20 +400,20 @@ 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, idx_map(IDX_PARAM_AGENT_ID)) + } pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) - } + ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + } pub fn chain_owner_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CHAIN_OWNER_ID)) + } pub fn contract_creator(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_CREATOR)) + } } #[derive(Clone, Copy)] @@ -423,8 +423,8 @@ 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, idx_map(IDX_PARAM_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -434,8 +434,8 @@ 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, idx_map(IDX_PARAM_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -445,8 +445,8 @@ pub struct ImmutableGetIntParams { impl ImmutableGetIntParams { pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -456,8 +456,8 @@ pub struct MutableGetIntParams { impl MutableGetIntParams { pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -467,8 +467,8 @@ 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, idx_map(IDX_PARAM_VAR_NAME)) + } } #[derive(Clone, Copy)] @@ -478,8 +478,8 @@ 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, idx_map(IDX_PARAM_VAR_NAME)) + } } #[derive(Clone, Copy)] @@ -489,48 +489,48 @@ pub struct ImmutablePassTypesViewParams { impl ImmutablePassTypesViewParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) - } + ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + } pub fn agent_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + } pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) - } + ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + } pub fn contract_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) + } pub fn hash(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) - } + ScImmutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + } pub fn hname(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) - } + ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + } pub fn hname_zero(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) - } + ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) + } pub fn int64(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + } pub fn int64_zero(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) + } pub fn string(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + } pub fn string_zero(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) + } } #[derive(Clone, Copy)] @@ -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, idx_map(IDX_PARAM_ADDRESS)) + } pub fn agent_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + } pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) - } + ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + } pub fn contract_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_CONTRACT_ID)) + } pub fn hash(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) - } + ScMutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + } pub fn hname(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) - } + ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + } pub fn hname_zero(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) - } + ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME_ZERO)) + } pub fn int64(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + } pub fn int64_zero(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64_ZERO)) + } pub fn string(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + } pub fn string_zero(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING_ZERO)) + } } diff --git a/contracts/wasm/testcore/src/results.rs b/contracts/wasm/testcore/src/results.rs index 6c038b65fe..974409c2dc 100644 --- a/contracts/wasm/testcore/src/results.rs +++ b/contracts/wasm/testcore/src/results.rs @@ -21,8 +21,8 @@ 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, idx_map(IDX_RESULT_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -32,8 +32,8 @@ 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, idx_map(IDX_RESULT_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -43,12 +43,12 @@ 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, idx_map(IDX_RESULT_MINTED_COLOR)) + } pub fn minted_supply(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_MINTED_SUPPLY)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_MINTED_SUPPLY)) + } } #[derive(Clone, Copy)] @@ -58,12 +58,12 @@ 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, idx_map(IDX_RESULT_MINTED_COLOR)) + } pub fn minted_supply(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_MINTED_SUPPLY)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_MINTED_SUPPLY)) + } } #[derive(Clone, Copy)] @@ -73,8 +73,8 @@ 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, idx_map(IDX_RESULT_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -84,8 +84,8 @@ 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, idx_map(IDX_RESULT_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -95,8 +95,8 @@ 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, idx_map(IDX_RESULT_CHAIN_OWNER_ID)) + } } #[derive(Clone, Copy)] @@ -106,8 +106,8 @@ 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, idx_map(IDX_RESULT_CHAIN_OWNER_ID)) + } } #[derive(Clone, Copy)] @@ -117,8 +117,8 @@ 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, idx_map(IDX_RESULT_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -128,8 +128,8 @@ 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, idx_map(IDX_RESULT_INT_VALUE)) + } } #[derive(Clone, Copy)] @@ -139,8 +139,8 @@ pub struct ImmutableGetCounterResults { impl ImmutableGetCounterResults { pub fn counter(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_COUNTER)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_COUNTER)) + } } #[derive(Clone, Copy)] @@ -150,12 +150,12 @@ pub struct MutableGetCounterResults { impl MutableGetCounterResults { pub fn counter(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_COUNTER)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_COUNTER)) + } } pub struct MapStringToImmutableInt64 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToImmutableInt64 { @@ -171,17 +171,17 @@ pub struct ImmutableGetIntResults { impl ImmutableGetIntResults { pub fn values(&self) -> MapStringToImmutableInt64 { - MapStringToImmutableInt64 { obj_id: self.id } - } + MapStringToImmutableInt64 { obj_id: self.id } + } } pub struct MapStringToMutableInt64 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToMutableInt64 { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_int64(&self, key: &str) -> ScMutableInt64 { @@ -196,12 +196,12 @@ pub struct MutableGetIntResults { impl MutableGetIntResults { pub fn values(&self) -> MapStringToMutableInt64 { - MapStringToMutableInt64 { obj_id: self.id } - } + MapStringToMutableInt64 { obj_id: self.id } + } } pub struct MapStringToImmutableString { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToImmutableString { @@ -217,17 +217,17 @@ pub struct ImmutableGetStringValueResults { impl ImmutableGetStringValueResults { pub fn vars(&self) -> MapStringToImmutableString { - MapStringToImmutableString { obj_id: self.id } - } + MapStringToImmutableString { obj_id: self.id } + } } pub struct MapStringToMutableString { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToMutableString { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_string(&self, key: &str) -> ScMutableString { @@ -242,8 +242,8 @@ pub struct MutableGetStringValueResults { impl MutableGetStringValueResults { pub fn vars(&self) -> MapStringToMutableString { - MapStringToMutableString { obj_id: self.id } - } + MapStringToMutableString { obj_id: self.id } + } } #[derive(Clone, Copy)] @@ -253,8 +253,8 @@ 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, idx_map(IDX_RESULT_CHAIN_OWNER_ID)) + } } #[derive(Clone, Copy)] @@ -264,8 +264,8 @@ 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, idx_map(IDX_RESULT_CHAIN_OWNER_ID)) + } } #[derive(Clone, Copy)] @@ -275,8 +275,8 @@ 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, idx_map(IDX_RESULT_SANDBOX_CALL)) + } } #[derive(Clone, Copy)] @@ -286,6 +286,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, idx_map(IDX_RESULT_SANDBOX_CALL)) + } } diff --git a/contracts/wasm/testcore/src/state.rs b/contracts/wasm/testcore/src/state.rs index 55d9caa8c8..1f62a862ac 100644 --- a/contracts/wasm/testcore/src/state.rs +++ b/contracts/wasm/testcore/src/state.rs @@ -21,25 +21,25 @@ pub struct ImmutableTestCoreState { impl ImmutableTestCoreState { pub fn counter(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) + } pub fn hname_ep(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_STATE_HNAME_EP)) - } + ScImmutableHname::new(self.id, idx_map(IDX_STATE_HNAME_EP)) + } pub fn ints(&self) -> MapStringToImmutableInt64 { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_INTS), TYPE_MAP); - MapStringToImmutableInt64 { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_INTS), 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, idx_map(IDX_STATE_MINTED_COLOR)) + } pub fn minted_supply(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_STATE_MINTED_SUPPLY)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_STATE_MINTED_SUPPLY)) + } } #[derive(Clone, Copy)] @@ -49,23 +49,23 @@ pub struct MutableTestCoreState { impl MutableTestCoreState { pub fn counter(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) - } + ScMutableInt64::new(self.id, idx_map(IDX_STATE_COUNTER)) + } pub fn hname_ep(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_STATE_HNAME_EP)) - } + ScMutableHname::new(self.id, idx_map(IDX_STATE_HNAME_EP)) + } pub fn ints(&self) -> MapStringToMutableInt64 { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_INTS), TYPE_MAP); - MapStringToMutableInt64 { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_INTS), 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, idx_map(IDX_STATE_MINTED_COLOR)) + } pub fn minted_supply(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_STATE_MINTED_SUPPLY)) - } + ScMutableInt64::new(self.id, idx_map(IDX_STATE_MINTED_SUPPLY)) + } } diff --git a/contracts/wasm/testcore/test/call_test.go b/contracts/wasm/testcore/test/call_test.go index 8adb54bf94..3221726f21 100644 --- a/contracts/wasm/testcore/test/call_test.go +++ b/contracts/wasm/testcore/test/call_test.go @@ -4,11 +4,10 @@ import ( "testing" "github.com/iotaledger/wasp/contracts/wasm/testcore/go/testcore" - "github.com/iotaledger/wasp/packages/vm/wasmsolo" "github.com/stretchr/testify/require" ) -const n = 10 +const fiboN = 10 func fibo(n int64) int64 { if n == 0 || n == 1 { @@ -19,39 +18,31 @@ func fibo(n int64) int64 { func TestCallFibonacci(t *testing.T) { run2(t, func(t *testing.T, w bool) { - if *wasmsolo.TsWasm { - t.SkipNow() - } - ctx := deployTestCore(t, w) f := testcore.ScFuncs.Fibonacci(ctx) - f.Params.IntValue().SetValue(n) + f.Params.IntValue().SetValue(fiboN) f.Func.Call() require.NoError(t, ctx.Err) result := f.Results.IntValue() require.True(t, result.Exists()) - require.EqualValues(t, fibo(n), result.Value()) + require.EqualValues(t, fibo(fiboN), result.Value()) }) } func TestCallFibonacciIndirect(t *testing.T) { run2(t, func(t *testing.T, w bool) { - if *wasmsolo.TsWasm { - t.SkipNow() - } - ctx := deployTestCore(t, w) f := testcore.ScFuncs.CallOnChain(ctx) - f.Params.IntValue().SetValue(n) + f.Params.IntValue().SetValue(fiboN) f.Params.HnameContract().SetValue(testcore.HScName) f.Params.HnameEP().SetValue(testcore.HViewFibonacci) f.Func.TransferIotas(1).Post() require.NoError(t, ctx.Err) result := f.Results.IntValue() require.True(t, result.Exists()) - require.EqualValues(t, fibo(n), result.Value()) + require.EqualValues(t, fibo(fiboN), result.Value()) v := testcore.ScFuncs.GetCounter(ctx) v.Func.Call() @@ -64,11 +55,6 @@ func TestCallFibonacciIndirect(t *testing.T) { func TestCallRecursive(t *testing.T) { run2(t, func(t *testing.T, w bool) { - // TODO need to adjust stack size for Go Wasm for this to succeed - if *wasmsolo.GoWasm || *wasmsolo.TsWasm { - t.SkipNow() - } - ctx := deployTestCore(t, w) f := testcore.ScFuncs.CallOnChain(ctx) diff --git a/contracts/wasm/testcore/test/concurrency_test.go b/contracts/wasm/testcore/test/concurrency_test.go index f380b86a1a..2d410b19ab 100644 --- a/contracts/wasm/testcore/test/concurrency_test.go +++ b/contracts/wasm/testcore/test/concurrency_test.go @@ -33,7 +33,7 @@ func TestCounter(t *testing.T) { func TestSynchronous(t *testing.T) { run2(t, func(t *testing.T, w bool) { // TODO fails with 999 instead of 1000 at WaitForPendingRequests - if *wasmsolo.GoDebug { + if *wasmsolo.GoDebug || *wasmsolo.GoWasmEdge { t.SkipNow() } ctx := deployTestCore(t, w) @@ -42,9 +42,15 @@ func TestSynchronous(t *testing.T) { f.Func.TransferIotas(1) repeats := []int{300, 100, 100, 100, 200, 100, 100} + if wasmsolo.SoloDebug { + for i := range repeats { + repeats[i] /= 10 + } + } + sum := 0 - for _, i := range repeats { - sum += i + for _, n := range repeats { + sum += n } for _, n := range repeats { @@ -58,7 +64,7 @@ func TestSynchronous(t *testing.T) { if w { reqs++ } - require.True(t, ctx.WaitForPendingRequests(-reqs, 60*time.Second)) + require.True(t, ctx.WaitForPendingRequests(-reqs, 180*time.Second)) v := testcore.ScFuncs.GetCounter(ctx) v.Func.Call() @@ -83,9 +89,15 @@ func TestConcurrency(t *testing.T) { WithIotas(1) repeats := []int{300, 100, 100, 100, 200, 100, 100} + if wasmsolo.SoloDebug { + for i := range repeats { + repeats[i] /= 10 + } + } + sum := 0 - for _, i := range repeats { - sum += i + for _, n := range repeats { + sum += n } chain := ctx.Chain @@ -98,7 +110,7 @@ func TestConcurrency(t *testing.T) { } }(r, n) } - require.True(t, ctx.WaitForPendingRequests(sum, 60*time.Second)) + require.True(t, ctx.WaitForPendingRequests(sum, 180*time.Second)) v := testcore.ScFuncs.GetCounter(ctx) v.Func.Call() @@ -123,9 +135,15 @@ func TestConcurrency2(t *testing.T) { WithIotas(1) repeats := []int{300, 100, 100, 100, 200, 100, 100} + if wasmsolo.SoloDebug { + for i := range repeats { + repeats[i] /= 10 + } + } + sum := 0 - for _, i := range repeats { - sum += i + for _, n := range repeats { + sum += n } chain := ctx.Chain @@ -141,7 +159,7 @@ func TestConcurrency2(t *testing.T) { }(r, n) } - require.True(t, ctx.WaitForPendingRequests(sum, 60*time.Second)) + require.True(t, ctx.WaitForPendingRequests(sum, 180*time.Second)) v := testcore.ScFuncs.GetCounter(ctx) v.Func.Call() @@ -166,7 +184,11 @@ func TestViewConcurrency(t *testing.T) { f := testcore.ScFuncs.IncCounter(ctx) f.Func.TransferIotas(1).Post() - const times = 2000 + times := 2000 + if wasmsolo.SoloDebug { + times /= 10 + } + channels := make(chan error, times) chain := ctx.Chain for i := 0; i < times; i++ { diff --git a/contracts/wasm/testcore/test/spawn_test.go b/contracts/wasm/testcore/test/spawn_test.go index 71d11c0256..7be97ab57e 100644 --- a/contracts/wasm/testcore/test/spawn_test.go +++ b/contracts/wasm/testcore/test/spawn_test.go @@ -5,17 +5,11 @@ import ( "github.com/iotaledger/wasp/contracts/wasm/testcore/go/testcore" "github.com/iotaledger/wasp/packages/vm/core" - "github.com/iotaledger/wasp/packages/vm/wasmsolo" "github.com/stretchr/testify/require" ) func TestSpawn(t *testing.T) { run2(t, func(t *testing.T, w bool) { - // TODO need to save globals for TypeScript Wasm for this to succeed - if *wasmsolo.TsWasm { - t.SkipNow() - } - ctx := deployTestCore(t, w) f := testcore.ScFuncs.Spawn(ctx) diff --git a/contracts/wasm/testcore/test/testcore_bg.wasm b/contracts/wasm/testcore/test/testcore_bg.wasm index c7701951f2..e3b2cafe6e 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/ts/testcore/consts.ts b/contracts/wasm/testcore/ts/testcore/consts.ts index bb40094455..9800e419f1 100644 --- a/contracts/wasm/testcore/ts/testcore/consts.ts +++ b/contracts/wasm/testcore/ts/testcore/consts.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export const ScName = "testcore"; export const ScDescription = "Core test for ISCP wasmlib Rust/Wasm library"; @@ -40,6 +40,8 @@ export const ResultIntValue = "intParamValue"; export const ResultMintedColor = "mintedColor"; export const ResultMintedSupply = "mintedSupply"; export const ResultSandboxCall = "sandboxCall"; +export const ResultValues = "this"; +export const ResultVars = "this"; export const StateCounter = "counter"; export const StateHnameEP = "hnameEP"; diff --git a/contracts/wasm/testcore/ts/testcore/contract.ts b/contracts/wasm/testcore/ts/testcore/contract.ts index a65695a48b..8c45bf2c57 100644 --- a/contracts/wasm/testcore/ts/testcore/contract.ts +++ b/contracts/wasm/testcore/ts/testcore/contract.ts @@ -5,317 +5,316 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class CallOnChainCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncCallOnChain); - params: sc.MutableCallOnChainParams = new sc.MutableCallOnChainParams(); - results: sc.ImmutableCallOnChainResults = new sc.ImmutableCallOnChainResults(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncCallOnChain); + params: sc.MutableCallOnChainParams = new sc.MutableCallOnChainParams(); + results: sc.ImmutableCallOnChainResults = new sc.ImmutableCallOnChainResults(); } export class CallOnChainContext { - params: sc.ImmutableCallOnChainParams = new sc.ImmutableCallOnChainParams(); - results: sc.MutableCallOnChainResults = new sc.MutableCallOnChainResults(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + params: sc.ImmutableCallOnChainParams = new sc.ImmutableCallOnChainParams(); + results: sc.MutableCallOnChainResults = new sc.MutableCallOnChainResults(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class CheckContextFromFullEPCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncCheckContextFromFullEP); - params: sc.MutableCheckContextFromFullEPParams = new sc.MutableCheckContextFromFullEPParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncCheckContextFromFullEP); + params: sc.MutableCheckContextFromFullEPParams = new sc.MutableCheckContextFromFullEPParams(); } export class CheckContextFromFullEPContext { - params: sc.ImmutableCheckContextFromFullEPParams = new sc.ImmutableCheckContextFromFullEPParams(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + params: sc.ImmutableCheckContextFromFullEPParams = new sc.ImmutableCheckContextFromFullEPParams(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class DoNothingCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDoNothing); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDoNothing); } export class DoNothingContext { - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class GetMintedSupplyCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncGetMintedSupply); - results: sc.ImmutableGetMintedSupplyResults = new sc.ImmutableGetMintedSupplyResults(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncGetMintedSupply); + results: sc.ImmutableGetMintedSupplyResults = new sc.ImmutableGetMintedSupplyResults(); } export class GetMintedSupplyContext { - results: sc.MutableGetMintedSupplyResults = new sc.MutableGetMintedSupplyResults(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + results: sc.MutableGetMintedSupplyResults = new sc.MutableGetMintedSupplyResults(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class IncCounterCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncIncCounter); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncIncCounter); } export class IncCounterContext { - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class InitCall { - func: wasmlib.ScInitFunc = new wasmlib.ScInitFunc(sc.HScName, sc.HFuncInit); - params: sc.MutableInitParams = new sc.MutableInitParams(); + func: wasmlib.ScInitFunc = new wasmlib.ScInitFunc(sc.HScName, sc.HFuncInit); + params: sc.MutableInitParams = new sc.MutableInitParams(); } export class InitContext { - params: sc.ImmutableInitParams = new sc.ImmutableInitParams(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + params: sc.ImmutableInitParams = new sc.ImmutableInitParams(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class PassTypesFullCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPassTypesFull); - params: sc.MutablePassTypesFullParams = new sc.MutablePassTypesFullParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncPassTypesFull); + params: sc.MutablePassTypesFullParams = new sc.MutablePassTypesFullParams(); } export class PassTypesFullContext { - params: sc.ImmutablePassTypesFullParams = new sc.ImmutablePassTypesFullParams(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + params: sc.ImmutablePassTypesFullParams = new sc.ImmutablePassTypesFullParams(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class RunRecursionCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncRunRecursion); - params: sc.MutableRunRecursionParams = new sc.MutableRunRecursionParams(); - results: sc.ImmutableRunRecursionResults = new sc.ImmutableRunRecursionResults(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncRunRecursion); + params: sc.MutableRunRecursionParams = new sc.MutableRunRecursionParams(); + results: sc.ImmutableRunRecursionResults = new sc.ImmutableRunRecursionResults(); } export class RunRecursionContext { - params: sc.ImmutableRunRecursionParams = new sc.ImmutableRunRecursionParams(); - results: sc.MutableRunRecursionResults = new sc.MutableRunRecursionResults(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + params: sc.ImmutableRunRecursionParams = new sc.ImmutableRunRecursionParams(); + results: sc.MutableRunRecursionResults = new sc.MutableRunRecursionResults(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class SendToAddressCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSendToAddress); - params: sc.MutableSendToAddressParams = new sc.MutableSendToAddressParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSendToAddress); + params: sc.MutableSendToAddressParams = new sc.MutableSendToAddressParams(); } export class SendToAddressContext { - params: sc.ImmutableSendToAddressParams = new sc.ImmutableSendToAddressParams(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + params: sc.ImmutableSendToAddressParams = new sc.ImmutableSendToAddressParams(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class SetIntCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetInt); - params: sc.MutableSetIntParams = new sc.MutableSetIntParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetInt); + params: sc.MutableSetIntParams = new sc.MutableSetIntParams(); } export class SetIntContext { - params: sc.ImmutableSetIntParams = new sc.ImmutableSetIntParams(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + params: sc.ImmutableSetIntParams = new sc.ImmutableSetIntParams(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class SpawnCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSpawn); - params: sc.MutableSpawnParams = new sc.MutableSpawnParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSpawn); + params: sc.MutableSpawnParams = new sc.MutableSpawnParams(); } export class SpawnContext { - params: sc.ImmutableSpawnParams = new sc.ImmutableSpawnParams(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + params: sc.ImmutableSpawnParams = new sc.ImmutableSpawnParams(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class TestBlockContext1Call { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestBlockContext1); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestBlockContext1); } export class TestBlockContext1Context { - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class TestBlockContext2Call { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestBlockContext2); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestBlockContext2); } export class TestBlockContext2Context { - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class TestCallPanicFullEPCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestCallPanicFullEP); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestCallPanicFullEP); } export class TestCallPanicFullEPContext { - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class TestCallPanicViewEPFromFullCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestCallPanicViewEPFromFull); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestCallPanicViewEPFromFull); } export class TestCallPanicViewEPFromFullContext { - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class TestChainOwnerIDFullCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestChainOwnerIDFull); - results: sc.ImmutableTestChainOwnerIDFullResults = new sc.ImmutableTestChainOwnerIDFullResults(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestChainOwnerIDFull); + results: sc.ImmutableTestChainOwnerIDFullResults = new sc.ImmutableTestChainOwnerIDFullResults(); } export class TestChainOwnerIDFullContext { - results: sc.MutableTestChainOwnerIDFullResults = new sc.MutableTestChainOwnerIDFullResults(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + results: sc.MutableTestChainOwnerIDFullResults = new sc.MutableTestChainOwnerIDFullResults(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class TestEventLogDeployCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestEventLogDeploy); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestEventLogDeploy); } export class TestEventLogDeployContext { - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class TestEventLogEventDataCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestEventLogEventData); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestEventLogEventData); } export class TestEventLogEventDataContext { - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class TestEventLogGenericDataCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestEventLogGenericData); - params: sc.MutableTestEventLogGenericDataParams = new sc.MutableTestEventLogGenericDataParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestEventLogGenericData); + params: sc.MutableTestEventLogGenericDataParams = new sc.MutableTestEventLogGenericDataParams(); } export class TestEventLogGenericDataContext { - params: sc.ImmutableTestEventLogGenericDataParams = new sc.ImmutableTestEventLogGenericDataParams(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + params: sc.ImmutableTestEventLogGenericDataParams = new sc.ImmutableTestEventLogGenericDataParams(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class TestPanicFullEPCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestPanicFullEP); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTestPanicFullEP); } export class TestPanicFullEPContext { - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class WithdrawToChainCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncWithdrawToChain); - params: sc.MutableWithdrawToChainParams = new sc.MutableWithdrawToChainParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncWithdrawToChain); + params: sc.MutableWithdrawToChainParams = new sc.MutableWithdrawToChainParams(); } export class WithdrawToChainContext { - params: sc.ImmutableWithdrawToChainParams = new sc.ImmutableWithdrawToChainParams(); - state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); + params: sc.ImmutableWithdrawToChainParams = new sc.ImmutableWithdrawToChainParams(); + state: sc.MutableTestCoreState = new sc.MutableTestCoreState(); } export class CheckContextFromViewEPCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewCheckContextFromViewEP); - params: sc.MutableCheckContextFromViewEPParams = new sc.MutableCheckContextFromViewEPParams(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewCheckContextFromViewEP); + params: sc.MutableCheckContextFromViewEPParams = new sc.MutableCheckContextFromViewEPParams(); } export class CheckContextFromViewEPContext { - params: sc.ImmutableCheckContextFromViewEPParams = new sc.ImmutableCheckContextFromViewEPParams(); - state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); + params: sc.ImmutableCheckContextFromViewEPParams = new sc.ImmutableCheckContextFromViewEPParams(); + state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); } export class FibonacciCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewFibonacci); - params: sc.MutableFibonacciParams = new sc.MutableFibonacciParams(); - results: sc.ImmutableFibonacciResults = new sc.ImmutableFibonacciResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewFibonacci); + params: sc.MutableFibonacciParams = new sc.MutableFibonacciParams(); + results: sc.ImmutableFibonacciResults = new sc.ImmutableFibonacciResults(); } export class FibonacciContext { - params: sc.ImmutableFibonacciParams = new sc.ImmutableFibonacciParams(); - results: sc.MutableFibonacciResults = new sc.MutableFibonacciResults(); - state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); + params: sc.ImmutableFibonacciParams = new sc.ImmutableFibonacciParams(); + results: sc.MutableFibonacciResults = new sc.MutableFibonacciResults(); + state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); } export class GetCounterCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetCounter); - results: sc.ImmutableGetCounterResults = new sc.ImmutableGetCounterResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetCounter); + results: sc.ImmutableGetCounterResults = new sc.ImmutableGetCounterResults(); } export class GetCounterContext { - results: sc.MutableGetCounterResults = new sc.MutableGetCounterResults(); - state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); + results: sc.MutableGetCounterResults = new sc.MutableGetCounterResults(); + state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); } export class GetIntCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetInt); - params: sc.MutableGetIntParams = new sc.MutableGetIntParams(); - results: sc.ImmutableGetIntResults = new sc.ImmutableGetIntResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetInt); + params: sc.MutableGetIntParams = new sc.MutableGetIntParams(); + results: sc.ImmutableGetIntResults = new sc.ImmutableGetIntResults(); } export class GetIntContext { - params: sc.ImmutableGetIntParams = new sc.ImmutableGetIntParams(); - results: sc.MutableGetIntResults = new sc.MutableGetIntResults(); - state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); + params: sc.ImmutableGetIntParams = new sc.ImmutableGetIntParams(); + results: sc.MutableGetIntResults = new sc.MutableGetIntResults(); + state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); } export class GetStringValueCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetStringValue); - params: sc.MutableGetStringValueParams = new sc.MutableGetStringValueParams(); - results: sc.ImmutableGetStringValueResults = new sc.ImmutableGetStringValueResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetStringValue); + params: sc.MutableGetStringValueParams = new sc.MutableGetStringValueParams(); + results: sc.ImmutableGetStringValueResults = new sc.ImmutableGetStringValueResults(); } export class GetStringValueContext { - params: sc.ImmutableGetStringValueParams = new sc.ImmutableGetStringValueParams(); - results: sc.MutableGetStringValueResults = new sc.MutableGetStringValueResults(); - state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); + params: sc.ImmutableGetStringValueParams = new sc.ImmutableGetStringValueParams(); + results: sc.MutableGetStringValueResults = new sc.MutableGetStringValueResults(); + state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); } export class JustViewCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewJustView); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewJustView); } export class JustViewContext { - state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); + state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); } export class PassTypesViewCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewPassTypesView); - params: sc.MutablePassTypesViewParams = new sc.MutablePassTypesViewParams(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewPassTypesView); + params: sc.MutablePassTypesViewParams = new sc.MutablePassTypesViewParams(); } export class PassTypesViewContext { - params: sc.ImmutablePassTypesViewParams = new sc.ImmutablePassTypesViewParams(); - state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); + params: sc.ImmutablePassTypesViewParams = new sc.ImmutablePassTypesViewParams(); + state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); } export class TestCallPanicViewEPFromViewCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTestCallPanicViewEPFromView); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTestCallPanicViewEPFromView); } export class TestCallPanicViewEPFromViewContext { - state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); + state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); } export class TestChainOwnerIDViewCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTestChainOwnerIDView); - results: sc.ImmutableTestChainOwnerIDViewResults = new sc.ImmutableTestChainOwnerIDViewResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTestChainOwnerIDView); + results: sc.ImmutableTestChainOwnerIDViewResults = new sc.ImmutableTestChainOwnerIDViewResults(); } export class TestChainOwnerIDViewContext { - results: sc.MutableTestChainOwnerIDViewResults = new sc.MutableTestChainOwnerIDViewResults(); - state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); + results: sc.MutableTestChainOwnerIDViewResults = new sc.MutableTestChainOwnerIDViewResults(); + state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); } export class TestPanicViewEPCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTestPanicViewEP); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTestPanicViewEP); } export class TestPanicViewEPContext { - state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); + state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); } export class TestSandboxCallCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTestSandboxCall); - results: sc.ImmutableTestSandboxCallResults = new sc.ImmutableTestSandboxCallResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTestSandboxCall); + results: sc.ImmutableTestSandboxCallResults = new sc.ImmutableTestSandboxCallResults(); } export class TestSandboxCallContext { - results: sc.MutableTestSandboxCallResults = new sc.MutableTestSandboxCallResults(); - state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); + results: sc.MutableTestSandboxCallResults = new sc.MutableTestSandboxCallResults(); + state: sc.ImmutableTestCoreState = new sc.ImmutableTestCoreState(); } export class ScFuncs { - static callOnChain(ctx: wasmlib.ScFuncCallContext): CallOnChainCall { let f = new CallOnChainCall(); f.func.setPtrs(f.params, f.results); @@ -329,8 +328,7 @@ export class ScFuncs { } static doNothing(ctx: wasmlib.ScFuncCallContext): DoNothingCall { - let f = new DoNothingCall(); - return f; + return new DoNothingCall(); } static getMintedSupply(ctx: wasmlib.ScFuncCallContext): GetMintedSupplyCall { @@ -340,8 +338,7 @@ export class ScFuncs { } static incCounter(ctx: wasmlib.ScFuncCallContext): IncCounterCall { - let f = new IncCounterCall(); - return f; + return new IncCounterCall(); } static init(ctx: wasmlib.ScFuncCallContext): InitCall { @@ -381,23 +378,19 @@ export class ScFuncs { } static testBlockContext1(ctx: wasmlib.ScFuncCallContext): TestBlockContext1Call { - let f = new TestBlockContext1Call(); - return f; + return new TestBlockContext1Call(); } static testBlockContext2(ctx: wasmlib.ScFuncCallContext): TestBlockContext2Call { - let f = new TestBlockContext2Call(); - return f; + return new TestBlockContext2Call(); } static testCallPanicFullEP(ctx: wasmlib.ScFuncCallContext): TestCallPanicFullEPCall { - let f = new TestCallPanicFullEPCall(); - return f; + return new TestCallPanicFullEPCall(); } static testCallPanicViewEPFromFull(ctx: wasmlib.ScFuncCallContext): TestCallPanicViewEPFromFullCall { - let f = new TestCallPanicViewEPFromFullCall(); - return f; + return new TestCallPanicViewEPFromFullCall(); } static testChainOwnerIDFull(ctx: wasmlib.ScFuncCallContext): TestChainOwnerIDFullCall { @@ -407,13 +400,11 @@ export class ScFuncs { } static testEventLogDeploy(ctx: wasmlib.ScFuncCallContext): TestEventLogDeployCall { - let f = new TestEventLogDeployCall(); - return f; + return new TestEventLogDeployCall(); } static testEventLogEventData(ctx: wasmlib.ScFuncCallContext): TestEventLogEventDataCall { - let f = new TestEventLogEventDataCall(); - return f; + return new TestEventLogEventDataCall(); } static testEventLogGenericData(ctx: wasmlib.ScFuncCallContext): TestEventLogGenericDataCall { @@ -423,8 +414,7 @@ export class ScFuncs { } static testPanicFullEP(ctx: wasmlib.ScFuncCallContext): TestPanicFullEPCall { - let f = new TestPanicFullEPCall(); - return f; + return new TestPanicFullEPCall(); } static withdrawToChain(ctx: wasmlib.ScFuncCallContext): WithdrawToChainCall { @@ -464,8 +454,7 @@ export class ScFuncs { } static justView(ctx: wasmlib.ScViewCallContext): JustViewCall { - let f = new JustViewCall(); - return f; + return new JustViewCall(); } static passTypesView(ctx: wasmlib.ScViewCallContext): PassTypesViewCall { @@ -475,8 +464,7 @@ export class ScFuncs { } static testCallPanicViewEPFromView(ctx: wasmlib.ScViewCallContext): TestCallPanicViewEPFromViewCall { - let f = new TestCallPanicViewEPFromViewCall(); - return f; + return new TestCallPanicViewEPFromViewCall(); } static testChainOwnerIDView(ctx: wasmlib.ScViewCallContext): TestChainOwnerIDViewCall { @@ -486,8 +474,7 @@ export class ScFuncs { } static testPanicViewEP(ctx: wasmlib.ScViewCallContext): TestPanicViewEPCall { - let f = new TestPanicViewEPCall(); - return f; + return new TestPanicViewEPCall(); } static testSandboxCall(ctx: wasmlib.ScViewCallContext): TestSandboxCallCall { diff --git a/contracts/wasm/testcore/ts/testcore/keys.ts b/contracts/wasm/testcore/ts/testcore/keys.ts index cee489bf53..f1fdbcb9fb 100644 --- a/contracts/wasm/testcore/ts/testcore/keys.ts +++ b/contracts/wasm/testcore/ts/testcore/keys.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export const IdxParamAddress = 0; @@ -30,52 +30,58 @@ export const IdxParamProgHash = 18; export const IdxParamString = 19; export const IdxParamStringZero = 20; export const IdxParamVarName = 21; -export const IdxResultChainOwnerID = 22; -export const IdxResultCounter = 23; -export const IdxResultIntValue = 24; -export const IdxResultMintedColor = 25; -export const IdxResultMintedSupply = 26; -export const IdxResultSandboxCall = 27; -export const IdxStateCounter = 28; -export const IdxStateHnameEP = 29; -export const IdxStateInts = 30; -export const IdxStateMintedColor = 31; -export const IdxStateMintedSupply = 32; + +export const IdxResultChainOwnerID = 22; +export const IdxResultCounter = 23; +export const IdxResultIntValue = 24; +export const IdxResultMintedColor = 25; +export const IdxResultMintedSupply = 26; +export const IdxResultSandboxCall = 27; +export const IdxResultValues = 28; +export const IdxResultVars = 29; + +export const IdxStateCounter = 30; +export const IdxStateHnameEP = 31; +export const IdxStateInts = 32; +export const IdxStateMintedColor = 33; +export const IdxStateMintedSupply = 34; export let keyMap: string[] = [ - sc.ParamAddress, - sc.ParamAgentID, - sc.ParamCaller, - sc.ParamChainID, - sc.ParamChainOwnerID, - sc.ParamContractCreator, - sc.ParamContractID, - sc.ParamCounter, - sc.ParamFail, - sc.ParamHash, - sc.ParamHname, - sc.ParamHnameContract, - sc.ParamHnameEP, - sc.ParamHnameZero, - sc.ParamInt64, - sc.ParamInt64Zero, - sc.ParamIntValue, - sc.ParamName, - sc.ParamProgHash, - sc.ParamString, - sc.ParamStringZero, - sc.ParamVarName, - sc.ResultChainOwnerID, - sc.ResultCounter, - sc.ResultIntValue, - sc.ResultMintedColor, - sc.ResultMintedSupply, - sc.ResultSandboxCall, - sc.StateCounter, - sc.StateHnameEP, - sc.StateInts, - sc.StateMintedColor, - sc.StateMintedSupply, + sc.ParamAddress, + sc.ParamAgentID, + sc.ParamCaller, + sc.ParamChainID, + sc.ParamChainOwnerID, + sc.ParamContractCreator, + sc.ParamContractID, + sc.ParamCounter, + sc.ParamFail, + sc.ParamHash, + sc.ParamHname, + sc.ParamHnameContract, + sc.ParamHnameEP, + sc.ParamHnameZero, + sc.ParamInt64, + sc.ParamInt64Zero, + sc.ParamIntValue, + sc.ParamName, + sc.ParamProgHash, + sc.ParamString, + sc.ParamStringZero, + sc.ParamVarName, + sc.ResultChainOwnerID, + sc.ResultCounter, + sc.ResultIntValue, + sc.ResultMintedColor, + sc.ResultMintedSupply, + sc.ResultSandboxCall, + sc.ResultValues, + sc.ResultVars, + sc.StateCounter, + sc.StateHnameEP, + sc.StateInts, + sc.StateMintedColor, + sc.StateMintedSupply, ]; export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/testcore/ts/testcore/lib.ts b/contracts/wasm/testcore/ts/testcore/lib.ts index 468c8b992f..2ff3e7d18e 100644 --- a/contracts/wasm/testcore/ts/testcore/lib.ts +++ b/contracts/wasm/testcore/ts/testcore/lib.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export function on_call(index: i32): void { @@ -14,38 +14,38 @@ export function on_call(index: i32): void { export function on_load(): void { let exports = new wasmlib.ScExports(); - exports.addFunc(sc.FuncCallOnChain, funcCallOnChainThunk); - exports.addFunc(sc.FuncCheckContextFromFullEP, funcCheckContextFromFullEPThunk); - exports.addFunc(sc.FuncDoNothing, funcDoNothingThunk); - exports.addFunc(sc.FuncGetMintedSupply, funcGetMintedSupplyThunk); - exports.addFunc(sc.FuncIncCounter, funcIncCounterThunk); - exports.addFunc(sc.FuncInit, funcInitThunk); - exports.addFunc(sc.FuncPassTypesFull, funcPassTypesFullThunk); - exports.addFunc(sc.FuncRunRecursion, funcRunRecursionThunk); - exports.addFunc(sc.FuncSendToAddress, funcSendToAddressThunk); - exports.addFunc(sc.FuncSetInt, funcSetIntThunk); - exports.addFunc(sc.FuncSpawn, funcSpawnThunk); - exports.addFunc(sc.FuncTestBlockContext1, funcTestBlockContext1Thunk); - exports.addFunc(sc.FuncTestBlockContext2, funcTestBlockContext2Thunk); - exports.addFunc(sc.FuncTestCallPanicFullEP, funcTestCallPanicFullEPThunk); + exports.addFunc(sc.FuncCallOnChain, funcCallOnChainThunk); + exports.addFunc(sc.FuncCheckContextFromFullEP, funcCheckContextFromFullEPThunk); + exports.addFunc(sc.FuncDoNothing, funcDoNothingThunk); + exports.addFunc(sc.FuncGetMintedSupply, funcGetMintedSupplyThunk); + exports.addFunc(sc.FuncIncCounter, funcIncCounterThunk); + exports.addFunc(sc.FuncInit, funcInitThunk); + exports.addFunc(sc.FuncPassTypesFull, funcPassTypesFullThunk); + exports.addFunc(sc.FuncRunRecursion, funcRunRecursionThunk); + exports.addFunc(sc.FuncSendToAddress, funcSendToAddressThunk); + exports.addFunc(sc.FuncSetInt, funcSetIntThunk); + exports.addFunc(sc.FuncSpawn, funcSpawnThunk); + exports.addFunc(sc.FuncTestBlockContext1, funcTestBlockContext1Thunk); + exports.addFunc(sc.FuncTestBlockContext2, funcTestBlockContext2Thunk); + exports.addFunc(sc.FuncTestCallPanicFullEP, funcTestCallPanicFullEPThunk); exports.addFunc(sc.FuncTestCallPanicViewEPFromFull, funcTestCallPanicViewEPFromFullThunk); - exports.addFunc(sc.FuncTestChainOwnerIDFull, funcTestChainOwnerIDFullThunk); - exports.addFunc(sc.FuncTestEventLogDeploy, funcTestEventLogDeployThunk); - exports.addFunc(sc.FuncTestEventLogEventData, funcTestEventLogEventDataThunk); - exports.addFunc(sc.FuncTestEventLogGenericData, funcTestEventLogGenericDataThunk); - exports.addFunc(sc.FuncTestPanicFullEP, funcTestPanicFullEPThunk); - exports.addFunc(sc.FuncWithdrawToChain, funcWithdrawToChainThunk); - exports.addView(sc.ViewCheckContextFromViewEP, viewCheckContextFromViewEPThunk); - exports.addView(sc.ViewFibonacci, viewFibonacciThunk); - exports.addView(sc.ViewGetCounter, viewGetCounterThunk); - exports.addView(sc.ViewGetInt, viewGetIntThunk); - exports.addView(sc.ViewGetStringValue, viewGetStringValueThunk); - exports.addView(sc.ViewJustView, viewJustViewThunk); - exports.addView(sc.ViewPassTypesView, viewPassTypesViewThunk); + exports.addFunc(sc.FuncTestChainOwnerIDFull, funcTestChainOwnerIDFullThunk); + exports.addFunc(sc.FuncTestEventLogDeploy, funcTestEventLogDeployThunk); + exports.addFunc(sc.FuncTestEventLogEventData, funcTestEventLogEventDataThunk); + exports.addFunc(sc.FuncTestEventLogGenericData, funcTestEventLogGenericDataThunk); + exports.addFunc(sc.FuncTestPanicFullEP, funcTestPanicFullEPThunk); + exports.addFunc(sc.FuncWithdrawToChain, funcWithdrawToChainThunk); + exports.addView(sc.ViewCheckContextFromViewEP, viewCheckContextFromViewEPThunk); + exports.addView(sc.ViewFibonacci, viewFibonacciThunk); + exports.addView(sc.ViewGetCounter, viewGetCounterThunk); + exports.addView(sc.ViewGetInt, viewGetIntThunk); + exports.addView(sc.ViewGetStringValue, viewGetStringValueThunk); + exports.addView(sc.ViewJustView, viewJustViewThunk); + exports.addView(sc.ViewPassTypesView, viewPassTypesViewThunk); exports.addView(sc.ViewTestCallPanicViewEPFromView, viewTestCallPanicViewEPFromViewThunk); - exports.addView(sc.ViewTestChainOwnerIDView, viewTestChainOwnerIDViewThunk); - exports.addView(sc.ViewTestPanicViewEP, viewTestPanicViewEPThunk); - exports.addView(sc.ViewTestSandboxCall, viewTestSandboxCallThunk); + exports.addView(sc.ViewTestChainOwnerIDView, viewTestChainOwnerIDViewThunk); + exports.addView(sc.ViewTestPanicViewEP, viewTestPanicViewEPThunk); + exports.addView(sc.ViewTestSandboxCall, viewTestSandboxCallThunk); for (let i = 0; i < sc.keyMap.length; i++) { sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); @@ -53,326 +53,326 @@ export function on_load(): void { } function funcCallOnChainThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcCallOnChain"); - let f = new sc.CallOnChainContext(); + ctx.log("testcore.funcCallOnChain"); + let f = new sc.CallOnChainContext(); 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.intValue().exists(), "missing mandatory intValue") - sc.funcCallOnChain(ctx, f); - ctx.log("testcore.funcCallOnChain ok"); + ctx.require(f.params.intValue().exists(), "missing mandatory intValue"); + sc.funcCallOnChain(ctx, f); + ctx.log("testcore.funcCallOnChain ok"); } function funcCheckContextFromFullEPThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcCheckContextFromFullEP"); - let f = new sc.CheckContextFromFullEPContext(); + ctx.log("testcore.funcCheckContextFromFullEP"); + let f = new sc.CheckContextFromFullEPContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.agentID().exists(), "missing mandatory agentID") - ctx.require(f.params.caller().exists(), "missing mandatory caller") - ctx.require(f.params.chainID().exists(), "missing mandatory chainID") - ctx.require(f.params.chainOwnerID().exists(), "missing mandatory chainOwnerID") - ctx.require(f.params.contractCreator().exists(), "missing mandatory contractCreator") - sc.funcCheckContextFromFullEP(ctx, f); - ctx.log("testcore.funcCheckContextFromFullEP ok"); + ctx.require(f.params.agentID().exists(), "missing mandatory agentID"); + ctx.require(f.params.caller().exists(), "missing mandatory caller"); + ctx.require(f.params.chainID().exists(), "missing mandatory chainID"); + ctx.require(f.params.chainOwnerID().exists(), "missing mandatory chainOwnerID"); + ctx.require(f.params.contractCreator().exists(), "missing mandatory contractCreator"); + sc.funcCheckContextFromFullEP(ctx, f); + ctx.log("testcore.funcCheckContextFromFullEP ok"); } function funcDoNothingThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcDoNothing"); - let f = new sc.DoNothingContext(); + ctx.log("testcore.funcDoNothing"); + let f = new sc.DoNothingContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcDoNothing(ctx, f); - ctx.log("testcore.funcDoNothing ok"); + sc.funcDoNothing(ctx, f); + ctx.log("testcore.funcDoNothing ok"); } function funcGetMintedSupplyThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcGetMintedSupply"); - let f = new sc.GetMintedSupplyContext(); + ctx.log("testcore.funcGetMintedSupply"); + let f = new sc.GetMintedSupplyContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcGetMintedSupply(ctx, f); - ctx.log("testcore.funcGetMintedSupply ok"); + sc.funcGetMintedSupply(ctx, f); + ctx.log("testcore.funcGetMintedSupply ok"); } function funcIncCounterThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcIncCounter"); - let f = new sc.IncCounterContext(); + ctx.log("testcore.funcIncCounter"); + let f = new sc.IncCounterContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcIncCounter(ctx, f); - ctx.log("testcore.funcIncCounter ok"); + sc.funcIncCounter(ctx, f); + ctx.log("testcore.funcIncCounter ok"); } function funcInitThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcInit"); - let f = new sc.InitContext(); + ctx.log("testcore.funcInit"); + let f = new sc.InitContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcInit(ctx, f); - ctx.log("testcore.funcInit ok"); + sc.funcInit(ctx, f); + ctx.log("testcore.funcInit ok"); } function funcPassTypesFullThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcPassTypesFull"); - let f = new sc.PassTypesFullContext(); + ctx.log("testcore.funcPassTypesFull"); + let f = new sc.PassTypesFullContext(); 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.agentID().exists(), "missing mandatory agentID") - ctx.require(f.params.chainID().exists(), "missing mandatory chainID") - ctx.require(f.params.contractID().exists(), "missing mandatory contractID") - ctx.require(f.params.hash().exists(), "missing mandatory hash") - ctx.require(f.params.hname().exists(), "missing mandatory hname") - ctx.require(f.params.hnameZero().exists(), "missing mandatory hnameZero") - ctx.require(f.params.int64().exists(), "missing mandatory int64") - ctx.require(f.params.int64Zero().exists(), "missing mandatory int64Zero") - ctx.require(f.params.string().exists(), "missing mandatory string") - ctx.require(f.params.stringZero().exists(), "missing mandatory stringZero") - sc.funcPassTypesFull(ctx, f); - ctx.log("testcore.funcPassTypesFull ok"); + ctx.require(f.params.address().exists(), "missing mandatory address"); + ctx.require(f.params.agentID().exists(), "missing mandatory agentID"); + ctx.require(f.params.chainID().exists(), "missing mandatory chainID"); + ctx.require(f.params.contractID().exists(), "missing mandatory contractID"); + ctx.require(f.params.hash().exists(), "missing mandatory hash"); + ctx.require(f.params.hname().exists(), "missing mandatory hname"); + ctx.require(f.params.hnameZero().exists(), "missing mandatory hnameZero"); + ctx.require(f.params.int64().exists(), "missing mandatory int64"); + ctx.require(f.params.int64Zero().exists(), "missing mandatory int64Zero"); + ctx.require(f.params.string().exists(), "missing mandatory string"); + ctx.require(f.params.stringZero().exists(), "missing mandatory stringZero"); + sc.funcPassTypesFull(ctx, f); + ctx.log("testcore.funcPassTypesFull ok"); } function funcRunRecursionThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcRunRecursion"); - let f = new sc.RunRecursionContext(); + ctx.log("testcore.funcRunRecursion"); + let f = new sc.RunRecursionContext(); 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.intValue().exists(), "missing mandatory intValue") - sc.funcRunRecursion(ctx, f); - ctx.log("testcore.funcRunRecursion ok"); + ctx.require(f.params.intValue().exists(), "missing mandatory intValue"); + sc.funcRunRecursion(ctx, f); + ctx.log("testcore.funcRunRecursion ok"); } function funcSendToAddressThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcSendToAddress"); - ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + ctx.log("testcore.funcSendToAddress"); + ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); - let f = new sc.SendToAddressContext(); + let f = new sc.SendToAddressContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.address().exists(), "missing mandatory address") - sc.funcSendToAddress(ctx, f); - ctx.log("testcore.funcSendToAddress ok"); + ctx.require(f.params.address().exists(), "missing mandatory address"); + sc.funcSendToAddress(ctx, f); + ctx.log("testcore.funcSendToAddress ok"); } function funcSetIntThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcSetInt"); - let f = new sc.SetIntContext(); + ctx.log("testcore.funcSetInt"); + let f = new sc.SetIntContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.intValue().exists(), "missing mandatory intValue") - ctx.require(f.params.name().exists(), "missing mandatory name") - sc.funcSetInt(ctx, f); - ctx.log("testcore.funcSetInt ok"); + ctx.require(f.params.intValue().exists(), "missing mandatory intValue"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + sc.funcSetInt(ctx, f); + ctx.log("testcore.funcSetInt ok"); } function funcSpawnThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcSpawn"); - let f = new sc.SpawnContext(); + ctx.log("testcore.funcSpawn"); + let f = new sc.SpawnContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.progHash().exists(), "missing mandatory progHash") - sc.funcSpawn(ctx, f); - ctx.log("testcore.funcSpawn ok"); + ctx.require(f.params.progHash().exists(), "missing mandatory progHash"); + sc.funcSpawn(ctx, f); + ctx.log("testcore.funcSpawn ok"); } function funcTestBlockContext1Thunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcTestBlockContext1"); - let f = new sc.TestBlockContext1Context(); + ctx.log("testcore.funcTestBlockContext1"); + let f = new sc.TestBlockContext1Context(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcTestBlockContext1(ctx, f); - ctx.log("testcore.funcTestBlockContext1 ok"); + sc.funcTestBlockContext1(ctx, f); + ctx.log("testcore.funcTestBlockContext1 ok"); } function funcTestBlockContext2Thunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcTestBlockContext2"); - let f = new sc.TestBlockContext2Context(); + ctx.log("testcore.funcTestBlockContext2"); + let f = new sc.TestBlockContext2Context(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcTestBlockContext2(ctx, f); - ctx.log("testcore.funcTestBlockContext2 ok"); + sc.funcTestBlockContext2(ctx, f); + ctx.log("testcore.funcTestBlockContext2 ok"); } function funcTestCallPanicFullEPThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcTestCallPanicFullEP"); - let f = new sc.TestCallPanicFullEPContext(); + ctx.log("testcore.funcTestCallPanicFullEP"); + let f = new sc.TestCallPanicFullEPContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcTestCallPanicFullEP(ctx, f); - ctx.log("testcore.funcTestCallPanicFullEP ok"); + sc.funcTestCallPanicFullEP(ctx, f); + ctx.log("testcore.funcTestCallPanicFullEP ok"); } function funcTestCallPanicViewEPFromFullThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcTestCallPanicViewEPFromFull"); - let f = new sc.TestCallPanicViewEPFromFullContext(); + ctx.log("testcore.funcTestCallPanicViewEPFromFull"); + let f = new sc.TestCallPanicViewEPFromFullContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcTestCallPanicViewEPFromFull(ctx, f); - ctx.log("testcore.funcTestCallPanicViewEPFromFull ok"); + sc.funcTestCallPanicViewEPFromFull(ctx, f); + ctx.log("testcore.funcTestCallPanicViewEPFromFull ok"); } function funcTestChainOwnerIDFullThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcTestChainOwnerIDFull"); - let f = new sc.TestChainOwnerIDFullContext(); + ctx.log("testcore.funcTestChainOwnerIDFull"); + let f = new sc.TestChainOwnerIDFullContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcTestChainOwnerIDFull(ctx, f); - ctx.log("testcore.funcTestChainOwnerIDFull ok"); + sc.funcTestChainOwnerIDFull(ctx, f); + ctx.log("testcore.funcTestChainOwnerIDFull ok"); } function funcTestEventLogDeployThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcTestEventLogDeploy"); - let f = new sc.TestEventLogDeployContext(); + ctx.log("testcore.funcTestEventLogDeploy"); + let f = new sc.TestEventLogDeployContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcTestEventLogDeploy(ctx, f); - ctx.log("testcore.funcTestEventLogDeploy ok"); + sc.funcTestEventLogDeploy(ctx, f); + ctx.log("testcore.funcTestEventLogDeploy ok"); } function funcTestEventLogEventDataThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcTestEventLogEventData"); - let f = new sc.TestEventLogEventDataContext(); + ctx.log("testcore.funcTestEventLogEventData"); + let f = new sc.TestEventLogEventDataContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcTestEventLogEventData(ctx, f); - ctx.log("testcore.funcTestEventLogEventData ok"); + sc.funcTestEventLogEventData(ctx, f); + ctx.log("testcore.funcTestEventLogEventData ok"); } function funcTestEventLogGenericDataThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcTestEventLogGenericData"); - let f = new sc.TestEventLogGenericDataContext(); + ctx.log("testcore.funcTestEventLogGenericData"); + let f = new sc.TestEventLogGenericDataContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.counter().exists(), "missing mandatory counter") - sc.funcTestEventLogGenericData(ctx, f); - ctx.log("testcore.funcTestEventLogGenericData ok"); + ctx.require(f.params.counter().exists(), "missing mandatory counter"); + sc.funcTestEventLogGenericData(ctx, f); + ctx.log("testcore.funcTestEventLogGenericData ok"); } function funcTestPanicFullEPThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcTestPanicFullEP"); - let f = new sc.TestPanicFullEPContext(); + ctx.log("testcore.funcTestPanicFullEP"); + let f = new sc.TestPanicFullEPContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcTestPanicFullEP(ctx, f); - ctx.log("testcore.funcTestPanicFullEP ok"); + sc.funcTestPanicFullEP(ctx, f); + ctx.log("testcore.funcTestPanicFullEP ok"); } function funcWithdrawToChainThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testcore.funcWithdrawToChain"); - let f = new sc.WithdrawToChainContext(); + ctx.log("testcore.funcWithdrawToChain"); + let f = new sc.WithdrawToChainContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.chainID().exists(), "missing mandatory chainID") - sc.funcWithdrawToChain(ctx, f); - ctx.log("testcore.funcWithdrawToChain ok"); + ctx.require(f.params.chainID().exists(), "missing mandatory chainID"); + sc.funcWithdrawToChain(ctx, f); + ctx.log("testcore.funcWithdrawToChain ok"); } function viewCheckContextFromViewEPThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testcore.viewCheckContextFromViewEP"); - let f = new sc.CheckContextFromViewEPContext(); + ctx.log("testcore.viewCheckContextFromViewEP"); + let f = new sc.CheckContextFromViewEPContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.agentID().exists(), "missing mandatory agentID") - ctx.require(f.params.chainID().exists(), "missing mandatory chainID") - ctx.require(f.params.chainOwnerID().exists(), "missing mandatory chainOwnerID") - ctx.require(f.params.contractCreator().exists(), "missing mandatory contractCreator") - sc.viewCheckContextFromViewEP(ctx, f); - ctx.log("testcore.viewCheckContextFromViewEP ok"); + ctx.require(f.params.agentID().exists(), "missing mandatory agentID"); + ctx.require(f.params.chainID().exists(), "missing mandatory chainID"); + ctx.require(f.params.chainOwnerID().exists(), "missing mandatory chainOwnerID"); + ctx.require(f.params.contractCreator().exists(), "missing mandatory contractCreator"); + sc.viewCheckContextFromViewEP(ctx, f); + ctx.log("testcore.viewCheckContextFromViewEP ok"); } function viewFibonacciThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testcore.viewFibonacci"); - let f = new sc.FibonacciContext(); + ctx.log("testcore.viewFibonacci"); + let f = new sc.FibonacciContext(); 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.intValue().exists(), "missing mandatory intValue") - sc.viewFibonacci(ctx, f); - ctx.log("testcore.viewFibonacci ok"); + ctx.require(f.params.intValue().exists(), "missing mandatory intValue"); + sc.viewFibonacci(ctx, f); + ctx.log("testcore.viewFibonacci ok"); } function viewGetCounterThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testcore.viewGetCounter"); - let f = new sc.GetCounterContext(); + ctx.log("testcore.viewGetCounter"); + let f = new sc.GetCounterContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewGetCounter(ctx, f); - ctx.log("testcore.viewGetCounter ok"); + sc.viewGetCounter(ctx, f); + ctx.log("testcore.viewGetCounter ok"); } function viewGetIntThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testcore.viewGetInt"); - let f = new sc.GetIntContext(); + ctx.log("testcore.viewGetInt"); + let f = new sc.GetIntContext(); 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.name().exists(), "missing mandatory name") - sc.viewGetInt(ctx, f); - ctx.log("testcore.viewGetInt ok"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + sc.viewGetInt(ctx, f); + ctx.log("testcore.viewGetInt ok"); } function viewGetStringValueThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testcore.viewGetStringValue"); - let f = new sc.GetStringValueContext(); + ctx.log("testcore.viewGetStringValue"); + let f = new sc.GetStringValueContext(); 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.varName().exists(), "missing mandatory varName") - sc.viewGetStringValue(ctx, f); - ctx.log("testcore.viewGetStringValue ok"); + ctx.require(f.params.varName().exists(), "missing mandatory varName"); + sc.viewGetStringValue(ctx, f); + ctx.log("testcore.viewGetStringValue ok"); } function viewJustViewThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testcore.viewJustView"); - let f = new sc.JustViewContext(); + ctx.log("testcore.viewJustView"); + let f = new sc.JustViewContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewJustView(ctx, f); - ctx.log("testcore.viewJustView ok"); + sc.viewJustView(ctx, f); + ctx.log("testcore.viewJustView ok"); } function viewPassTypesViewThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testcore.viewPassTypesView"); - let f = new sc.PassTypesViewContext(); + ctx.log("testcore.viewPassTypesView"); + let f = new sc.PassTypesViewContext(); 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.agentID().exists(), "missing mandatory agentID") - ctx.require(f.params.chainID().exists(), "missing mandatory chainID") - ctx.require(f.params.contractID().exists(), "missing mandatory contractID") - ctx.require(f.params.hash().exists(), "missing mandatory hash") - ctx.require(f.params.hname().exists(), "missing mandatory hname") - ctx.require(f.params.hnameZero().exists(), "missing mandatory hnameZero") - ctx.require(f.params.int64().exists(), "missing mandatory int64") - ctx.require(f.params.int64Zero().exists(), "missing mandatory int64Zero") - ctx.require(f.params.string().exists(), "missing mandatory string") - ctx.require(f.params.stringZero().exists(), "missing mandatory stringZero") - sc.viewPassTypesView(ctx, f); - ctx.log("testcore.viewPassTypesView ok"); + ctx.require(f.params.address().exists(), "missing mandatory address"); + ctx.require(f.params.agentID().exists(), "missing mandatory agentID"); + ctx.require(f.params.chainID().exists(), "missing mandatory chainID"); + ctx.require(f.params.contractID().exists(), "missing mandatory contractID"); + ctx.require(f.params.hash().exists(), "missing mandatory hash"); + ctx.require(f.params.hname().exists(), "missing mandatory hname"); + ctx.require(f.params.hnameZero().exists(), "missing mandatory hnameZero"); + ctx.require(f.params.int64().exists(), "missing mandatory int64"); + ctx.require(f.params.int64Zero().exists(), "missing mandatory int64Zero"); + ctx.require(f.params.string().exists(), "missing mandatory string"); + ctx.require(f.params.stringZero().exists(), "missing mandatory stringZero"); + sc.viewPassTypesView(ctx, f); + ctx.log("testcore.viewPassTypesView ok"); } function viewTestCallPanicViewEPFromViewThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testcore.viewTestCallPanicViewEPFromView"); - let f = new sc.TestCallPanicViewEPFromViewContext(); + ctx.log("testcore.viewTestCallPanicViewEPFromView"); + let f = new sc.TestCallPanicViewEPFromViewContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewTestCallPanicViewEPFromView(ctx, f); - ctx.log("testcore.viewTestCallPanicViewEPFromView ok"); + sc.viewTestCallPanicViewEPFromView(ctx, f); + ctx.log("testcore.viewTestCallPanicViewEPFromView ok"); } function viewTestChainOwnerIDViewThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testcore.viewTestChainOwnerIDView"); - let f = new sc.TestChainOwnerIDViewContext(); + ctx.log("testcore.viewTestChainOwnerIDView"); + let f = new sc.TestChainOwnerIDViewContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewTestChainOwnerIDView(ctx, f); - ctx.log("testcore.viewTestChainOwnerIDView ok"); + sc.viewTestChainOwnerIDView(ctx, f); + ctx.log("testcore.viewTestChainOwnerIDView ok"); } function viewTestPanicViewEPThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testcore.viewTestPanicViewEP"); - let f = new sc.TestPanicViewEPContext(); + ctx.log("testcore.viewTestPanicViewEP"); + let f = new sc.TestPanicViewEPContext(); f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewTestPanicViewEP(ctx, f); - ctx.log("testcore.viewTestPanicViewEP ok"); + sc.viewTestPanicViewEP(ctx, f); + ctx.log("testcore.viewTestPanicViewEP ok"); } function viewTestSandboxCallThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testcore.viewTestSandboxCall"); - let f = new sc.TestSandboxCallContext(); + ctx.log("testcore.viewTestSandboxCall"); + let f = new sc.TestSandboxCallContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewTestSandboxCall(ctx, f); - ctx.log("testcore.viewTestSandboxCall ok"); + sc.viewTestSandboxCall(ctx, f); + ctx.log("testcore.viewTestSandboxCall ok"); } diff --git a/contracts/wasm/testcore/ts/testcore/params.ts b/contracts/wasm/testcore/ts/testcore/params.ts index 6d961d9498..8e90695611 100644 --- a/contracts/wasm/testcore/ts/testcore/params.ts +++ b/contracts/wasm/testcore/ts/testcore/params.ts @@ -5,455 +5,425 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxParamHnameContract]); + } hnameEP(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameEP]); - } + return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameEP]); + } intValue(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); + } } 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, sc.idxMap[sc.IdxParamHnameContract]); + } hnameEP(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameEP]); - } + return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameEP]); + } intValue(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamIntValue]); + } } 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, sc.idxMap[sc.IdxParamAgentID]); + } caller(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamCaller]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamCaller]); + } chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); - } + return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + } chainOwnerID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); + } contractCreator(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); + } } 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, sc.idxMap[sc.IdxParamAgentID]); + } caller(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamCaller]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamCaller]); + } chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); - } + return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + } chainOwnerID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); + } contractCreator(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); + } } export class ImmutableInitParams extends wasmlib.ScMapID { - fail(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamFail]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamFail]); + } } export class MutableInitParams extends wasmlib.ScMapID { - fail(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamFail]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamFail]); + } } 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, sc.idxMap[sc.IdxParamAddress]); + } agentID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + } chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); - } + return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + } contractID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); + } hash(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); - } + return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + } hname(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); - } + return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + } hnameZero(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); - } + return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); + } int64(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + } int64Zero(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); + } string(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamString]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + } stringZero(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); + } } 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, sc.idxMap[sc.IdxParamAddress]); + } agentID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + } chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); - } + return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + } contractID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); + } hash(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); - } + return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + } hname(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); - } + return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + } hnameZero(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); - } + return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); + } int64(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + } int64Zero(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); + } string(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamString]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + } stringZero(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); + } } 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, sc.idxMap[sc.IdxParamIntValue]); + } } 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, sc.idxMap[sc.IdxParamIntValue]); + } } 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, sc.idxMap[sc.IdxParamAddress]); + } } 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, sc.idxMap[sc.IdxParamAddress]); + } } 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, sc.idxMap[sc.IdxParamIntValue]); + } name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamIntValue]); + } name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamProgHash]); + } } 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, sc.idxMap[sc.IdxParamProgHash]); + } } 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, sc.idxMap[sc.IdxParamCounter]); + } } 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, sc.idxMap[sc.IdxParamCounter]); + } } 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, sc.idxMap[sc.IdxParamChainID]); + } } 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, sc.idxMap[sc.IdxParamChainID]); + } } 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, sc.idxMap[sc.IdxParamAgentID]); + } chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); - } + return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + } chainOwnerID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); + } contractCreator(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); + } } 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, sc.idxMap[sc.IdxParamAgentID]); + } chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); - } + return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + } chainOwnerID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamChainOwnerID]); + } contractCreator(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractCreator]); + } } 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, sc.idxMap[sc.IdxParamIntValue]); + } } 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, sc.idxMap[sc.IdxParamIntValue]); + } } 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, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamVarName]); + } } 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, sc.idxMap[sc.IdxParamVarName]); + } } 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, sc.idxMap[sc.IdxParamAddress]); + } agentID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + } chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); - } + return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + } contractID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); + } hash(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); - } + return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + } hname(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); - } + return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + } hnameZero(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); - } + return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); + } int64(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + } int64Zero(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); + } string(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamString]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + } stringZero(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); + } } 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, sc.idxMap[sc.IdxParamAddress]); + } agentID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + } chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); - } + return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + } contractID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamContractID]); + } hash(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); - } + return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + } hname(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); - } + return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + } hnameZero(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); - } + return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHnameZero]); + } int64(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + } int64Zero(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64Zero]); + } string(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamString]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + } stringZero(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamStringZero]); + } } diff --git a/contracts/wasm/testcore/ts/testcore/results.ts b/contracts/wasm/testcore/ts/testcore/results.ts index 1c64fa616f..f25dbe28d6 100644 --- a/contracts/wasm/testcore/ts/testcore/results.ts +++ b/contracts/wasm/testcore/ts/testcore/results.ts @@ -5,209 +5,189 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxResultIntValue]); + } } 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, sc.idxMap[sc.IdxResultIntValue]); + } } 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, sc.idxMap[sc.IdxResultMintedColor]); + } mintedSupply(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultMintedSupply]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultMintedSupply]); + } } 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, sc.idxMap[sc.IdxResultMintedColor]); + } mintedSupply(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultMintedSupply]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultMintedSupply]); + } } 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, sc.idxMap[sc.IdxResultIntValue]); + } } 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, sc.idxMap[sc.IdxResultIntValue]); + } } 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, sc.idxMap[sc.IdxResultChainOwnerID]); + } } 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, sc.idxMap[sc.IdxResultChainOwnerID]); + } } 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, sc.idxMap[sc.IdxResultIntValue]); + } } 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, sc.idxMap[sc.IdxResultIntValue]); + } } 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, sc.idxMap[sc.IdxResultCounter]); + } } 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, sc.idxMap[sc.IdxResultCounter]); + } } export class MapStringToImmutableInt64 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } getInt64(key: string): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.objID, wasmlib.Key32.fromString(key).getKeyID()); + return new wasmlib.ScImmutableInt64(this.objID, wasmlib.Key32.fromString(key)); } } export class ImmutableGetIntResults extends wasmlib.ScMapID { - values(): sc.MapStringToImmutableInt64 { - return new sc.MapStringToImmutableInt64(this.mapID); - } + return new sc.MapStringToImmutableInt64(this.mapID); + } } export class MapStringToMutableInt64 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getInt64(key: string): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.objID, wasmlib.Key32.fromString(key).getKeyID()); + return new wasmlib.ScMutableInt64(this.objID, wasmlib.Key32.fromString(key)); } } export class MutableGetIntResults extends wasmlib.ScMapID { - values(): sc.MapStringToMutableInt64 { - return new sc.MapStringToMutableInt64(this.mapID); - } + return new sc.MapStringToMutableInt64(this.mapID); + } } export class MapStringToImmutableString { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } getString(key: string): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.objID, wasmlib.Key32.fromString(key).getKeyID()); + return new wasmlib.ScImmutableString(this.objID, wasmlib.Key32.fromString(key)); } } export class ImmutableGetStringValueResults extends wasmlib.ScMapID { - vars(): sc.MapStringToImmutableString { - return new sc.MapStringToImmutableString(this.mapID); - } + return new sc.MapStringToImmutableString(this.mapID); + } } export class MapStringToMutableString { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getString(key: string): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.objID, wasmlib.Key32.fromString(key).getKeyID()); + return new wasmlib.ScMutableString(this.objID, wasmlib.Key32.fromString(key)); } } export class MutableGetStringValueResults extends wasmlib.ScMapID { - vars(): sc.MapStringToMutableString { - return new sc.MapStringToMutableString(this.mapID); - } + return new sc.MapStringToMutableString(this.mapID); + } } 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, sc.idxMap[sc.IdxResultChainOwnerID]); + } } 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, sc.idxMap[sc.IdxResultChainOwnerID]); + } } 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, sc.idxMap[sc.IdxResultSandboxCall]); + } } 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, sc.idxMap[sc.IdxResultSandboxCall]); + } } diff --git a/contracts/wasm/testcore/ts/testcore/state.ts b/contracts/wasm/testcore/ts/testcore/state.ts index f2fe2ddfa6..3a20e3d512 100644 --- a/contracts/wasm/testcore/ts/testcore/state.ts +++ b/contracts/wasm/testcore/ts/testcore/state.ts @@ -5,53 +5,51 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxStateCounter]); + } hnameEP(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxStateHnameEP]); - } + return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxStateHnameEP]); + } ints(): sc.MapStringToImmutableInt64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateInts], wasmlib.TYPE_MAP); - return new sc.MapStringToImmutableInt64(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateInts], 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, sc.idxMap[sc.IdxStateMintedColor]); + } mintedSupply(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateMintedSupply]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateMintedSupply]); + } } export class MutableTestCoreState extends wasmlib.ScMapID { - counter(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateCounter]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateCounter]); + } hnameEP(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxStateHnameEP]); - } + return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxStateHnameEP]); + } ints(): sc.MapStringToMutableInt64 { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateInts], wasmlib.TYPE_MAP); - return new sc.MapStringToMutableInt64(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateInts], 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, sc.idxMap[sc.IdxStateMintedColor]); + } mintedSupply(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateMintedSupply]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateMintedSupply]); + } } diff --git a/contracts/wasm/testcore/ts/testcore/testcore.ts b/contracts/wasm/testcore/ts/testcore/testcore.ts index 2d72873ae3..58e7e960ed 100644 --- a/contracts/wasm/testcore/ts/testcore/testcore.ts +++ b/contracts/wasm/testcore/ts/testcore/testcore.ts @@ -107,7 +107,7 @@ export function funcSetInt(ctx: wasmlib.ScFuncContext, f: sc.SetIntContext): voi } export function funcSpawn(ctx: wasmlib.ScFuncContext, f: sc.SpawnContext): void { - let spawnName = sc.ScName + "Spawned"; + let spawnName = sc.ScName + "_spawned"; let spawnDescr = "spawned contract description"; ctx.deploy(f.params.progHash().value(), spawnName, spawnDescr, null); diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/consts.go b/contracts/wasm/testwasmlib/go/testwasmlib/consts.go index 17f1e726ee..b28384f1f9 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/consts.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/consts.go @@ -16,44 +16,57 @@ const ( ) const ( - ParamAddress = wasmlib.Key("address") - ParamAgentID = wasmlib.Key("agentID") - ParamBlockIndex = wasmlib.Key("blockIndex") - ParamBytes = wasmlib.Key("bytes") - ParamChainID = wasmlib.Key("chainID") - ParamColor = wasmlib.Key("color") - ParamHash = wasmlib.Key("hash") - ParamHname = wasmlib.Key("hname") - ParamIndex = wasmlib.Key("index") - ParamInt16 = wasmlib.Key("int16") - ParamInt32 = wasmlib.Key("int32") - ParamInt64 = wasmlib.Key("int64") - ParamName = wasmlib.Key("name") - ParamRecordIndex = wasmlib.Key("recordIndex") - ParamRequestID = wasmlib.Key("requestID") - ParamString = wasmlib.Key("string") - ParamValue = wasmlib.Key("value") + ParamAddress = "address" + ParamAgentID = "agentID" + ParamBlockIndex = "blockIndex" + ParamBool = "bool" + ParamBytes = "bytes" + ParamChainID = "chainID" + ParamColor = "color" + ParamHash = "hash" + ParamHname = "hname" + ParamIndex = "index" + ParamInt16 = "int16" + ParamInt32 = "int32" + ParamInt64 = "int64" + ParamInt8 = "int8" + ParamName = "name" + ParamParam = "this" + ParamRecordIndex = "recordIndex" + ParamRequestID = "requestID" + ParamString = "string" + ParamUint16 = "uint16" + ParamUint32 = "uint32" + ParamUint64 = "uint64" + ParamUint8 = "uint8" + ParamValue = "value" ) const ( - ResultCount = wasmlib.Key("count") - ResultIotas = wasmlib.Key("iotas") - ResultLength = wasmlib.Key("length") - ResultRecord = wasmlib.Key("record") - ResultValue = wasmlib.Key("value") + ResultCount = "count" + ResultIotas = "iotas" + ResultLength = "length" + ResultRandom = "random" + ResultRecord = "record" + ResultValue = "value" ) -const StateArrays = wasmlib.Key("arrays") +const ( + StateArrays = "arrays" + StateRandom = "random" +) const ( FuncArrayClear = "arrayClear" FuncArrayCreate = "arrayCreate" FuncArraySet = "arraySet" FuncParamTypes = "paramTypes" + FuncRandom = "random" ViewArrayLength = "arrayLength" ViewArrayValue = "arrayValue" ViewBlockRecord = "blockRecord" ViewBlockRecords = "blockRecords" + ViewGetRandom = "getRandom" ViewIotaBalance = "iotaBalance" ) @@ -62,9 +75,11 @@ const ( HFuncArrayCreate = wasmlib.ScHname(0x1ed5b23b) HFuncArraySet = wasmlib.ScHname(0x2c4150b3) HFuncParamTypes = wasmlib.ScHname(0x6921c4cd) + HFuncRandom = wasmlib.ScHname(0xe86c97ca) HViewArrayLength = wasmlib.ScHname(0x3a831021) HViewArrayValue = wasmlib.ScHname(0x662dbd81) HViewBlockRecord = wasmlib.ScHname(0xad13b2f8) HViewBlockRecords = wasmlib.ScHname(0x16e249ea) + HViewGetRandom = wasmlib.ScHname(0x46263045) HViewIotaBalance = wasmlib.ScHname(0x9d3920bd) ) diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/contract.go b/contracts/wasm/testwasmlib/go/testwasmlib/contract.go index b4e9802136..816dc14035 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/contract.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/contract.go @@ -29,6 +29,10 @@ type ParamTypesCall struct { Params MutableParamTypesParams } +type RandomCall struct { + Func *wasmlib.ScFunc +} + type ArrayLengthCall struct { Func *wasmlib.ScView Params MutableArrayLengthParams @@ -53,6 +57,11 @@ type BlockRecordsCall struct { Results ImmutableBlockRecordsResults } +type GetRandomCall struct { + Func *wasmlib.ScView + Results ImmutableGetRandomResults +} + type IotaBalanceCall struct { Func *wasmlib.ScView Results ImmutableIotaBalanceResults @@ -86,6 +95,10 @@ func (sc Funcs) ParamTypes(ctx wasmlib.ScFuncCallContext) *ParamTypesCall { return f } +func (sc Funcs) Random(ctx wasmlib.ScFuncCallContext) *RandomCall { + return &RandomCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncRandom)} +} + 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) @@ -110,6 +123,12 @@ func (sc Funcs) BlockRecords(ctx wasmlib.ScViewCallContext) *BlockRecordsCall { return f } +func (sc Funcs) GetRandom(ctx wasmlib.ScViewCallContext) *GetRandomCall { + f := &GetRandomCall{Func: wasmlib.NewScView(ctx, HScName, HViewGetRandom)} + f.Func.SetPtrs(nil, &f.Results.id) + return f +} + func (sc Funcs) IotaBalance(ctx wasmlib.ScViewCallContext) *IotaBalanceCall { f := &IotaBalanceCall{Func: wasmlib.NewScView(ctx, HScName, HViewIotaBalance)} f.Func.SetPtrs(nil, &f.Results.id) diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/keys.go b/contracts/wasm/testwasmlib/go/testwasmlib/keys.go index 8dbbd0d026..e5d6841858 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/keys.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/keys.go @@ -13,34 +13,46 @@ const ( IdxParamAddress = 0 IdxParamAgentID = 1 IdxParamBlockIndex = 2 - IdxParamBytes = 3 - IdxParamChainID = 4 - IdxParamColor = 5 - IdxParamHash = 6 - IdxParamHname = 7 - IdxParamIndex = 8 - IdxParamInt16 = 9 - IdxParamInt32 = 10 - IdxParamInt64 = 11 - IdxParamName = 12 - IdxParamRecordIndex = 13 - IdxParamRequestID = 14 - IdxParamString = 15 - IdxParamValue = 16 - IdxResultCount = 17 - IdxResultIotas = 18 - IdxResultLength = 19 - IdxResultRecord = 20 - IdxResultValue = 21 - IdxStateArrays = 22 + IdxParamBool = 3 + IdxParamBytes = 4 + IdxParamChainID = 5 + IdxParamColor = 6 + IdxParamHash = 7 + IdxParamHname = 8 + IdxParamIndex = 9 + IdxParamInt16 = 10 + 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 + + IdxResultCount = 24 + IdxResultIotas = 25 + IdxResultLength = 26 + IdxResultRandom = 27 + IdxResultRecord = 28 + IdxResultValue = 29 + + IdxStateArrays = 30 + IdxStateRandom = 31 ) -const keyMapLen = 23 +const keyMapLen = 32 var keyMap = [keyMapLen]wasmlib.Key{ ParamAddress, ParamAgentID, ParamBlockIndex, + ParamBool, ParamBytes, ParamChainID, ParamColor, @@ -50,17 +62,25 @@ var keyMap = [keyMapLen]wasmlib.Key{ ParamInt16, ParamInt32, ParamInt64, + ParamInt8, ParamName, + ParamParam, ParamRecordIndex, ParamRequestID, ParamString, + ParamUint16, + ParamUint32, + ParamUint64, + ParamUint8, ParamValue, ResultCount, ResultIotas, ResultLength, + ResultRandom, ResultRecord, ResultValue, StateArrays, + StateRandom, } var idxMap [keyMapLen]wasmlib.Key32 diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/lib.go b/contracts/wasm/testwasmlib/go/testwasmlib/lib.go index d5b74fed67..19543d3317 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/lib.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/lib.go @@ -15,10 +15,12 @@ func OnLoad() { exports.AddFunc(FuncArrayCreate, funcArrayCreateThunk) exports.AddFunc(FuncArraySet, funcArraySetThunk) exports.AddFunc(FuncParamTypes, funcParamTypesThunk) + exports.AddFunc(FuncRandom, funcRandomThunk) exports.AddView(ViewArrayLength, viewArrayLengthThunk) exports.AddView(ViewArrayValue, viewArrayValueThunk) exports.AddView(ViewBlockRecord, viewBlockRecordThunk) exports.AddView(ViewBlockRecords, viewBlockRecordsThunk) + exports.AddView(ViewGetRandom, viewGetRandomThunk) exports.AddView(ViewIotaBalance, viewIotaBalanceThunk) for i, key := range keyMap { @@ -107,6 +109,21 @@ func funcParamTypesThunk(ctx wasmlib.ScFuncContext) { ctx.Log("testwasmlib.funcParamTypes ok") } +type RandomContext struct { + State MutableTestWasmLibState +} + +func funcRandomThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("testwasmlib.funcRandom") + f := &RandomContext{ + State: MutableTestWasmLibState{ + id: wasmlib.OBJ_ID_STATE, + }, + } + funcRandom(ctx, f) + ctx.Log("testwasmlib.funcRandom ok") +} + type ArrayLengthContext struct { Params ImmutableArrayLengthParams Results MutableArrayLengthResults @@ -205,6 +222,25 @@ func viewBlockRecordsThunk(ctx wasmlib.ScViewContext) { ctx.Log("testwasmlib.viewBlockRecords ok") } +type GetRandomContext struct { + Results MutableGetRandomResults + State ImmutableTestWasmLibState +} + +func viewGetRandomThunk(ctx wasmlib.ScViewContext) { + ctx.Log("testwasmlib.viewGetRandom") + f := &GetRandomContext{ + Results: MutableGetRandomResults{ + id: wasmlib.OBJ_ID_RESULTS, + }, + State: ImmutableTestWasmLibState{ + id: wasmlib.OBJ_ID_STATE, + }, + } + viewGetRandom(ctx, f) + ctx.Log("testwasmlib.viewGetRandom ok") +} + type IotaBalanceContext struct { Results MutableIotaBalanceResults State ImmutableTestWasmLibState diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/params.go b/contracts/wasm/testwasmlib/go/testwasmlib/params.go index 668e7b8e07..c31fca95d0 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/params.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/params.go @@ -93,6 +93,10 @@ func (s ImmutableParamTypesParams) AgentID() wasmlib.ScImmutableAgentID { return wasmlib.NewScImmutableAgentID(s.id, idxMap[IdxParamAgentID]) } +func (s ImmutableParamTypesParams) Bool() wasmlib.ScImmutableBool { + return wasmlib.NewScImmutableBool(s.id, idxMap[IdxParamBool]) +} + func (s ImmutableParamTypesParams) Bytes() wasmlib.ScImmutableBytes { return wasmlib.NewScImmutableBytes(s.id, idxMap[IdxParamBytes]) } @@ -125,6 +129,10 @@ func (s ImmutableParamTypesParams) Int64() wasmlib.ScImmutableInt64 { return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxParamInt64]) } +func (s ImmutableParamTypesParams) Int8() wasmlib.ScImmutableInt8 { + return wasmlib.NewScImmutableInt8(s.id, idxMap[IdxParamInt8]) +} + func (s ImmutableParamTypesParams) Param() MapStringToImmutableBytes { return MapStringToImmutableBytes{objID: s.id} } @@ -137,6 +145,22 @@ func (s ImmutableParamTypesParams) String() wasmlib.ScImmutableString { return wasmlib.NewScImmutableString(s.id, idxMap[IdxParamString]) } +func (s ImmutableParamTypesParams) Uint16() wasmlib.ScImmutableUint16 { + return wasmlib.NewScImmutableUint16(s.id, idxMap[IdxParamUint16]) +} + +func (s ImmutableParamTypesParams) Uint32() wasmlib.ScImmutableUint32 { + return wasmlib.NewScImmutableUint32(s.id, idxMap[IdxParamUint32]) +} + +func (s ImmutableParamTypesParams) Uint64() wasmlib.ScImmutableUint64 { + return wasmlib.NewScImmutableUint64(s.id, idxMap[IdxParamUint64]) +} + +func (s ImmutableParamTypesParams) Uint8() wasmlib.ScImmutableUint8 { + return wasmlib.NewScImmutableUint8(s.id, idxMap[IdxParamUint8]) +} + type MapStringToMutableBytes struct { objID int32 } @@ -161,6 +185,10 @@ func (s MutableParamTypesParams) AgentID() wasmlib.ScMutableAgentID { return wasmlib.NewScMutableAgentID(s.id, idxMap[IdxParamAgentID]) } +func (s MutableParamTypesParams) Bool() wasmlib.ScMutableBool { + return wasmlib.NewScMutableBool(s.id, idxMap[IdxParamBool]) +} + func (s MutableParamTypesParams) Bytes() wasmlib.ScMutableBytes { return wasmlib.NewScMutableBytes(s.id, idxMap[IdxParamBytes]) } @@ -193,6 +221,10 @@ func (s MutableParamTypesParams) Int64() wasmlib.ScMutableInt64 { return wasmlib.NewScMutableInt64(s.id, idxMap[IdxParamInt64]) } +func (s MutableParamTypesParams) Int8() wasmlib.ScMutableInt8 { + return wasmlib.NewScMutableInt8(s.id, idxMap[IdxParamInt8]) +} + func (s MutableParamTypesParams) Param() MapStringToMutableBytes { return MapStringToMutableBytes{objID: s.id} } @@ -205,6 +237,22 @@ func (s MutableParamTypesParams) String() wasmlib.ScMutableString { return wasmlib.NewScMutableString(s.id, idxMap[IdxParamString]) } +func (s MutableParamTypesParams) Uint16() wasmlib.ScMutableUint16 { + return wasmlib.NewScMutableUint16(s.id, idxMap[IdxParamUint16]) +} + +func (s MutableParamTypesParams) Uint32() wasmlib.ScMutableUint32 { + return wasmlib.NewScMutableUint32(s.id, idxMap[IdxParamUint32]) +} + +func (s MutableParamTypesParams) Uint64() wasmlib.ScMutableUint64 { + return wasmlib.NewScMutableUint64(s.id, idxMap[IdxParamUint64]) +} + +func (s MutableParamTypesParams) Uint8() wasmlib.ScMutableUint8 { + return wasmlib.NewScMutableUint8(s.id, idxMap[IdxParamUint8]) +} + type ImmutableArrayLengthParams struct { id int32 } diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/results.go b/contracts/wasm/testwasmlib/go/testwasmlib/results.go index 2d85a02d1f..9cb62e01e0 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/results.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/results.go @@ -73,6 +73,22 @@ func (s MutableBlockRecordsResults) Count() wasmlib.ScMutableInt32 { return wasmlib.NewScMutableInt32(s.id, idxMap[IdxResultCount]) } +type ImmutableGetRandomResults struct { + id int32 +} + +func (s ImmutableGetRandomResults) Random() wasmlib.ScImmutableInt64 { + return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultRandom]) +} + +type MutableGetRandomResults struct { + id int32 +} + +func (s MutableGetRandomResults) Random() wasmlib.ScMutableInt64 { + return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultRandom]) +} + type ImmutableIotaBalanceResults struct { id int32 } diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/state.go b/contracts/wasm/testwasmlib/go/testwasmlib/state.go index 5389e238b3..7d08d8f873 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/state.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/state.go @@ -27,6 +27,10 @@ func (s ImmutableTestWasmLibState) Arrays() MapStringToImmutableStringArray { return MapStringToImmutableStringArray{objID: mapID} } +func (s ImmutableTestWasmLibState) Random() wasmlib.ScImmutableInt64 { + return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateRandom]) +} + type MapStringToMutableStringArray struct { objID int32 } @@ -48,3 +52,7 @@ func (s MutableTestWasmLibState) Arrays() MapStringToMutableStringArray { mapID := wasmlib.GetObjectID(s.id, idxMap[IdxStateArrays], wasmlib.TYPE_MAP) return MapStringToMutableStringArray{objID: mapID} } + +func (s MutableTestWasmLibState) Random() wasmlib.ScMutableInt64 { + return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateRandom]) +} diff --git a/contracts/wasm/testwasmlib/go/testwasmlib/testwasmlib.go b/contracts/wasm/testwasmlib/go/testwasmlib/testwasmlib.go index b466b76b91..dba9a43d1f 100644 --- a/contracts/wasm/testwasmlib/go/testwasmlib/testwasmlib.go +++ b/contracts/wasm/testwasmlib/go/testwasmlib/testwasmlib.go @@ -17,6 +17,9 @@ func funcParamTypes(ctx wasmlib.ScFuncContext, f *ParamTypesContext) { if f.Params.AgentID().Exists() { ctx.Require(f.Params.AgentID().Value() == ctx.AccountID(), "mismatch: AgentID") } + if f.Params.Bool().Exists() { + ctx.Require(f.Params.Bool().Value(), "mismatch: Bool") + } if f.Params.Bytes().Exists() { byteData := []byte("these are bytes") ctx.Require(bytes.Equal(f.Params.Bytes().Value(), byteData), "mismatch: Bytes") @@ -35,14 +38,17 @@ func funcParamTypes(ctx wasmlib.ScFuncContext, f *ParamTypesContext) { if f.Params.Hname().Exists() { ctx.Require(f.Params.Hname().Value() == ctx.AccountID().Hname(), "mismatch: Hname") } + if f.Params.Int8().Exists() { + ctx.Require(f.Params.Int8().Value() == -123, "mismatch: Int8") + } if f.Params.Int16().Exists() { - ctx.Require(f.Params.Int16().Value() == 12345, "mismatch: Int16") + ctx.Require(f.Params.Int16().Value() == -12345, "mismatch: Int16") } if f.Params.Int32().Exists() { - ctx.Require(f.Params.Int32().Value() == 1234567890, "mismatch: Int32") + ctx.Require(f.Params.Int32().Value() == -1234567890, "mismatch: Int32") } if f.Params.Int64().Exists() { - ctx.Require(f.Params.Int64().Value() == 1234567890123456789, "mismatch: Int64") + ctx.Require(f.Params.Int64().Value() == -1234567890123456789, "mismatch: Int64") } if f.Params.RequestID().Exists() { requestID := wasmlib.NewScRequestIDFromBytes([]byte("abcdefghijklmnopqrstuvwxyz123456\x00\x00")) @@ -51,6 +57,18 @@ func funcParamTypes(ctx wasmlib.ScFuncContext, f *ParamTypesContext) { if f.Params.String().Exists() { ctx.Require(f.Params.String().Value() == "this is a string", "mismatch: String") } + if f.Params.Uint8().Exists() { + ctx.Require(f.Params.Uint8().Value() == 123, "mismatch: Uint8") + } + if f.Params.Uint16().Exists() { + ctx.Require(f.Params.Uint16().Value() == 12345, "mismatch: Uint16") + } + if f.Params.Uint32().Exists() { + ctx.Require(f.Params.Uint32().Value() == 1234567890, "mismatch: Uint32") + } + if f.Params.Uint64().Exists() { + ctx.Require(f.Params.Uint64().Value() == 1234567890123456789, "mismatch: Uint64") + } } func viewBlockRecord(ctx wasmlib.ScViewContext, f *BlockRecordContext) { @@ -107,3 +125,11 @@ func viewArrayValue(ctx wasmlib.ScViewContext, f *ArrayValueContext) { func viewIotaBalance(ctx wasmlib.ScViewContext, f *IotaBalanceContext) { f.Results.Iotas().SetValue(ctx.Balances().Balance(wasmlib.IOTA)) } + +func funcRandom(ctx wasmlib.ScFuncContext, f *RandomContext) { + f.State.Random().SetValue(ctx.Random(1000)) +} + +func viewGetRandom(ctx wasmlib.ScViewContext, f *GetRandomContext) { + f.Results.Random().SetValue(f.State.Random().Value()) +} diff --git a/contracts/wasm/testwasmlib/schema.yaml b/contracts/wasm/testwasmlib/schema.yaml index 06829b46f6..05b9d67cb9 100644 --- a/contracts/wasm/testwasmlib/schema.yaml +++ b/contracts/wasm/testwasmlib/schema.yaml @@ -5,6 +5,7 @@ typedefs: StringArray: String[] state: arrays: map[String]StringArray + random: Int64 funcs: arrayClear: params: @@ -21,17 +22,24 @@ funcs: params: address: Address? agentID: AgentID? + bool: Bool? bytes: Bytes? chainID: ChainID? color: Color? hash: Hash? hname: Hname? + int8: Int8? int16: Int16? int32: Int32? int64: Int64? param=this: map[String]Bytes? // special hook to be able to pass key/values as raw bytes requestID: RequestID? string: String? + uint8: Uint8? + uint16: Uint16? + uint32: Uint32? + uint64: Uint64? + random: views: arrayLength: params: @@ -58,3 +66,6 @@ views: iotaBalance: results: iotas: Int64 + getRandom: + results: + random: Int64 diff --git a/contracts/wasm/testwasmlib/src/consts.rs b/contracts/wasm/testwasmlib/src/consts.rs index 375988caee..8af1763e67 100644 --- a/contracts/wasm/testwasmlib/src/consts.rs +++ b/contracts/wasm/testwasmlib/src/consts.rs @@ -5,60 +5,69 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; -pub const SC_NAME: &str = "testwasmlib"; -pub const SC_DESCRIPTION: &str = "Exercise all aspects of WasmLib"; -pub const HSC_NAME: ScHname = ScHname(0x89703a45); - -pub const PARAM_ADDRESS: &str = "address"; -pub const PARAM_AGENT_ID: &str = "agentID"; -pub const PARAM_BLOCK_INDEX: &str = "blockIndex"; -pub const PARAM_BYTES: &str = "bytes"; -pub const PARAM_CHAIN_ID: &str = "chainID"; -pub const PARAM_COLOR: &str = "color"; -pub const PARAM_HASH: &str = "hash"; -pub const PARAM_HNAME: &str = "hname"; -pub const PARAM_INDEX: &str = "index"; -pub const PARAM_INT16: &str = "int16"; -pub const PARAM_INT32: &str = "int32"; -pub const PARAM_INT64: &str = "int64"; -pub const PARAM_NAME: &str = "name"; -pub const PARAM_RECORD_INDEX: &str = "recordIndex"; -pub const PARAM_REQUEST_ID: &str = "requestID"; -pub const PARAM_STRING: &str = "string"; -pub const PARAM_VALUE: &str = "value"; +pub const SC_NAME : &str = "testwasmlib"; +pub const SC_DESCRIPTION : &str = "Exercise all aspects of WasmLib"; +pub const HSC_NAME : ScHname = ScHname(0x89703a45); -pub const RESULT_COUNT: &str = "count"; -pub const RESULT_IOTAS: &str = "iotas"; -pub const RESULT_LENGTH: &str = "length"; -pub const RESULT_RECORD: &str = "record"; -pub const RESULT_VALUE: &str = "value"; +pub const PARAM_ADDRESS : &str = "address"; +pub const PARAM_AGENT_ID : &str = "agentID"; +pub const PARAM_BLOCK_INDEX : &str = "blockIndex"; +pub const PARAM_BOOL : &str = "bool"; +pub const PARAM_BYTES : &str = "bytes"; +pub const PARAM_CHAIN_ID : &str = "chainID"; +pub const PARAM_COLOR : &str = "color"; +pub const PARAM_HASH : &str = "hash"; +pub const PARAM_HNAME : &str = "hname"; +pub const PARAM_INDEX : &str = "index"; +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_NAME : &str = "name"; +pub const PARAM_PARAM : &str = "this"; +pub const PARAM_RECORD_INDEX : &str = "recordIndex"; +pub const PARAM_REQUEST_ID : &str = "requestID"; +pub const PARAM_STRING : &str = "string"; +pub const PARAM_UINT16 : &str = "uint16"; +pub const PARAM_UINT32 : &str = "uint32"; +pub const PARAM_UINT64 : &str = "uint64"; +pub const PARAM_UINT8 : &str = "uint8"; +pub const PARAM_VALUE : &str = "value"; -pub const STATE_ARRAYS: &str = "arrays"; +pub const RESULT_COUNT : &str = "count"; +pub const RESULT_IOTAS : &str = "iotas"; +pub const RESULT_LENGTH : &str = "length"; +pub const RESULT_RANDOM : &str = "random"; +pub const RESULT_RECORD : &str = "record"; +pub const RESULT_VALUE : &str = "value"; -pub const FUNC_ARRAY_CLEAR: &str = "arrayClear"; -pub const FUNC_ARRAY_CREATE: &str = "arrayCreate"; -pub const FUNC_ARRAY_SET: &str = "arraySet"; -pub const FUNC_PARAM_TYPES: &str = "paramTypes"; -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_IOTA_BALANCE: &str = "iotaBalance"; +pub const STATE_ARRAYS : &str = "arrays"; +pub const STATE_RANDOM : &str = "random"; -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_PARAM_TYPES: ScHname = ScHname(0x6921c4cd); -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_IOTA_BALANCE: ScHname = ScHname(0x9d3920bd); +pub const FUNC_ARRAY_CLEAR : &str = "arrayClear"; +pub const FUNC_ARRAY_CREATE : &str = "arrayCreate"; +pub const FUNC_ARRAY_SET : &str = "arraySet"; +pub const FUNC_PARAM_TYPES : &str = "paramTypes"; +pub const FUNC_RANDOM : &str = "random"; +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"; -// @formatter:on +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_PARAM_TYPES : ScHname = ScHname(0x6921c4cd); +pub const HFUNC_RANDOM : ScHname = ScHname(0xe86c97ca); +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); diff --git a/contracts/wasm/testwasmlib/src/contract.rs b/contracts/wasm/testwasmlib/src/contract.rs index 52ec39daff..5df0ede6ee 100644 --- a/contracts/wasm/testwasmlib/src/contract.rs +++ b/contracts/wasm/testwasmlib/src/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -18,52 +16,61 @@ use crate::params::*; use crate::results::*; pub struct ArrayClearCall { - pub func: ScFunc, - pub params: MutableArrayClearParams, + pub func: ScFunc, + pub params: MutableArrayClearParams, } pub struct ArrayCreateCall { - pub func: ScFunc, - pub params: MutableArrayCreateParams, + pub func: ScFunc, + pub params: MutableArrayCreateParams, } pub struct ArraySetCall { - pub func: ScFunc, - pub params: MutableArraySetParams, + pub func: ScFunc, + pub params: MutableArraySetParams, } pub struct ParamTypesCall { - pub func: ScFunc, - pub params: MutableParamTypesParams, + pub func: ScFunc, + pub params: MutableParamTypesParams, +} + +pub struct RandomCall { + pub func: ScFunc, } pub struct ArrayLengthCall { - pub func: ScView, - pub params: MutableArrayLengthParams, - pub results: ImmutableArrayLengthResults, + pub func: ScView, + pub params: MutableArrayLengthParams, + pub results: ImmutableArrayLengthResults, } pub struct ArrayValueCall { - pub func: ScView, - pub params: MutableArrayValueParams, - pub results: ImmutableArrayValueResults, + pub func: ScView, + pub params: MutableArrayValueParams, + pub results: ImmutableArrayValueResults, } pub struct BlockRecordCall { - pub func: ScView, - pub params: MutableBlockRecordParams, - pub results: ImmutableBlockRecordResults, + pub func: ScView, + pub params: MutableBlockRecordParams, + pub results: ImmutableBlockRecordResults, } pub struct BlockRecordsCall { - pub func: ScView, - pub params: MutableBlockRecordsParams, - pub results: ImmutableBlockRecordsResults, + pub func: ScView, + pub params: MutableBlockRecordsParams, + pub results: ImmutableBlockRecordsResults, +} + +pub struct GetRandomCall { + pub func: ScView, + pub results: ImmutableGetRandomResults, } pub struct IotaBalanceCall { - pub func: ScView, - pub results: ImmutableIotaBalanceResults, + pub func: ScView, + pub results: ImmutableIotaBalanceResults, } pub struct ScFuncs { @@ -72,80 +79,101 @@ pub struct ScFuncs { impl ScFuncs { pub fn array_clear(_ctx: & dyn ScFuncCallContext) -> ArrayClearCall { let mut f = ArrayClearCall { - func: ScFunc::new(HSC_NAME, HFUNC_ARRAY_CLEAR), + func: ScFunc::new(HSC_NAME, HFUNC_ARRAY_CLEAR), params: MutableArrayClearParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn array_create(_ctx: & dyn ScFuncCallContext) -> ArrayCreateCall { let mut f = ArrayCreateCall { - func: ScFunc::new(HSC_NAME, HFUNC_ARRAY_CREATE), + func: ScFunc::new(HSC_NAME, HFUNC_ARRAY_CREATE), params: MutableArrayCreateParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn array_set(_ctx: & dyn ScFuncCallContext) -> ArraySetCall { let mut f = ArraySetCall { - func: ScFunc::new(HSC_NAME, HFUNC_ARRAY_SET), + func: ScFunc::new(HSC_NAME, HFUNC_ARRAY_SET), params: MutableArraySetParams { 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), + func: ScFunc::new(HSC_NAME, HFUNC_PARAM_TYPES), params: MutableParamTypesParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + + pub fn random(_ctx: & dyn ScFuncCallContext) -> RandomCall { + RandomCall { + func: ScFunc::new(HSC_NAME, HFUNC_RANDOM), + } + } + pub fn array_length(_ctx: & dyn ScViewCallContext) -> ArrayLengthCall { let mut f = ArrayLengthCall { - func: ScView::new(HSC_NAME, HVIEW_ARRAY_LENGTH), - params: MutableArrayLengthParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_ARRAY_LENGTH), + params: MutableArrayLengthParams { id: 0 }, results: ImmutableArrayLengthResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn array_value(_ctx: & dyn ScViewCallContext) -> ArrayValueCall { let mut f = ArrayValueCall { - func: ScView::new(HSC_NAME, HVIEW_ARRAY_VALUE), - params: MutableArrayValueParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_ARRAY_VALUE), + params: MutableArrayValueParams { id: 0 }, results: ImmutableArrayValueResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn block_record(_ctx: & dyn ScViewCallContext) -> BlockRecordCall { let mut f = BlockRecordCall { - func: ScView::new(HSC_NAME, HVIEW_BLOCK_RECORD), - params: MutableBlockRecordParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_BLOCK_RECORD), + params: MutableBlockRecordParams { id: 0 }, results: ImmutableBlockRecordResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn block_records(_ctx: & dyn ScViewCallContext) -> BlockRecordsCall { let mut f = BlockRecordsCall { - func: ScView::new(HSC_NAME, HVIEW_BLOCK_RECORDS), - params: MutableBlockRecordsParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_BLOCK_RECORDS), + params: MutableBlockRecordsParams { id: 0 }, results: ImmutableBlockRecordsResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + + pub fn get_random(_ctx: & dyn ScViewCallContext) -> GetRandomCall { + let mut f = GetRandomCall { + func: ScView::new(HSC_NAME, HVIEW_GET_RANDOM), + results: ImmutableGetRandomResults { id: 0 }, + }; + f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); + f + } + pub fn iota_balance(_ctx: & dyn ScViewCallContext) -> IotaBalanceCall { let mut f = IotaBalanceCall { - func: ScView::new(HSC_NAME, HVIEW_IOTA_BALANCE), + func: ScView::new(HSC_NAME, HVIEW_IOTA_BALANCE), results: ImmutableIotaBalanceResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/contracts/wasm/testwasmlib/src/keys.rs b/contracts/wasm/testwasmlib/src/keys.rs index 99b969a6a1..f20b5ce4ed 100644 --- a/contracts/wasm/testwasmlib/src/keys.rs +++ b/contracts/wasm/testwasmlib/src/keys.rs @@ -5,64 +5,82 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use crate::*; -pub(crate) const IDX_PARAM_ADDRESS: usize = 0; -pub(crate) const IDX_PARAM_AGENT_ID: usize = 1; -pub(crate) const IDX_PARAM_BLOCK_INDEX: usize = 2; -pub(crate) const IDX_PARAM_BYTES: usize = 3; -pub(crate) const IDX_PARAM_CHAIN_ID: usize = 4; -pub(crate) const IDX_PARAM_COLOR: usize = 5; -pub(crate) const IDX_PARAM_HASH: usize = 6; -pub(crate) const IDX_PARAM_HNAME: usize = 7; -pub(crate) const IDX_PARAM_INDEX: usize = 8; -pub(crate) const IDX_PARAM_INT16: usize = 9; -pub(crate) const IDX_PARAM_INT32: usize = 10; -pub(crate) const IDX_PARAM_INT64: usize = 11; -pub(crate) const IDX_PARAM_NAME: usize = 12; -pub(crate) const IDX_PARAM_RECORD_INDEX: usize = 13; -pub(crate) const IDX_PARAM_REQUEST_ID: usize = 14; -pub(crate) const IDX_PARAM_STRING: usize = 15; -pub(crate) const IDX_PARAM_VALUE: usize = 16; -pub(crate) const IDX_RESULT_COUNT: usize = 17; -pub(crate) const IDX_RESULT_IOTAS: usize = 18; -pub(crate) const IDX_RESULT_LENGTH: usize = 19; -pub(crate) const IDX_RESULT_RECORD: usize = 20; -pub(crate) const IDX_RESULT_VALUE: usize = 21; -pub(crate) const IDX_STATE_ARRAYS: usize = 22; +pub(crate) const IDX_PARAM_ADDRESS : usize = 0; +pub(crate) const IDX_PARAM_AGENT_ID : usize = 1; +pub(crate) const IDX_PARAM_BLOCK_INDEX : usize = 2; +pub(crate) const IDX_PARAM_BOOL : usize = 3; +pub(crate) const IDX_PARAM_BYTES : usize = 4; +pub(crate) const IDX_PARAM_CHAIN_ID : usize = 5; +pub(crate) const IDX_PARAM_COLOR : usize = 6; +pub(crate) const IDX_PARAM_HASH : usize = 7; +pub(crate) const IDX_PARAM_HNAME : usize = 8; +pub(crate) const IDX_PARAM_INDEX : usize = 9; +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_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 const KEY_MAP_LEN: usize = 23; +pub(crate) const IDX_STATE_ARRAYS : usize = 30; +pub(crate) const IDX_STATE_RANDOM : usize = 31; + +pub const KEY_MAP_LEN: usize = 32; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ - PARAM_ADDRESS, - PARAM_AGENT_ID, - PARAM_BLOCK_INDEX, - PARAM_BYTES, - PARAM_CHAIN_ID, - PARAM_COLOR, - PARAM_HASH, - PARAM_HNAME, - PARAM_INDEX, - PARAM_INT16, - PARAM_INT32, - PARAM_INT64, - PARAM_NAME, - PARAM_RECORD_INDEX, - PARAM_REQUEST_ID, - PARAM_STRING, - PARAM_VALUE, - RESULT_COUNT, - RESULT_IOTAS, - RESULT_LENGTH, - RESULT_RECORD, - RESULT_VALUE, - STATE_ARRAYS, + PARAM_ADDRESS, + PARAM_AGENT_ID, + PARAM_BLOCK_INDEX, + PARAM_BOOL, + PARAM_BYTES, + PARAM_CHAIN_ID, + PARAM_COLOR, + PARAM_HASH, + PARAM_HNAME, + PARAM_INDEX, + PARAM_INT16, + PARAM_INT32, + PARAM_INT64, + PARAM_INT8, + PARAM_NAME, + PARAM_PARAM, + PARAM_RECORD_INDEX, + PARAM_REQUEST_ID, + PARAM_STRING, + PARAM_UINT16, + PARAM_UINT32, + PARAM_UINT64, + PARAM_UINT8, + PARAM_VALUE, + RESULT_COUNT, + RESULT_IOTAS, + RESULT_LENGTH, + RESULT_RANDOM, + RESULT_RECORD, + RESULT_VALUE, + STATE_ARRAYS, + STATE_RANDOM, ]; pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; @@ -72,5 +90,3 @@ pub fn idx_map(idx: usize) -> Key32 { IDX_MAP[idx] } } - -// @formatter:on diff --git a/contracts/wasm/testwasmlib/src/lib.rs b/contracts/wasm/testwasmlib/src/lib.rs index e24d7b3394..f064f1deb6 100644 --- a/contracts/wasm/testwasmlib/src/lib.rs +++ b/contracts/wasm/testwasmlib/src/lib.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] #![allow(unused_imports)] @@ -32,15 +30,17 @@ mod testwasmlib; #[no_mangle] fn on_load() { let exports = ScExports::new(); - 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_PARAM_TYPES, func_param_types_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_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_PARAM_TYPES, func_param_types_thunk); + exports.add_func(FUNC_RANDOM, func_random_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_IOTA_BALANCE, view_iota_balance_thunk); + exports.add_view(VIEW_GET_RANDOM, view_get_random_thunk); + exports.add_view(VIEW_IOTA_BALANCE, view_iota_balance_thunk); unsafe { for i in 0..KEY_MAP_LEN { @@ -50,201 +50,233 @@ fn on_load() { } pub struct ArrayClearContext { - params: ImmutableArrayClearParams, - state: MutableTestWasmLibState, + params: ImmutableArrayClearParams, + state: MutableTestWasmLibState, } fn func_array_clear_thunk(ctx: &ScFuncContext) { - ctx.log("testwasmlib.funcArrayClear"); - let f = ArrayClearContext { - params: ImmutableArrayClearParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestWasmLibState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.name().exists(), "missing mandatory name"); - func_array_clear(ctx, &f); - ctx.log("testwasmlib.funcArrayClear ok"); + ctx.log("testwasmlib.funcArrayClear"); + let f = ArrayClearContext { + params: ImmutableArrayClearParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.name().exists(), "missing mandatory name"); + func_array_clear(ctx, &f); + ctx.log("testwasmlib.funcArrayClear ok"); } pub struct ArrayCreateContext { - params: ImmutableArrayCreateParams, - state: MutableTestWasmLibState, + params: ImmutableArrayCreateParams, + state: MutableTestWasmLibState, } fn func_array_create_thunk(ctx: &ScFuncContext) { - ctx.log("testwasmlib.funcArrayCreate"); - let f = ArrayCreateContext { - params: ImmutableArrayCreateParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestWasmLibState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.name().exists(), "missing mandatory name"); - func_array_create(ctx, &f); - ctx.log("testwasmlib.funcArrayCreate ok"); + ctx.log("testwasmlib.funcArrayCreate"); + let f = ArrayCreateContext { + params: ImmutableArrayCreateParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.name().exists(), "missing mandatory name"); + func_array_create(ctx, &f); + ctx.log("testwasmlib.funcArrayCreate ok"); } pub struct ArraySetContext { - params: ImmutableArraySetParams, - state: MutableTestWasmLibState, + params: ImmutableArraySetParams, + state: MutableTestWasmLibState, } fn func_array_set_thunk(ctx: &ScFuncContext) { - ctx.log("testwasmlib.funcArraySet"); - let f = ArraySetContext { - params: ImmutableArraySetParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestWasmLibState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.index().exists(), "missing mandatory index"); - ctx.require(f.params.name().exists(), "missing mandatory name"); - ctx.require(f.params.value().exists(), "missing mandatory value"); - func_array_set(ctx, &f); - ctx.log("testwasmlib.funcArraySet ok"); + ctx.log("testwasmlib.funcArraySet"); + let f = ArraySetContext { + params: ImmutableArraySetParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.index().exists(), "missing mandatory index"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + ctx.require(f.params.value().exists(), "missing mandatory value"); + func_array_set(ctx, &f); + ctx.log("testwasmlib.funcArraySet ok"); } pub struct ParamTypesContext { - params: ImmutableParamTypesParams, - state: MutableTestWasmLibState, + params: ImmutableParamTypesParams, + state: MutableTestWasmLibState, } fn func_param_types_thunk(ctx: &ScFuncContext) { - ctx.log("testwasmlib.funcParamTypes"); - let f = ParamTypesContext { - params: ImmutableParamTypesParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTestWasmLibState { - id: OBJ_ID_STATE, - }, - }; - func_param_types(ctx, &f); - ctx.log("testwasmlib.funcParamTypes ok"); + ctx.log("testwasmlib.funcParamTypes"); + let f = ParamTypesContext { + params: ImmutableParamTypesParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + func_param_types(ctx, &f); + ctx.log("testwasmlib.funcParamTypes ok"); +} + +pub struct RandomContext { + state: MutableTestWasmLibState, +} + +fn func_random_thunk(ctx: &ScFuncContext) { + ctx.log("testwasmlib.funcRandom"); + let f = RandomContext { + state: MutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + func_random(ctx, &f); + ctx.log("testwasmlib.funcRandom ok"); } pub struct ArrayLengthContext { - params: ImmutableArrayLengthParams, - results: MutableArrayLengthResults, - state: ImmutableTestWasmLibState, + params: ImmutableArrayLengthParams, + results: MutableArrayLengthResults, + state: ImmutableTestWasmLibState, } fn view_array_length_thunk(ctx: &ScViewContext) { - ctx.log("testwasmlib.viewArrayLength"); - let f = ArrayLengthContext { - params: ImmutableArrayLengthParams { - id: OBJ_ID_PARAMS, - }, - results: MutableArrayLengthResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableTestWasmLibState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.name().exists(), "missing mandatory name"); - view_array_length(ctx, &f); - ctx.log("testwasmlib.viewArrayLength ok"); + ctx.log("testwasmlib.viewArrayLength"); + let f = ArrayLengthContext { + params: ImmutableArrayLengthParams { + id: OBJ_ID_PARAMS, + }, + results: MutableArrayLengthResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.name().exists(), "missing mandatory name"); + view_array_length(ctx, &f); + ctx.log("testwasmlib.viewArrayLength ok"); } pub struct ArrayValueContext { - params: ImmutableArrayValueParams, - results: MutableArrayValueResults, - state: ImmutableTestWasmLibState, + params: ImmutableArrayValueParams, + results: MutableArrayValueResults, + state: ImmutableTestWasmLibState, } fn view_array_value_thunk(ctx: &ScViewContext) { - ctx.log("testwasmlib.viewArrayValue"); - let f = ArrayValueContext { - params: ImmutableArrayValueParams { - id: OBJ_ID_PARAMS, - }, - results: MutableArrayValueResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableTestWasmLibState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.index().exists(), "missing mandatory index"); - ctx.require(f.params.name().exists(), "missing mandatory name"); - view_array_value(ctx, &f); - ctx.log("testwasmlib.viewArrayValue ok"); + ctx.log("testwasmlib.viewArrayValue"); + let f = ArrayValueContext { + params: ImmutableArrayValueParams { + id: OBJ_ID_PARAMS, + }, + results: MutableArrayValueResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.index().exists(), "missing mandatory index"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + view_array_value(ctx, &f); + ctx.log("testwasmlib.viewArrayValue ok"); } pub struct BlockRecordContext { - params: ImmutableBlockRecordParams, - results: MutableBlockRecordResults, - state: ImmutableTestWasmLibState, + params: ImmutableBlockRecordParams, + results: MutableBlockRecordResults, + state: ImmutableTestWasmLibState, } fn view_block_record_thunk(ctx: &ScViewContext) { - ctx.log("testwasmlib.viewBlockRecord"); - let f = BlockRecordContext { - params: ImmutableBlockRecordParams { - id: OBJ_ID_PARAMS, - }, - results: MutableBlockRecordResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableTestWasmLibState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.block_index().exists(), "missing mandatory blockIndex"); - ctx.require(f.params.record_index().exists(), "missing mandatory recordIndex"); - view_block_record(ctx, &f); - ctx.log("testwasmlib.viewBlockRecord ok"); + ctx.log("testwasmlib.viewBlockRecord"); + let f = BlockRecordContext { + params: ImmutableBlockRecordParams { + id: OBJ_ID_PARAMS, + }, + results: MutableBlockRecordResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.block_index().exists(), "missing mandatory blockIndex"); + ctx.require(f.params.record_index().exists(), "missing mandatory recordIndex"); + view_block_record(ctx, &f); + ctx.log("testwasmlib.viewBlockRecord ok"); } pub struct BlockRecordsContext { - params: ImmutableBlockRecordsParams, - results: MutableBlockRecordsResults, - state: ImmutableTestWasmLibState, + params: ImmutableBlockRecordsParams, + results: MutableBlockRecordsResults, + state: ImmutableTestWasmLibState, } fn view_block_records_thunk(ctx: &ScViewContext) { - ctx.log("testwasmlib.viewBlockRecords"); - let f = BlockRecordsContext { - params: ImmutableBlockRecordsParams { - id: OBJ_ID_PARAMS, - }, - results: MutableBlockRecordsResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableTestWasmLibState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.block_index().exists(), "missing mandatory blockIndex"); - view_block_records(ctx, &f); - ctx.log("testwasmlib.viewBlockRecords ok"); + ctx.log("testwasmlib.viewBlockRecords"); + let f = BlockRecordsContext { + params: ImmutableBlockRecordsParams { + id: OBJ_ID_PARAMS, + }, + results: MutableBlockRecordsResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.block_index().exists(), "missing mandatory blockIndex"); + view_block_records(ctx, &f); + ctx.log("testwasmlib.viewBlockRecords ok"); +} + +pub struct GetRandomContext { + results: MutableGetRandomResults, + state: ImmutableTestWasmLibState, +} + +fn view_get_random_thunk(ctx: &ScViewContext) { + ctx.log("testwasmlib.viewGetRandom"); + let f = GetRandomContext { + results: MutableGetRandomResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + view_get_random(ctx, &f); + ctx.log("testwasmlib.viewGetRandom ok"); } pub struct IotaBalanceContext { - results: MutableIotaBalanceResults, - state: ImmutableTestWasmLibState, + results: MutableIotaBalanceResults, + state: ImmutableTestWasmLibState, } fn view_iota_balance_thunk(ctx: &ScViewContext) { - ctx.log("testwasmlib.viewIotaBalance"); - let f = IotaBalanceContext { - results: MutableIotaBalanceResults { - id: OBJ_ID_RESULTS, - }, - state: ImmutableTestWasmLibState { - id: OBJ_ID_STATE, - }, - }; - view_iota_balance(ctx, &f); - ctx.log("testwasmlib.viewIotaBalance ok"); -} - -// @formatter:on + ctx.log("testwasmlib.viewIotaBalance"); + let f = IotaBalanceContext { + results: MutableIotaBalanceResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutableTestWasmLibState { + id: OBJ_ID_STATE, + }, + }; + view_iota_balance(ctx, &f); + ctx.log("testwasmlib.viewIotaBalance ok"); +} diff --git a/contracts/wasm/testwasmlib/src/params.rs b/contracts/wasm/testwasmlib/src/params.rs index 2356f21b0d..aaa1f6b8b4 100644 --- a/contracts/wasm/testwasmlib/src/params.rs +++ b/contracts/wasm/testwasmlib/src/params.rs @@ -13,6 +13,7 @@ use wasmlib::host::*; use crate::*; use crate::keys::*; +use crate::typedefs::*; #[derive(Clone, Copy)] pub struct ImmutableArrayClearParams { @@ -21,8 +22,8 @@ pub struct ImmutableArrayClearParams { impl ImmutableArrayClearParams { pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -32,8 +33,8 @@ pub struct MutableArrayClearParams { impl MutableArrayClearParams { pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -43,8 +44,8 @@ pub struct ImmutableArrayCreateParams { impl ImmutableArrayCreateParams { pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -54,8 +55,8 @@ pub struct MutableArrayCreateParams { impl MutableArrayCreateParams { pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -65,16 +66,16 @@ pub struct ImmutableArraySetParams { impl ImmutableArraySetParams { pub fn index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) + } pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } pub fn value(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_VALUE)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_VALUE)) + } } #[derive(Clone, Copy)] @@ -84,20 +85,20 @@ pub struct MutableArraySetParams { impl MutableArraySetParams { pub fn index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) - } + ScMutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) + } pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } pub fn value(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_VALUE)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_VALUE)) + } } pub struct MapStringToImmutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToImmutableBytes { @@ -113,65 +114,89 @@ pub struct ImmutableParamTypesParams { impl ImmutableParamTypesParams { pub fn address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) - } + ScImmutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + } pub fn agent_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) - } + ScImmutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + } + + pub fn bool(&self) -> ScImmutableBool { + ScImmutableBool::new(self.id, idx_map(IDX_PARAM_BOOL)) + } pub fn bytes(&self) -> ScImmutableBytes { - ScImmutableBytes::new(self.id, idx_map(IDX_PARAM_BYTES)) - } + ScImmutableBytes::new(self.id, idx_map(IDX_PARAM_BYTES)) + } pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) - } + ScImmutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + } pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } pub fn hash(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) - } + ScImmutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + } pub fn hname(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) - } + ScImmutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + } pub fn int16(&self) -> ScImmutableInt16 { - ScImmutableInt16::new(self.id, idx_map(IDX_PARAM_INT16)) - } + ScImmutableInt16::new(self.id, idx_map(IDX_PARAM_INT16)) + } pub fn int32(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_INT32)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_INT32)) + } pub fn int64(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + } + + pub fn int8(&self) -> ScImmutableInt8 { + ScImmutableInt8::new(self.id, idx_map(IDX_PARAM_INT8)) + } pub fn param(&self) -> MapStringToImmutableBytes { - MapStringToImmutableBytes { obj_id: self.id } - } + MapStringToImmutableBytes { obj_id: self.id } + } pub fn request_id(&self) -> ScImmutableRequestID { - ScImmutableRequestID::new(self.id, idx_map(IDX_PARAM_REQUEST_ID)) - } + ScImmutableRequestID::new(self.id, idx_map(IDX_PARAM_REQUEST_ID)) + } pub fn string(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + } + + pub fn uint16(&self) -> ScImmutableUint16 { + ScImmutableUint16::new(self.id, idx_map(IDX_PARAM_UINT16)) + } + + pub fn uint32(&self) -> ScImmutableUint32 { + ScImmutableUint32::new(self.id, idx_map(IDX_PARAM_UINT32)) + } + + pub fn uint64(&self) -> ScImmutableUint64 { + ScImmutableUint64::new(self.id, idx_map(IDX_PARAM_UINT64)) + } + + pub fn uint8(&self) -> ScImmutableUint8 { + ScImmutableUint8::new(self.id, idx_map(IDX_PARAM_UINT8)) + } } pub struct MapStringToMutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToMutableBytes { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_bytes(&self, key: &str) -> ScMutableBytes { @@ -186,56 +211,80 @@ pub struct MutableParamTypesParams { impl MutableParamTypesParams { pub fn address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) - } + ScMutableAddress::new(self.id, idx_map(IDX_PARAM_ADDRESS)) + } pub fn agent_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) - } + ScMutableAgentID::new(self.id, idx_map(IDX_PARAM_AGENT_ID)) + } + + pub fn bool(&self) -> ScMutableBool { + ScMutableBool::new(self.id, idx_map(IDX_PARAM_BOOL)) + } pub fn bytes(&self) -> ScMutableBytes { - ScMutableBytes::new(self.id, idx_map(IDX_PARAM_BYTES)) - } + ScMutableBytes::new(self.id, idx_map(IDX_PARAM_BYTES)) + } pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) - } + ScMutableChainID::new(self.id, idx_map(IDX_PARAM_CHAIN_ID)) + } pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } pub fn hash(&self) -> ScMutableHash { - ScMutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) - } + ScMutableHash::new(self.id, idx_map(IDX_PARAM_HASH)) + } pub fn hname(&self) -> ScMutableHname { - ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) - } + ScMutableHname::new(self.id, idx_map(IDX_PARAM_HNAME)) + } pub fn int16(&self) -> ScMutableInt16 { - ScMutableInt16::new(self.id, idx_map(IDX_PARAM_INT16)) - } + ScMutableInt16::new(self.id, idx_map(IDX_PARAM_INT16)) + } pub fn int32(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_INT32)) - } + ScMutableInt32::new(self.id, idx_map(IDX_PARAM_INT32)) + } pub fn int64(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) - } + ScMutableInt64::new(self.id, idx_map(IDX_PARAM_INT64)) + } + + pub fn int8(&self) -> ScMutableInt8 { + ScMutableInt8::new(self.id, idx_map(IDX_PARAM_INT8)) + } pub fn param(&self) -> MapStringToMutableBytes { - MapStringToMutableBytes { obj_id: self.id } - } + MapStringToMutableBytes { obj_id: self.id } + } pub fn request_id(&self) -> ScMutableRequestID { - ScMutableRequestID::new(self.id, idx_map(IDX_PARAM_REQUEST_ID)) - } + ScMutableRequestID::new(self.id, idx_map(IDX_PARAM_REQUEST_ID)) + } pub fn string(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_STRING)) + } + + pub fn uint16(&self) -> ScMutableUint16 { + ScMutableUint16::new(self.id, idx_map(IDX_PARAM_UINT16)) + } + + pub fn uint32(&self) -> ScMutableUint32 { + ScMutableUint32::new(self.id, idx_map(IDX_PARAM_UINT32)) + } + + pub fn uint64(&self) -> ScMutableUint64 { + ScMutableUint64::new(self.id, idx_map(IDX_PARAM_UINT64)) + } + + pub fn uint8(&self) -> ScMutableUint8 { + ScMutableUint8::new(self.id, idx_map(IDX_PARAM_UINT8)) + } } #[derive(Clone, Copy)] @@ -245,8 +294,8 @@ pub struct ImmutableArrayLengthParams { impl ImmutableArrayLengthParams { pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -256,8 +305,8 @@ pub struct MutableArrayLengthParams { impl MutableArrayLengthParams { pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -267,12 +316,12 @@ pub struct ImmutableArrayValueParams { impl ImmutableArrayValueParams { pub fn index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) + } pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -282,12 +331,12 @@ pub struct MutableArrayValueParams { impl MutableArrayValueParams { pub fn index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) - } + ScMutableInt32::new(self.id, idx_map(IDX_PARAM_INDEX)) + } pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_NAME)) + } } #[derive(Clone, Copy)] @@ -297,12 +346,12 @@ 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, idx_map(IDX_PARAM_BLOCK_INDEX)) + } pub fn record_index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_RECORD_INDEX)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_PARAM_RECORD_INDEX)) + } } #[derive(Clone, Copy)] @@ -312,12 +361,12 @@ 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, idx_map(IDX_PARAM_BLOCK_INDEX)) + } pub fn record_index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_PARAM_RECORD_INDEX)) - } + ScMutableInt32::new(self.id, idx_map(IDX_PARAM_RECORD_INDEX)) + } } #[derive(Clone, Copy)] @@ -327,8 +376,8 @@ 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, idx_map(IDX_PARAM_BLOCK_INDEX)) + } } #[derive(Clone, Copy)] @@ -338,6 +387,6 @@ 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, idx_map(IDX_PARAM_BLOCK_INDEX)) + } } diff --git a/contracts/wasm/testwasmlib/src/results.rs b/contracts/wasm/testwasmlib/src/results.rs index f0f2c0adae..528943d5aa 100644 --- a/contracts/wasm/testwasmlib/src/results.rs +++ b/contracts/wasm/testwasmlib/src/results.rs @@ -13,6 +13,7 @@ use wasmlib::host::*; use crate::*; use crate::keys::*; +use crate::typedefs::*; #[derive(Clone, Copy)] pub struct ImmutableArrayLengthResults { @@ -21,8 +22,8 @@ pub struct ImmutableArrayLengthResults { impl ImmutableArrayLengthResults { pub fn length(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_LENGTH)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_LENGTH)) + } } #[derive(Clone, Copy)] @@ -32,8 +33,8 @@ pub struct MutableArrayLengthResults { impl MutableArrayLengthResults { pub fn length(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_RESULT_LENGTH)) - } + ScMutableInt32::new(self.id, idx_map(IDX_RESULT_LENGTH)) + } } #[derive(Clone, Copy)] @@ -43,8 +44,8 @@ pub struct ImmutableArrayValueResults { impl ImmutableArrayValueResults { pub fn value(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_RESULT_VALUE)) - } + ScImmutableString::new(self.id, idx_map(IDX_RESULT_VALUE)) + } } #[derive(Clone, Copy)] @@ -54,8 +55,8 @@ pub struct MutableArrayValueResults { impl MutableArrayValueResults { pub fn value(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_RESULT_VALUE)) - } + ScMutableString::new(self.id, idx_map(IDX_RESULT_VALUE)) + } } #[derive(Clone, Copy)] @@ -65,8 +66,8 @@ pub struct ImmutableBlockRecordResults { impl ImmutableBlockRecordResults { pub fn record(&self) -> ScImmutableBytes { - ScImmutableBytes::new(self.id, idx_map(IDX_RESULT_RECORD)) - } + ScImmutableBytes::new(self.id, idx_map(IDX_RESULT_RECORD)) + } } #[derive(Clone, Copy)] @@ -76,8 +77,8 @@ pub struct MutableBlockRecordResults { impl MutableBlockRecordResults { pub fn record(&self) -> ScMutableBytes { - ScMutableBytes::new(self.id, idx_map(IDX_RESULT_RECORD)) - } + ScMutableBytes::new(self.id, idx_map(IDX_RESULT_RECORD)) + } } #[derive(Clone, Copy)] @@ -87,8 +88,8 @@ pub struct ImmutableBlockRecordsResults { impl ImmutableBlockRecordsResults { pub fn count(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_COUNT)) - } + ScImmutableInt32::new(self.id, idx_map(IDX_RESULT_COUNT)) + } } #[derive(Clone, Copy)] @@ -98,8 +99,30 @@ pub struct MutableBlockRecordsResults { impl MutableBlockRecordsResults { pub fn count(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, idx_map(IDX_RESULT_COUNT)) - } + ScMutableInt32::new(self.id, idx_map(IDX_RESULT_COUNT)) + } +} + +#[derive(Clone, Copy)] +pub struct ImmutableGetRandomResults { + pub(crate) id: i32, +} + +impl ImmutableGetRandomResults { + pub fn random(&self) -> ScImmutableInt64 { + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_RANDOM)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableGetRandomResults { + pub(crate) id: i32, +} + +impl MutableGetRandomResults { + pub fn random(&self) -> ScMutableInt64 { + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_RANDOM)) + } } #[derive(Clone, Copy)] @@ -109,8 +132,8 @@ pub struct ImmutableIotaBalanceResults { impl ImmutableIotaBalanceResults { pub fn iotas(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_IOTAS)) - } + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_IOTAS)) + } } #[derive(Clone, Copy)] @@ -120,6 +143,6 @@ pub struct MutableIotaBalanceResults { impl MutableIotaBalanceResults { pub fn iotas(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, idx_map(IDX_RESULT_IOTAS)) - } + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_IOTAS)) + } } diff --git a/contracts/wasm/testwasmlib/src/state.rs b/contracts/wasm/testwasmlib/src/state.rs index aa62142b2b..e2dfc69350 100644 --- a/contracts/wasm/testwasmlib/src/state.rs +++ b/contracts/wasm/testwasmlib/src/state.rs @@ -16,7 +16,7 @@ use crate::keys::*; use crate::typedefs::*; pub struct MapStringToImmutableStringArray { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToImmutableStringArray { @@ -33,18 +33,22 @@ 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); - MapStringToImmutableStringArray { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_ARRAYS), TYPE_MAP); + MapStringToImmutableStringArray { obj_id: map_id } + } + + pub fn random(&self) -> ScImmutableInt64 { + ScImmutableInt64::new(self.id, idx_map(IDX_STATE_RANDOM)) + } } pub struct MapStringToMutableStringArray { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToMutableStringArray { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_string_array(&self, key: &str) -> MutableStringArray { @@ -60,7 +64,11 @@ pub struct MutableTestWasmLibState { impl MutableTestWasmLibState { pub fn arrays(&self) -> MapStringToMutableStringArray { - let map_id = get_object_id(self.id, idx_map(IDX_STATE_ARRAYS), TYPE_MAP); - MapStringToMutableStringArray { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_ARRAYS), TYPE_MAP); + MapStringToMutableStringArray { obj_id: map_id } + } + + pub fn random(&self) -> ScMutableInt64 { + ScMutableInt64::new(self.id, idx_map(IDX_STATE_RANDOM)) + } } diff --git a/contracts/wasm/testwasmlib/src/testwasmlib.rs b/contracts/wasm/testwasmlib/src/testwasmlib.rs index 3c40d4a018..ac32a8a541 100644 --- a/contracts/wasm/testwasmlib/src/testwasmlib.rs +++ b/contracts/wasm/testwasmlib/src/testwasmlib.rs @@ -32,6 +32,9 @@ pub fn func_param_types(ctx: &ScFuncContext, f: &ParamTypesContext) { if f.params.agent_id().exists() { ctx.require(f.params.agent_id().value() == ctx.account_id(), "mismatch: AgentID"); } + if f.params.bool().exists() { + ctx.require(f.params.bool().value(), "mismatch: Bool"); + } if f.params.bytes().exists() { let byte_data = "these are bytes".as_bytes(); ctx.require(f.params.bytes().value() == byte_data, "mismatch: Bytes"); @@ -50,14 +53,17 @@ pub fn func_param_types(ctx: &ScFuncContext, f: &ParamTypesContext) { if f.params.hname().exists() { ctx.require(f.params.hname().value() == ctx.account_id().hname(), "mismatch: Hname"); } + if f.params.int8().exists() { + ctx.require(f.params.int8().value() == -123, "mismatch: Int8"); + } if f.params.int16().exists() { - ctx.require(f.params.int16().value() == 12345, "mismatch: Int16"); + ctx.require(f.params.int16().value() == -12345, "mismatch: Int16"); } if f.params.int32().exists() { - ctx.require(f.params.int32().value() == 1234567890, "mismatch: Int32"); + ctx.require(f.params.int32().value() == -1234567890, "mismatch: Int32"); } if f.params.int64().exists() { - ctx.require(f.params.int64().value() == 1234567890123456789, "mismatch: Int64"); + ctx.require(f.params.int64().value() == -1234567890123456789, "mismatch: Int64"); } if f.params.request_id().exists() { let request_id = ScRequestID::from_bytes("abcdefghijklmnopqrstuvwxyz123456\x00\x00".as_bytes()); @@ -66,6 +72,18 @@ pub fn func_param_types(ctx: &ScFuncContext, f: &ParamTypesContext) { if f.params.string().exists() { ctx.require(f.params.string().value() == "this is a string", "mismatch: String"); } + if f.params.uint8().exists() { + ctx.require(f.params.uint8().value() == 123, "mismatch: Uint8"); + } + if f.params.uint16().exists() { + ctx.require(f.params.uint16().value() == 12345, "mismatch: Uint16"); + } + if f.params.uint32().exists() { + ctx.require(f.params.uint32().value() == 1234567890, "mismatch: Uint32"); + } + if f.params.uint64().exists() { + ctx.require(f.params.uint64().value() == 1234567890123456789, "mismatch: Uint64"); + } } pub fn view_array_length(_ctx: &ScViewContext, f: &ArrayLengthContext) { @@ -102,3 +120,11 @@ pub fn view_block_records(ctx: &ScViewContext, f: &BlockRecordsContext) { pub fn view_iota_balance(ctx: &ScViewContext, f: &IotaBalanceContext) { f.results.iotas().set_value(ctx.balances().balance(&ScColor::IOTA)); } + +pub fn func_random(ctx: &ScFuncContext, f: &RandomContext) { + f.state.random().set_value(ctx.random(1000)); +} + +pub fn view_get_random(_ctx: &ScViewContext, f: &GetRandomContext) { + f.results.random().set_value(f.state.random().value()); +} diff --git a/contracts/wasm/testwasmlib/src/typedefs.rs b/contracts/wasm/testwasmlib/src/typedefs.rs index aa1dff8c02..7c8e0d9e73 100644 --- a/contracts/wasm/testwasmlib/src/typedefs.rs +++ b/contracts/wasm/testwasmlib/src/typedefs.rs @@ -5,15 +5,13 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use wasmlib::host::*; pub struct ArrayOfImmutableString { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfImmutableString { @@ -29,7 +27,7 @@ impl ArrayOfImmutableString { pub type ImmutableStringArray = ArrayOfImmutableString; pub struct ArrayOfMutableString { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfMutableString { @@ -47,5 +45,3 @@ impl ArrayOfMutableString { } pub type MutableStringArray = ArrayOfMutableString; - -// @formatter:on diff --git a/contracts/wasm/testwasmlib/test/testwasmlib_bg.wasm b/contracts/wasm/testwasmlib/test/testwasmlib_bg.wasm index a7eb32fe2b..ddfa98208d 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_test.go b/contracts/wasm/testwasmlib/test/testwasmlib_test.go index 4082f81e8f..3cc625fccc 100644 --- a/contracts/wasm/testwasmlib/test/testwasmlib_test.go +++ b/contracts/wasm/testwasmlib/test/testwasmlib_test.go @@ -1,10 +1,12 @@ package test import ( + "fmt" "strconv" "strings" "testing" + "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/wasp/contracts/wasm/testwasmlib/go/testwasmlib" "github.com/iotaledger/wasp/packages/solo" "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" @@ -14,18 +16,24 @@ import ( var ( allParams = []string{ - string(testwasmlib.ParamAddress), - string(testwasmlib.ParamAgentID), - string(testwasmlib.ParamChainID), - string(testwasmlib.ParamColor), - string(testwasmlib.ParamHash), - string(testwasmlib.ParamHname), - string(testwasmlib.ParamInt16), - string(testwasmlib.ParamInt32), - string(testwasmlib.ParamInt64), - string(testwasmlib.ParamRequestID), + testwasmlib.ParamAddress, + testwasmlib.ParamAgentID, + testwasmlib.ParamBool, + testwasmlib.ParamChainID, + testwasmlib.ParamColor, + testwasmlib.ParamHash, + testwasmlib.ParamHname, + testwasmlib.ParamInt8, + testwasmlib.ParamInt16, + testwasmlib.ParamInt32, + testwasmlib.ParamInt64, + testwasmlib.ParamRequestID, + testwasmlib.ParamUint8, + testwasmlib.ParamUint16, + testwasmlib.ParamUint32, + testwasmlib.ParamUint64, } - allLengths = []int{33, 37, 33, 32, 32, 4, 2, 4, 8, 34} + allLengths = []int{33, 37, 1, 33, 32, 32, 4, 1, 2, 4, 8, 34, 1, 2, 4, 8} invalidValues = map[wasmlib.Key][][]byte{ testwasmlib.ParamAddress: { append([]byte{3}, zeroHash...), @@ -77,16 +85,22 @@ func testValidParams(t *testing.T) *wasmsolo.SoloContext { pt := testwasmlib.ScFuncs.ParamTypes(ctx) pt.Params.Address().SetValue(ctx.ChainID().Address()) pt.Params.AgentID().SetValue(ctx.AccountID()) + pt.Params.Bool().SetValue(true) pt.Params.Bytes().SetValue([]byte("these are bytes")) pt.Params.ChainID().SetValue(ctx.ChainID()) pt.Params.Color().SetValue(wasmlib.NewScColorFromBytes([]byte("RedGreenBlueYellowCyanBlackWhite"))) pt.Params.Hash().SetValue(wasmlib.NewScHashFromBytes([]byte("0123456789abcdeffedcba9876543210"))) pt.Params.Hname().SetValue(testwasmlib.HScName) - pt.Params.Int16().SetValue(12345) - pt.Params.Int32().SetValue(1234567890) - pt.Params.Int64().SetValue(1234567890123456789) + pt.Params.Int8().SetValue(-123) + pt.Params.Int16().SetValue(-12345) + pt.Params.Int32().SetValue(-1234567890) + pt.Params.Int64().SetValue(-1234567890123456789) pt.Params.RequestID().SetValue(wasmlib.NewScRequestIDFromBytes([]byte("abcdefghijklmnopqrstuvwxyz123456\x00\x00"))) pt.Params.String().SetValue("this is a string") + pt.Params.Uint8().SetValue(123) + pt.Params.Uint16().SetValue(12345) + pt.Params.Uint32().SetValue(1234567890) + pt.Params.Uint64().SetValue(1234567890123456789) pt.Func.TransferIotas(1).Post() require.NoError(t, ctx.Err) return ctx @@ -97,14 +111,14 @@ func TestValidSizeParams(t *testing.T) { for index, param := range allParams { t.Run("ValidSize "+param, func(t *testing.T) { pt := testwasmlib.ScFuncs.ParamTypes(ctx) - pt.Params.Param().GetBytes(param).SetValue(make([]byte, allLengths[index])) + bytes := make([]byte, allLengths[index]) + if param == testwasmlib.ParamChainID { + bytes[0] = byte(ledgerstate.AliasAddressType) + } + pt.Params.Param().GetBytes(param).SetValue(bytes) pt.Func.TransferIotas(1).Post() require.Error(t, ctx.Err) - if param == string(testwasmlib.ParamChainID) { - require.Contains(t, ctx.Err.Error(), "invalid ") - } else { - require.Contains(t, ctx.Err.Error(), "mismatch: ") - } + require.Contains(t, ctx.Err.Error(), "mismatch: ") }) } } @@ -255,3 +269,40 @@ func TestViewBalanceWithTokens(t *testing.T) { require.True(t, v.Results.Iotas().Exists()) require.EqualValues(t, 42, v.Results.Iotas().Value()) } + +func TestRandom(t *testing.T) { + ctx := setupTest(t) + + f := testwasmlib.ScFuncs.Random(ctx) + f.Func.TransferIotas(1).Post() + require.NoError(t, ctx.Err) + + v := testwasmlib.ScFuncs.GetRandom(ctx) + v.Func.Call() + require.NoError(t, ctx.Err) + random := v.Results.Random().Value() + require.True(t, random >= 0 && random < 1000) + fmt.Printf("Random value: %d\n", random) +} + +func TestMultiRandom(t *testing.T) { + ctx := setupTest(t) + + numbers := make([]int64, 0) + for i := 0; i < 10; i++ { + f := testwasmlib.ScFuncs.Random(ctx) + f.Func.TransferIotas(1).Post() + require.NoError(t, ctx.Err) + + v := testwasmlib.ScFuncs.GetRandom(ctx) + v.Func.Call() + require.NoError(t, ctx.Err) + random := v.Results.Random().Value() + require.True(t, random >= 0 && random < 1000) + numbers = append(numbers, random) + } + + for _, number := range numbers { + fmt.Printf("Random value: %d\n", number) + } +} diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/consts.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/consts.ts index 0919d7d32f..a6a3b0d49c 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/consts.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/consts.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export const ScName = "testwasmlib"; export const ScDescription = "Exercise all aspects of WasmLib"; @@ -14,6 +14,7 @@ export const HScName = new wasmlib.ScHname(0x89703a45); export const ParamAddress = "address"; export const ParamAgentID = "agentID"; export const ParamBlockIndex = "blockIndex"; +export const ParamBool = "bool"; export const ParamBytes = "bytes"; export const ParamChainID = "chainID"; export const ParamColor = "color"; @@ -23,36 +24,48 @@ export const ParamIndex = "index"; export const ParamInt16 = "int16"; export const ParamInt32 = "int32"; export const ParamInt64 = "int64"; +export const ParamInt8 = "int8"; export const ParamName = "name"; +export const ParamParam = "this"; export const ParamRecordIndex = "recordIndex"; export const ParamRequestID = "requestID"; export const ParamString = "string"; +export const ParamUint16 = "uint16"; +export const ParamUint32 = "uint32"; +export const ParamUint64 = "uint64"; +export const ParamUint8 = "uint8"; export const ParamValue = "value"; export const ResultCount = "count"; export const ResultIotas = "iotas"; export const ResultLength = "length"; +export const ResultRandom = "random"; export const ResultRecord = "record"; export const ResultValue = "value"; export const StateArrays = "arrays"; +export const StateRandom = "random"; export const FuncArrayClear = "arrayClear"; export const FuncArrayCreate = "arrayCreate"; export const FuncArraySet = "arraySet"; export const FuncParamTypes = "paramTypes"; +export const FuncRandom = "random"; 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 HFuncArrayClear = new wasmlib.ScHname(0x88021821); export const HFuncArrayCreate = new wasmlib.ScHname(0x1ed5b23b); export const HFuncArraySet = new wasmlib.ScHname(0x2c4150b3); export const HFuncParamTypes = new wasmlib.ScHname(0x6921c4cd); +export const HFuncRandom = new wasmlib.ScHname(0xe86c97ca); 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); diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/contract.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/contract.ts index 1cf201fa0a..7e24c61f0f 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/contract.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/contract.ts @@ -5,109 +5,126 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ArrayClearCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncArrayClear); - params: sc.MutableArrayClearParams = new sc.MutableArrayClearParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncArrayClear); + params: sc.MutableArrayClearParams = new sc.MutableArrayClearParams(); } export class ArrayClearContext { - params: sc.ImmutableArrayClearParams = new sc.ImmutableArrayClearParams(); - state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); + params: sc.ImmutableArrayClearParams = new sc.ImmutableArrayClearParams(); + state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); } export class ArrayCreateCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncArrayCreate); - params: sc.MutableArrayCreateParams = new sc.MutableArrayCreateParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncArrayCreate); + params: sc.MutableArrayCreateParams = new sc.MutableArrayCreateParams(); } export class ArrayCreateContext { - params: sc.ImmutableArrayCreateParams = new sc.ImmutableArrayCreateParams(); - state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); + params: sc.ImmutableArrayCreateParams = new sc.ImmutableArrayCreateParams(); + state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); } export class ArraySetCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncArraySet); - params: sc.MutableArraySetParams = new sc.MutableArraySetParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncArraySet); + params: sc.MutableArraySetParams = new sc.MutableArraySetParams(); } export class ArraySetContext { - params: sc.ImmutableArraySetParams = new sc.ImmutableArraySetParams(); - state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); + params: sc.ImmutableArraySetParams = new sc.ImmutableArraySetParams(); + 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(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncParamTypes); + params: sc.MutableParamTypesParams = new sc.MutableParamTypesParams(); } export class ParamTypesContext { - params: sc.ImmutableParamTypesParams = new sc.ImmutableParamTypesParams(); - state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); + params: sc.ImmutableParamTypesParams = new sc.ImmutableParamTypesParams(); + state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); +} + +export class RandomCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncRandom); +} + +export class RandomContext { + state: sc.MutableTestWasmLibState = new sc.MutableTestWasmLibState(); } export class ArrayLengthCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewArrayLength); - params: sc.MutableArrayLengthParams = new sc.MutableArrayLengthParams(); - results: sc.ImmutableArrayLengthResults = new sc.ImmutableArrayLengthResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewArrayLength); + params: sc.MutableArrayLengthParams = new sc.MutableArrayLengthParams(); + results: sc.ImmutableArrayLengthResults = new sc.ImmutableArrayLengthResults(); } export class ArrayLengthContext { - params: sc.ImmutableArrayLengthParams = new sc.ImmutableArrayLengthParams(); - results: sc.MutableArrayLengthResults = new sc.MutableArrayLengthResults(); - state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); + params: sc.ImmutableArrayLengthParams = new sc.ImmutableArrayLengthParams(); + results: sc.MutableArrayLengthResults = new sc.MutableArrayLengthResults(); + state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); } export class ArrayValueCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewArrayValue); - params: sc.MutableArrayValueParams = new sc.MutableArrayValueParams(); - results: sc.ImmutableArrayValueResults = new sc.ImmutableArrayValueResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewArrayValue); + params: sc.MutableArrayValueParams = new sc.MutableArrayValueParams(); + results: sc.ImmutableArrayValueResults = new sc.ImmutableArrayValueResults(); } export class ArrayValueContext { - params: sc.ImmutableArrayValueParams = new sc.ImmutableArrayValueParams(); - results: sc.MutableArrayValueResults = new sc.MutableArrayValueResults(); - state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); + params: sc.ImmutableArrayValueParams = new sc.ImmutableArrayValueParams(); + results: sc.MutableArrayValueResults = new sc.MutableArrayValueResults(); + state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); } export class BlockRecordCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewBlockRecord); - params: sc.MutableBlockRecordParams = new sc.MutableBlockRecordParams(); - results: sc.ImmutableBlockRecordResults = new sc.ImmutableBlockRecordResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewBlockRecord); + params: sc.MutableBlockRecordParams = new sc.MutableBlockRecordParams(); + results: sc.ImmutableBlockRecordResults = new sc.ImmutableBlockRecordResults(); } export class BlockRecordContext { - params: sc.ImmutableBlockRecordParams = new sc.ImmutableBlockRecordParams(); - results: sc.MutableBlockRecordResults = new sc.MutableBlockRecordResults(); - state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); + params: sc.ImmutableBlockRecordParams = new sc.ImmutableBlockRecordParams(); + results: sc.MutableBlockRecordResults = new sc.MutableBlockRecordResults(); + state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); } export class BlockRecordsCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewBlockRecords); - params: sc.MutableBlockRecordsParams = new sc.MutableBlockRecordsParams(); - results: sc.ImmutableBlockRecordsResults = new sc.ImmutableBlockRecordsResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewBlockRecords); + params: sc.MutableBlockRecordsParams = new sc.MutableBlockRecordsParams(); + results: sc.ImmutableBlockRecordsResults = new sc.ImmutableBlockRecordsResults(); } export class BlockRecordsContext { - params: sc.ImmutableBlockRecordsParams = new sc.ImmutableBlockRecordsParams(); - results: sc.MutableBlockRecordsResults = new sc.MutableBlockRecordsResults(); - state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); + params: sc.ImmutableBlockRecordsParams = new sc.ImmutableBlockRecordsParams(); + results: sc.MutableBlockRecordsResults = new sc.MutableBlockRecordsResults(); + state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); +} + +export class GetRandomCall { + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetRandom); + results: sc.ImmutableGetRandomResults = new sc.ImmutableGetRandomResults(); +} + +export class GetRandomContext { + results: sc.MutableGetRandomResults = new sc.MutableGetRandomResults(); + state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); } export class IotaBalanceCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewIotaBalance); - results: sc.ImmutableIotaBalanceResults = new sc.ImmutableIotaBalanceResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewIotaBalance); + results: sc.ImmutableIotaBalanceResults = new sc.ImmutableIotaBalanceResults(); } export class IotaBalanceContext { - results: sc.MutableIotaBalanceResults = new sc.MutableIotaBalanceResults(); - state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); + results: sc.MutableIotaBalanceResults = new sc.MutableIotaBalanceResults(); + state: sc.ImmutableTestWasmLibState = new sc.ImmutableTestWasmLibState(); } export class ScFuncs { - static arrayClear(ctx: wasmlib.ScFuncCallContext): ArrayClearCall { let f = new ArrayClearCall(); f.func.setPtrs(f.params, null); @@ -132,6 +149,10 @@ export class ScFuncs { return f; } + static random(ctx: wasmlib.ScFuncCallContext): RandomCall { + return new RandomCall(); + } + static arrayLength(ctx: wasmlib.ScViewCallContext): ArrayLengthCall { let f = new ArrayLengthCall(); f.func.setPtrs(f.params, f.results); @@ -156,6 +177,12 @@ export class ScFuncs { return f; } + static getRandom(ctx: wasmlib.ScViewCallContext): GetRandomCall { + let f = new GetRandomCall(); + f.func.setPtrs(null, f.results); + return f; + } + static iotaBalance(ctx: wasmlib.ScViewCallContext): IotaBalanceCall { let f = new IotaBalanceCall(); f.func.setPtrs(null, f.results); diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/keys.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/keys.ts index d530270667..a67473b453 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/keys.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/keys.ts @@ -5,57 +5,77 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export const IdxParamAddress = 0; export const IdxParamAgentID = 1; export const IdxParamBlockIndex = 2; -export const IdxParamBytes = 3; -export const IdxParamChainID = 4; -export const IdxParamColor = 5; -export const IdxParamHash = 6; -export const IdxParamHname = 7; -export const IdxParamIndex = 8; -export const IdxParamInt16 = 9; -export const IdxParamInt32 = 10; -export const IdxParamInt64 = 11; -export const IdxParamName = 12; -export const IdxParamRecordIndex = 13; -export const IdxParamRequestID = 14; -export const IdxParamString = 15; -export const IdxParamValue = 16; -export const IdxResultCount = 17; -export const IdxResultIotas = 18; -export const IdxResultLength = 19; -export const IdxResultRecord = 20; -export const IdxResultValue = 21; -export const IdxStateArrays = 22; +export const IdxParamBool = 3; +export const IdxParamBytes = 4; +export const IdxParamChainID = 5; +export const IdxParamColor = 6; +export const IdxParamHash = 7; +export const IdxParamHname = 8; +export const IdxParamIndex = 9; +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 IdxResultCount = 24; +export const IdxResultIotas = 25; +export const IdxResultLength = 26; +export const IdxResultRandom = 27; +export const IdxResultRecord = 28; +export const IdxResultValue = 29; + +export const IdxStateArrays = 30; +export const IdxStateRandom = 31; export let keyMap: string[] = [ - sc.ParamAddress, - sc.ParamAgentID, - sc.ParamBlockIndex, - sc.ParamBytes, - sc.ParamChainID, - sc.ParamColor, - sc.ParamHash, - sc.ParamHname, - sc.ParamIndex, - sc.ParamInt16, - sc.ParamInt32, - sc.ParamInt64, - sc.ParamName, - sc.ParamRecordIndex, - sc.ParamRequestID, - sc.ParamString, - sc.ParamValue, - sc.ResultCount, - sc.ResultIotas, - sc.ResultLength, - sc.ResultRecord, - sc.ResultValue, - sc.StateArrays, + sc.ParamAddress, + sc.ParamAgentID, + sc.ParamBlockIndex, + sc.ParamBool, + sc.ParamBytes, + sc.ParamChainID, + sc.ParamColor, + sc.ParamHash, + sc.ParamHname, + sc.ParamIndex, + sc.ParamInt16, + sc.ParamInt32, + sc.ParamInt64, + sc.ParamInt8, + sc.ParamName, + sc.ParamParam, + sc.ParamRecordIndex, + sc.ParamRequestID, + sc.ParamString, + sc.ParamUint16, + sc.ParamUint32, + sc.ParamUint64, + sc.ParamUint8, + sc.ParamValue, + sc.ResultCount, + sc.ResultIotas, + sc.ResultLength, + sc.ResultRandom, + sc.ResultRecord, + sc.ResultValue, + sc.StateArrays, + sc.StateRandom, ]; export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/lib.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/lib.ts index 64720fe3b6..6517abda64 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/lib.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/lib.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export function on_call(index: i32): void { @@ -14,15 +14,17 @@ export function on_call(index: i32): void { export function on_load(): void { let exports = new wasmlib.ScExports(); - exports.addFunc(sc.FuncArrayClear, funcArrayClearThunk); - exports.addFunc(sc.FuncArrayCreate, funcArrayCreateThunk); - exports.addFunc(sc.FuncArraySet, funcArraySetThunk); - exports.addFunc(sc.FuncParamTypes, funcParamTypesThunk); - exports.addView(sc.ViewArrayLength, viewArrayLengthThunk); - exports.addView(sc.ViewArrayValue, viewArrayValueThunk); - exports.addView(sc.ViewBlockRecord, viewBlockRecordThunk); + exports.addFunc(sc.FuncArrayClear, funcArrayClearThunk); + exports.addFunc(sc.FuncArrayCreate, funcArrayCreateThunk); + exports.addFunc(sc.FuncArraySet, funcArraySetThunk); + exports.addFunc(sc.FuncParamTypes, funcParamTypesThunk); + exports.addFunc(sc.FuncRandom, funcRandomThunk); + exports.addView(sc.ViewArrayLength, viewArrayLengthThunk); + exports.addView(sc.ViewArrayValue, viewArrayValueThunk); + exports.addView(sc.ViewBlockRecord, viewBlockRecordThunk); exports.addView(sc.ViewBlockRecords, viewBlockRecordsThunk); - exports.addView(sc.ViewIotaBalance, viewIotaBalanceThunk); + exports.addView(sc.ViewGetRandom, viewGetRandomThunk); + exports.addView(sc.ViewIotaBalance, viewIotaBalanceThunk); for (let i = 0; i < sc.keyMap.length; i++) { sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); @@ -30,97 +32,114 @@ export function on_load(): void { } function funcArrayClearThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testwasmlib.funcArrayClear"); - let f = new sc.ArrayClearContext(); + ctx.log("testwasmlib.funcArrayClear"); + let f = new sc.ArrayClearContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.name().exists(), "missing mandatory name") - sc.funcArrayClear(ctx, f); - ctx.log("testwasmlib.funcArrayClear ok"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + sc.funcArrayClear(ctx, f); + ctx.log("testwasmlib.funcArrayClear ok"); } function funcArrayCreateThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testwasmlib.funcArrayCreate"); - let f = new sc.ArrayCreateContext(); + ctx.log("testwasmlib.funcArrayCreate"); + let f = new sc.ArrayCreateContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.name().exists(), "missing mandatory name") - sc.funcArrayCreate(ctx, f); - ctx.log("testwasmlib.funcArrayCreate ok"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + sc.funcArrayCreate(ctx, f); + ctx.log("testwasmlib.funcArrayCreate ok"); } function funcArraySetThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testwasmlib.funcArraySet"); - let f = new sc.ArraySetContext(); + ctx.log("testwasmlib.funcArraySet"); + let f = new sc.ArraySetContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.index().exists(), "missing mandatory index") - ctx.require(f.params.name().exists(), "missing mandatory name") - ctx.require(f.params.value().exists(), "missing mandatory value") - sc.funcArraySet(ctx, f); - ctx.log("testwasmlib.funcArraySet ok"); + ctx.require(f.params.index().exists(), "missing mandatory index"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + ctx.require(f.params.value().exists(), "missing mandatory value"); + sc.funcArraySet(ctx, f); + ctx.log("testwasmlib.funcArraySet ok"); } function funcParamTypesThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("testwasmlib.funcParamTypes"); - let f = new sc.ParamTypesContext(); + ctx.log("testwasmlib.funcParamTypes"); + let f = new sc.ParamTypesContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcParamTypes(ctx, f); - ctx.log("testwasmlib.funcParamTypes ok"); + sc.funcParamTypes(ctx, f); + ctx.log("testwasmlib.funcParamTypes ok"); +} + +function funcRandomThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("testwasmlib.funcRandom"); + let f = new sc.RandomContext(); + f.state.mapID = wasmlib.OBJ_ID_STATE; + sc.funcRandom(ctx, f); + ctx.log("testwasmlib.funcRandom ok"); } function viewArrayLengthThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testwasmlib.viewArrayLength"); - let f = new sc.ArrayLengthContext(); + ctx.log("testwasmlib.viewArrayLength"); + let f = new sc.ArrayLengthContext(); 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.name().exists(), "missing mandatory name") - sc.viewArrayLength(ctx, f); - ctx.log("testwasmlib.viewArrayLength ok"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + sc.viewArrayLength(ctx, f); + ctx.log("testwasmlib.viewArrayLength ok"); } function viewArrayValueThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testwasmlib.viewArrayValue"); - let f = new sc.ArrayValueContext(); + ctx.log("testwasmlib.viewArrayValue"); + let f = new sc.ArrayValueContext(); 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.index().exists(), "missing mandatory index") - ctx.require(f.params.name().exists(), "missing mandatory name") - sc.viewArrayValue(ctx, f); - ctx.log("testwasmlib.viewArrayValue ok"); + ctx.require(f.params.index().exists(), "missing mandatory index"); + ctx.require(f.params.name().exists(), "missing mandatory name"); + sc.viewArrayValue(ctx, f); + ctx.log("testwasmlib.viewArrayValue ok"); } function viewBlockRecordThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testwasmlib.viewBlockRecord"); - let f = new sc.BlockRecordContext(); + ctx.log("testwasmlib.viewBlockRecord"); + let f = new sc.BlockRecordContext(); 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.blockIndex().exists(), "missing mandatory blockIndex") - ctx.require(f.params.recordIndex().exists(), "missing mandatory recordIndex") - sc.viewBlockRecord(ctx, f); - ctx.log("testwasmlib.viewBlockRecord ok"); + ctx.require(f.params.blockIndex().exists(), "missing mandatory blockIndex"); + ctx.require(f.params.recordIndex().exists(), "missing mandatory recordIndex"); + sc.viewBlockRecord(ctx, f); + ctx.log("testwasmlib.viewBlockRecord ok"); } function viewBlockRecordsThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testwasmlib.viewBlockRecords"); - let f = new sc.BlockRecordsContext(); + ctx.log("testwasmlib.viewBlockRecords"); + let f = new sc.BlockRecordsContext(); 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.blockIndex().exists(), "missing mandatory blockIndex") - sc.viewBlockRecords(ctx, f); - ctx.log("testwasmlib.viewBlockRecords ok"); + ctx.require(f.params.blockIndex().exists(), "missing mandatory blockIndex"); + sc.viewBlockRecords(ctx, f); + ctx.log("testwasmlib.viewBlockRecords ok"); +} + +function viewGetRandomThunk(ctx: wasmlib.ScViewContext): void { + ctx.log("testwasmlib.viewGetRandom"); + let f = new sc.GetRandomContext(); + f.results.mapID = wasmlib.OBJ_ID_RESULTS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + sc.viewGetRandom(ctx, f); + ctx.log("testwasmlib.viewGetRandom ok"); } function viewIotaBalanceThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("testwasmlib.viewIotaBalance"); - let f = new sc.IotaBalanceContext(); + ctx.log("testwasmlib.viewIotaBalance"); + let f = new sc.IotaBalanceContext(); f.results.mapID = wasmlib.OBJ_ID_RESULTS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.viewIotaBalance(ctx, f); - ctx.log("testwasmlib.viewIotaBalance ok"); + sc.viewIotaBalance(ctx, f); + ctx.log("testwasmlib.viewIotaBalance ok"); } diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/params.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/params.ts index f70524c36c..b4865a4e4e 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/params.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/params.ts @@ -5,273 +5,305 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamIndex]); + } name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + } value(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamValue]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamValue]); + } } 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, sc.idxMap[sc.IdxParamIndex]); + } name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + } value(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamValue]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamValue]); + } } export class MapStringToImmutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } getBytes(key: string): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.objID, wasmlib.Key32.fromString(key).getKeyID()); + return new wasmlib.ScImmutableBytes(this.objID, wasmlib.Key32.fromString(key)); } } 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, sc.idxMap[sc.IdxParamAddress]); + } agentID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); - } + return new wasmlib.ScImmutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + } + + bool(): wasmlib.ScImmutableBool { + return new wasmlib.ScImmutableBool(this.mapID, sc.idxMap[sc.IdxParamBool]); + } bytes(): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.mapID, sc.idxMap[sc.IdxParamBytes]); - } + return new wasmlib.ScImmutableBytes(this.mapID, sc.idxMap[sc.IdxParamBytes]); + } chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); - } + return new wasmlib.ScImmutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + } color(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); - } + return new wasmlib.ScImmutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + } hash(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); - } + return new wasmlib.ScImmutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + } hname(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); - } + return new wasmlib.ScImmutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + } int16(): wasmlib.ScImmutableInt16 { - return new wasmlib.ScImmutableInt16(this.mapID, sc.idxMap[sc.IdxParamInt16]); - } + return new wasmlib.ScImmutableInt16(this.mapID, sc.idxMap[sc.IdxParamInt16]); + } int32(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamInt32]); - } + return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamInt32]); + } int64(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); - } + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + } + + int8(): wasmlib.ScImmutableInt8 { + return new wasmlib.ScImmutableInt8(this.mapID, sc.idxMap[sc.IdxParamInt8]); + } param(): sc.MapStringToImmutableBytes { - return new sc.MapStringToImmutableBytes(this.mapID); - } + return new sc.MapStringToImmutableBytes(this.mapID); + } requestID(): wasmlib.ScImmutableRequestID { - return new wasmlib.ScImmutableRequestID(this.mapID, sc.idxMap[sc.IdxParamRequestID]); - } + return new wasmlib.ScImmutableRequestID(this.mapID, sc.idxMap[sc.IdxParamRequestID]); + } string(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamString]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + } + + uint16(): wasmlib.ScImmutableUint16 { + return new wasmlib.ScImmutableUint16(this.mapID, sc.idxMap[sc.IdxParamUint16]); + } + + uint32(): wasmlib.ScImmutableUint32 { + return new wasmlib.ScImmutableUint32(this.mapID, sc.idxMap[sc.IdxParamUint32]); + } + + uint64(): wasmlib.ScImmutableUint64 { + return new wasmlib.ScImmutableUint64(this.mapID, sc.idxMap[sc.IdxParamUint64]); + } + + uint8(): wasmlib.ScImmutableUint8 { + return new wasmlib.ScImmutableUint8(this.mapID, sc.idxMap[sc.IdxParamUint8]); + } } export class MapStringToMutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getBytes(key: string): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.objID, wasmlib.Key32.fromString(key).getKeyID()); + return new wasmlib.ScMutableBytes(this.objID, wasmlib.Key32.fromString(key)); } } 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, sc.idxMap[sc.IdxParamAddress]); + } agentID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); - } + return new wasmlib.ScMutableAgentID(this.mapID, sc.idxMap[sc.IdxParamAgentID]); + } + + bool(): wasmlib.ScMutableBool { + return new wasmlib.ScMutableBool(this.mapID, sc.idxMap[sc.IdxParamBool]); + } bytes(): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.mapID, sc.idxMap[sc.IdxParamBytes]); - } + return new wasmlib.ScMutableBytes(this.mapID, sc.idxMap[sc.IdxParamBytes]); + } chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); - } + return new wasmlib.ScMutableChainID(this.mapID, sc.idxMap[sc.IdxParamChainID]); + } color(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); - } + return new wasmlib.ScMutableColor(this.mapID, sc.idxMap[sc.IdxParamColor]); + } hash(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); - } + return new wasmlib.ScMutableHash(this.mapID, sc.idxMap[sc.IdxParamHash]); + } hname(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); - } + return new wasmlib.ScMutableHname(this.mapID, sc.idxMap[sc.IdxParamHname]); + } int16(): wasmlib.ScMutableInt16 { - return new wasmlib.ScMutableInt16(this.mapID, sc.idxMap[sc.IdxParamInt16]); - } + return new wasmlib.ScMutableInt16(this.mapID, sc.idxMap[sc.IdxParamInt16]); + } int32(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamInt32]); - } + return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamInt32]); + } int64(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); - } + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxParamInt64]); + } + + int8(): wasmlib.ScMutableInt8 { + return new wasmlib.ScMutableInt8(this.mapID, sc.idxMap[sc.IdxParamInt8]); + } param(): sc.MapStringToMutableBytes { - return new sc.MapStringToMutableBytes(this.mapID); - } + return new sc.MapStringToMutableBytes(this.mapID); + } requestID(): wasmlib.ScMutableRequestID { - return new wasmlib.ScMutableRequestID(this.mapID, sc.idxMap[sc.IdxParamRequestID]); - } + return new wasmlib.ScMutableRequestID(this.mapID, sc.idxMap[sc.IdxParamRequestID]); + } string(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamString]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamString]); + } + + uint16(): wasmlib.ScMutableUint16 { + return new wasmlib.ScMutableUint16(this.mapID, sc.idxMap[sc.IdxParamUint16]); + } + + uint32(): wasmlib.ScMutableUint32 { + return new wasmlib.ScMutableUint32(this.mapID, sc.idxMap[sc.IdxParamUint32]); + } + + uint64(): wasmlib.ScMutableUint64 { + return new wasmlib.ScMutableUint64(this.mapID, sc.idxMap[sc.IdxParamUint64]); + } + + uint8(): wasmlib.ScMutableUint8 { + return new wasmlib.ScMutableUint8(this.mapID, sc.idxMap[sc.IdxParamUint8]); + } } 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, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamIndex]); + } name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamIndex]); + } name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamName]); + } } 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, sc.idxMap[sc.IdxParamBlockIndex]); + } recordIndex(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamRecordIndex]); - } + return new wasmlib.ScImmutableInt32(this.mapID, sc.idxMap[sc.IdxParamRecordIndex]); + } } 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, sc.idxMap[sc.IdxParamBlockIndex]); + } recordIndex(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamRecordIndex]); - } + return new wasmlib.ScMutableInt32(this.mapID, sc.idxMap[sc.IdxParamRecordIndex]); + } } 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, sc.idxMap[sc.IdxParamBlockIndex]); + } } 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, sc.idxMap[sc.IdxParamBlockIndex]); + } } diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/results.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/results.ts index a4427f0b3b..5c4de29bc1 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/results.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/results.ts @@ -5,75 +5,77 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxResultLength]); + } } 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, sc.idxMap[sc.IdxResultLength]); + } } 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, sc.idxMap[sc.IdxResultValue]); + } } 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, sc.idxMap[sc.IdxResultValue]); + } } 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, sc.idxMap[sc.IdxResultRecord]); + } } 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, sc.idxMap[sc.IdxResultRecord]); + } } 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, sc.idxMap[sc.IdxResultCount]); + } } 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, sc.idxMap[sc.IdxResultCount]); + } } -export class ImmutableIotaBalanceResults extends wasmlib.ScMapID { +export class ImmutableGetRandomResults extends wasmlib.ScMapID { + random(): wasmlib.ScImmutableInt64 { + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultRandom]); + } +} +export class MutableGetRandomResults extends wasmlib.ScMapID { + random(): wasmlib.ScMutableInt64 { + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultRandom]); + } +} + +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, sc.idxMap[sc.IdxResultIotas]); + } } 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, sc.idxMap[sc.IdxResultIotas]); + } } diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/state.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/state.ts index 5f63655ae7..a823238696 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/state.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/state.ts @@ -5,51 +5,57 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class MapStringToImmutableStringArray { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } getStringArray(key: string): sc.ImmutableStringArray { - let subID = wasmlib.getObjectID(this.objID, wasmlib.Key32.fromString(key).getKeyID(), wasmlib.TYPE_ARRAY|wasmlib.TYPE_STRING); + let subID = wasmlib.getObjectID(this.objID, wasmlib.Key32.fromString(key), wasmlib.TYPE_ARRAY|wasmlib.TYPE_STRING); return new sc.ImmutableStringArray(subID); } } export class ImmutableTestWasmLibState extends wasmlib.ScMapID { - arrays(): sc.MapStringToImmutableStringArray { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateArrays], wasmlib.TYPE_MAP); - return new sc.MapStringToImmutableStringArray(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateArrays], wasmlib.TYPE_MAP); + return new sc.MapStringToImmutableStringArray(mapID); + } + + random(): wasmlib.ScImmutableInt64 { + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateRandom]); + } } export class MapStringToMutableStringArray { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getStringArray(key: string): sc.MutableStringArray { - let subID = wasmlib.getObjectID(this.objID, wasmlib.Key32.fromString(key).getKeyID(), wasmlib.TYPE_ARRAY|wasmlib.TYPE_STRING); + let subID = wasmlib.getObjectID(this.objID, wasmlib.Key32.fromString(key), wasmlib.TYPE_ARRAY|wasmlib.TYPE_STRING); return new sc.MutableStringArray(subID); } } export class MutableTestWasmLibState extends wasmlib.ScMapID { - arrays(): sc.MapStringToMutableStringArray { - let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateArrays], wasmlib.TYPE_MAP); - return new sc.MapStringToMutableStringArray(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateArrays], wasmlib.TYPE_MAP); + return new sc.MapStringToMutableStringArray(mapID); + } + + random(): wasmlib.ScMutableInt64 { + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateRandom]); + } } diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/testwasmlib.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/testwasmlib.ts index 79592fd43b..1bfc31f7bd 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/testwasmlib.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/testwasmlib.ts @@ -32,6 +32,9 @@ export function funcParamTypes(ctx: wasmlib.ScFuncContext, f: sc.ParamTypesConte if (f.params.agentID().exists()) { ctx.require(f.params.agentID().value().equals(ctx.accountID()), "mismatch: AgentID"); } + if (f.params.bool().exists()) { + ctx.require(f.params.bool().value(), "mismatch: Bool"); + } if (f.params.bytes().exists()) { let byteData = wasmlib.Convert.fromString("these are bytes"); ctx.require(wasmlib.Convert.equals(f.params.bytes().value(), byteData), "mismatch: Bytes"); @@ -50,14 +53,17 @@ export function funcParamTypes(ctx: wasmlib.ScFuncContext, f: sc.ParamTypesConte if (f.params.hname().exists()) { ctx.require(f.params.hname().value().equals(ctx.accountID().hname()), "mismatch: Hname"); } + if (f.params.int8().exists()) { + ctx.require(f.params.int8().value() == -123, "mismatch: Int8"); + } if (f.params.int16().exists()) { - ctx.require(f.params.int16().value() == 12345, "mismatch: Int16"); + ctx.require(f.params.int16().value() == -12345, "mismatch: Int16"); } if (f.params.int32().exists()) { - ctx.require(f.params.int32().value() == 1234567890, "mismatch: Int32"); + ctx.require(f.params.int32().value() == -1234567890, "mismatch: Int32"); } if (f.params.int64().exists()) { - ctx.require(f.params.int64().value() == 1234567890123456789, "mismatch: Int64"); + ctx.require(f.params.int64().value() == -1234567890123456789, "mismatch: Int64"); } if (f.params.requestID().exists()) { let requestId = wasmlib.ScRequestID.fromBytes(wasmlib.Convert.fromString("abcdefghijklmnopqrstuvwxyz123456\x00\x00")); @@ -66,6 +72,18 @@ export function funcParamTypes(ctx: wasmlib.ScFuncContext, f: sc.ParamTypesConte if (f.params.string().exists()) { ctx.require(f.params.string().value() == "this is a string", "mismatch: String"); } + if (f.params.uint8().exists()) { + ctx.require(f.params.uint8().value() == 123, "mismatch: Uint8"); + } + if (f.params.uint16().exists()) { + ctx.require(f.params.uint16().value() == 12345, "mismatch: Uint16"); + } + if (f.params.uint32().exists()) { + ctx.require(f.params.uint32().value() == 1234567890, "mismatch: Uint32"); + } + if (f.params.uint64().exists()) { + ctx.require(f.params.uint64().value() == 1234567890123456789, "mismatch: Uint64"); + } } export function viewArrayLength(ctx: wasmlib.ScViewContext, f: sc.ArrayLengthContext): void { @@ -102,3 +120,11 @@ export function viewBlockRecords(ctx: wasmlib.ScViewContext, f: sc.BlockRecordsC export function viewIotaBalance(ctx: wasmlib.ScViewContext, f: sc.IotaBalanceContext): void { f.results.iotas().setValue(ctx.balances().balance(wasmlib.ScColor.IOTA)); } + +export function funcRandom(ctx: wasmlib.ScFuncContext, f: sc.RandomContext): void { + f.state.random().setValue(ctx.random(1000)); +} + +export function viewGetRandom(ctx: wasmlib.ScViewContext, f: sc.GetRandomContext): void { + f.results.random().setValue(f.state.random().value()); +} diff --git a/contracts/wasm/testwasmlib/ts/testwasmlib/typedefs.ts b/contracts/wasm/testwasmlib/ts/testwasmlib/typedefs.ts index 872ea82c21..aab311ce94 100644 --- a/contracts/wasm/testwasmlib/ts/testwasmlib/typedefs.ts +++ b/contracts/wasm/testwasmlib/ts/testwasmlib/typedefs.ts @@ -5,11 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ArrayOfImmutableString { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -28,7 +28,7 @@ export class ImmutableStringArray extends ArrayOfImmutableString { }; export class ArrayOfMutableString { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; diff --git a/contracts/wasm/timestamp/Cargo.toml b/contracts/wasm/timestamp/Cargo.toml new file mode 100644 index 0000000000..1484bd0a63 --- /dev/null +++ b/contracts/wasm/timestamp/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "timestamp" +description = "Extremely simple timestamp server" +license = "Apache-2.0" +version = "0.1.0" +authors = ["John Doe "] +edition = "2018" +repository = "https://github.com/iotaledger/wasp" + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +default = ["console_error_panic_hook"] + +[dependencies] +wasmlib = { path = "../../../packages/vm/wasmlib" } +#wasmlib = { git = "https://github.com/iotaledger/wasp", branch = "develop" } +console_error_panic_hook = { version = "0.1.6", optional = true } +wee_alloc = { version = "0.4.5", optional = true } + +[dev-dependencies] +wasm-bindgen-test = "0.3.13" diff --git a/contracts/wasm/timestamp/LICENSE b/contracts/wasm/timestamp/LICENSE new file mode 100644 index 0000000000..d22c90e122 --- /dev/null +++ b/contracts/wasm/timestamp/LICENSE @@ -0,0 +1,216 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2019 IOTA Foundation + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +For the errors package: + +Copyright (c) 2015, Dave Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/contracts/wasm/timestamp/README.md b/contracts/wasm/timestamp/README.md new file mode 100644 index 0000000000..5f93881307 --- /dev/null +++ b/contracts/wasm/timestamp/README.md @@ -0,0 +1,5 @@ +## timestamp + +Sample smart contract + + Extremely simple timestamp server. diff --git a/contracts/wasm/timestamp/go/main.go b/contracts/wasm/timestamp/go/main.go new file mode 100644 index 0000000000..24e856e140 --- /dev/null +++ b/contracts/wasm/timestamp/go/main.go @@ -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 + +// +build wasm + +package main + +import "github.com/iotaledger/wasp/packages/vm/wasmclient" + +import "github.com/iotaledger/wasp/contracts/wasm/timestamp/go/timestamp" + +func main() { +} + +//export on_load +func onLoad() { + h := &wasmclient.WasmVMHost{} + h.ConnectWasmHost() + timestamp.OnLoad() +} diff --git a/contracts/wasm/timestamp/go/timestamp/consts.go b/contracts/wasm/timestamp/go/timestamp/consts.go new file mode 100644 index 0000000000..7e2f5135f8 --- /dev/null +++ b/contracts/wasm/timestamp/go/timestamp/consts.go @@ -0,0 +1,34 @@ +// 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 timestamp + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +const ( + ScName = "timestamp" + ScDescription = "Extremely simple timestamp server" + HScName = wasmlib.ScHname(0x3988002e) +) + +const ( + ResultTimestamp = "timestamp" +) + +const ( + StateTimestamp = "timestamp" +) + +const ( + FuncNow = "now" + ViewGetTimestamp = "getTimestamp" +) + +const ( + HFuncNow = wasmlib.ScHname(0xd73b7fc9) + HViewGetTimestamp = wasmlib.ScHname(0x40c6376a) +) diff --git a/contracts/wasm/timestamp/go/timestamp/contract.go b/contracts/wasm/timestamp/go/timestamp/contract.go new file mode 100644 index 0000000000..e58a562fbd --- /dev/null +++ b/contracts/wasm/timestamp/go/timestamp/contract.go @@ -0,0 +1,33 @@ +// 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 timestamp + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type NowCall struct { + Func *wasmlib.ScFunc +} + +type GetTimestampCall struct { + Func *wasmlib.ScView + Results ImmutableGetTimestampResults +} + +type Funcs struct{} + +var ScFuncs Funcs + +func (sc Funcs) Now(ctx wasmlib.ScFuncCallContext) *NowCall { + return &NowCall{Func: wasmlib.NewScFunc(ctx, HScName, HFuncNow)} +} + +func (sc Funcs) GetTimestamp(ctx wasmlib.ScViewCallContext) *GetTimestampCall { + f := &GetTimestampCall{Func: wasmlib.NewScView(ctx, HScName, HViewGetTimestamp)} + f.Func.SetPtrs(nil, &f.Results.id) + return f +} diff --git a/contracts/wasm/timestamp/go/timestamp/keys.go b/contracts/wasm/timestamp/go/timestamp/keys.go new file mode 100644 index 0000000000..9b658897b1 --- /dev/null +++ b/contracts/wasm/timestamp/go/timestamp/keys.go @@ -0,0 +1,25 @@ +// 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 timestamp + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +const ( + IdxResultTimestamp = 0 + + IdxStateTimestamp = 1 +) + +const keyMapLen = 2 + +var keyMap = [keyMapLen]wasmlib.Key{ + ResultTimestamp, + StateTimestamp, +} + +var idxMap [keyMapLen]wasmlib.Key32 diff --git a/contracts/wasm/timestamp/go/timestamp/lib.go b/contracts/wasm/timestamp/go/timestamp/lib.go new file mode 100644 index 0000000000..bc42403aa1 --- /dev/null +++ b/contracts/wasm/timestamp/go/timestamp/lib.go @@ -0,0 +1,54 @@ +// 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 timestamp + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +func OnLoad() { + exports := wasmlib.NewScExports() + exports.AddFunc(FuncNow, funcNowThunk) + exports.AddView(ViewGetTimestamp, viewGetTimestampThunk) + + for i, key := range keyMap { + idxMap[i] = key.KeyID() + } +} + +type NowContext struct { + State MutabletimestampState +} + +func funcNowThunk(ctx wasmlib.ScFuncContext) { + ctx.Log("timestamp.funcNow") + f := &NowContext{ + State: MutabletimestampState{ + id: wasmlib.OBJ_ID_STATE, + }, + } + funcNow(ctx, f) + ctx.Log("timestamp.funcNow ok") +} + +type GetTimestampContext struct { + Results MutableGetTimestampResults + State ImmutabletimestampState +} + +func viewGetTimestampThunk(ctx wasmlib.ScViewContext) { + ctx.Log("timestamp.viewGetTimestamp") + f := &GetTimestampContext{ + Results: MutableGetTimestampResults{ + id: wasmlib.OBJ_ID_RESULTS, + }, + State: ImmutabletimestampState{ + id: wasmlib.OBJ_ID_STATE, + }, + } + viewGetTimestamp(ctx, f) + ctx.Log("timestamp.viewGetTimestamp ok") +} diff --git a/contracts/wasm/timestamp/go/timestamp/results.go b/contracts/wasm/timestamp/go/timestamp/results.go new file mode 100644 index 0000000000..cb8989f123 --- /dev/null +++ b/contracts/wasm/timestamp/go/timestamp/results.go @@ -0,0 +1,26 @@ +// 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 timestamp + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type ImmutableGetTimestampResults struct { + id int32 +} + +func (s ImmutableGetTimestampResults) Timestamp() wasmlib.ScImmutableInt64 { + return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxResultTimestamp]) +} + +type MutableGetTimestampResults struct { + id int32 +} + +func (s MutableGetTimestampResults) Timestamp() wasmlib.ScMutableInt64 { + return wasmlib.NewScMutableInt64(s.id, idxMap[IdxResultTimestamp]) +} diff --git a/contracts/wasm/timestamp/go/timestamp/state.go b/contracts/wasm/timestamp/go/timestamp/state.go new file mode 100644 index 0000000000..d57540232e --- /dev/null +++ b/contracts/wasm/timestamp/go/timestamp/state.go @@ -0,0 +1,26 @@ +// 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 timestamp + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type ImmutabletimestampState struct { + id int32 +} + +func (s ImmutabletimestampState) Timestamp() wasmlib.ScImmutableInt64 { + return wasmlib.NewScImmutableInt64(s.id, idxMap[IdxStateTimestamp]) +} + +type MutabletimestampState struct { + id int32 +} + +func (s MutabletimestampState) Timestamp() wasmlib.ScMutableInt64 { + return wasmlib.NewScMutableInt64(s.id, idxMap[IdxStateTimestamp]) +} diff --git a/contracts/wasm/timestamp/go/timestamp/timestamp.go b/contracts/wasm/timestamp/go/timestamp/timestamp.go new file mode 100644 index 0000000000..f8af6b9764 --- /dev/null +++ b/contracts/wasm/timestamp/go/timestamp/timestamp.go @@ -0,0 +1,14 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package timestamp + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +func funcNow(ctx wasmlib.ScFuncContext, f *NowContext) { + f.State.Timestamp().SetValue(ctx.Timestamp()) +} + +func viewGetTimestamp(ctx wasmlib.ScViewContext, f *GetTimestampContext) { + f.Results.Timestamp().SetValue(f.State.Timestamp().Value()) +} diff --git a/contracts/wasm/timestamp/schema.yaml b/contracts/wasm/timestamp/schema.yaml new file mode 100644 index 0000000000..aaad197bea --- /dev/null +++ b/contracts/wasm/timestamp/schema.yaml @@ -0,0 +1,12 @@ +name: timestamp +description: Extremely simple timestamp server +structs: {} +typedefs: {} +state: + timestamp: Int64 // last official timestamp generated +funcs: + now: +views: + getTimestamp: + results: + timestamp: Int64 // last official timestamp generated diff --git a/contracts/wasm/timestamp/src/consts.rs b/contracts/wasm/timestamp/src/consts.rs new file mode 100644 index 0000000000..31a77b2afd --- /dev/null +++ b/contracts/wasm/timestamp/src/consts.rs @@ -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 + +#![allow(dead_code)] + +use wasmlib::*; + +pub const SC_NAME : &str = "timestamp"; +pub const SC_DESCRIPTION : &str = "Extremely simple timestamp server"; +pub const HSC_NAME : ScHname = ScHname(0x3988002e); + +pub const RESULT_TIMESTAMP : &str = "timestamp"; + +pub const STATE_TIMESTAMP : &str = "timestamp"; + +pub const FUNC_NOW : &str = "now"; +pub const VIEW_GET_TIMESTAMP : &str = "getTimestamp"; + +pub const HFUNC_NOW : ScHname = ScHname(0xd73b7fc9); +pub const HVIEW_GET_TIMESTAMP : ScHname = ScHname(0x40c6376a); diff --git a/contracts/wasm/timestamp/src/contract.rs b/contracts/wasm/timestamp/src/contract.rs new file mode 100644 index 0000000000..91ec41f186 --- /dev/null +++ b/contracts/wasm/timestamp/src/contract.rs @@ -0,0 +1,44 @@ +// 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 std::ptr; + +use wasmlib::*; + +use crate::consts::*; +use crate::results::*; + +pub struct NowCall { + pub func: ScFunc, +} + +pub struct GetTimestampCall { + pub func: ScView, + pub results: ImmutableGetTimestampResults, +} + +pub struct ScFuncs { +} + +impl ScFuncs { + pub fn now(_ctx: & dyn ScFuncCallContext) -> NowCall { + NowCall { + func: ScFunc::new(HSC_NAME, HFUNC_NOW), + } + } + + pub fn get_timestamp(_ctx: & dyn ScViewCallContext) -> GetTimestampCall { + let mut f = GetTimestampCall { + func: ScView::new(HSC_NAME, HVIEW_GET_TIMESTAMP), + results: ImmutableGetTimestampResults { id: 0 }, + }; + f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); + f + } +} diff --git a/contracts/wasm/timestamp/src/keys.rs b/contracts/wasm/timestamp/src/keys.rs new file mode 100644 index 0000000000..52cdcdbbb8 --- /dev/null +++ b/contracts/wasm/timestamp/src/keys.rs @@ -0,0 +1,32 @@ +// 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::*; + +use crate::*; + + +pub(crate) const IDX_RESULT_TIMESTAMP : usize = 0; + +pub(crate) const IDX_STATE_TIMESTAMP : usize = 1; + +pub const KEY_MAP_LEN: usize = 2; + +pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ + RESULT_TIMESTAMP, + STATE_TIMESTAMP, +]; + +pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; + +pub fn idx_map(idx: usize) -> Key32 { + unsafe { + IDX_MAP[idx] + } +} diff --git a/contracts/wasm/timestamp/src/lib.rs b/contracts/wasm/timestamp/src/lib.rs new file mode 100644 index 0000000000..e50f6ade0a --- /dev/null +++ b/contracts/wasm/timestamp/src/lib.rs @@ -0,0 +1,72 @@ +// 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 timestamp::*; +use wasmlib::*; +use wasmlib::host::*; + +use crate::consts::*; +use crate::keys::*; +use crate::results::*; +use crate::state::*; + +mod consts; +mod contract; +mod keys; +mod results; +mod state; +mod timestamp; + +#[no_mangle] +fn on_load() { + let exports = ScExports::new(); + exports.add_func(FUNC_NOW, func_now_thunk); + exports.add_view(VIEW_GET_TIMESTAMP, view_get_timestamp_thunk); + + unsafe { + for i in 0..KEY_MAP_LEN { + IDX_MAP[i] = get_key_id_from_string(KEY_MAP[i]); + } + } +} + +pub struct NowContext { + state: MutabletimestampState, +} + +fn func_now_thunk(ctx: &ScFuncContext) { + ctx.log("timestamp.funcNow"); + let f = NowContext { + state: MutabletimestampState { + id: OBJ_ID_STATE, + }, + }; + func_now(ctx, &f); + ctx.log("timestamp.funcNow ok"); +} + +pub struct GetTimestampContext { + results: MutableGetTimestampResults, + state: ImmutabletimestampState, +} + +fn view_get_timestamp_thunk(ctx: &ScViewContext) { + ctx.log("timestamp.viewGetTimestamp"); + let f = GetTimestampContext { + results: MutableGetTimestampResults { + id: OBJ_ID_RESULTS, + }, + state: ImmutabletimestampState { + id: OBJ_ID_STATE, + }, + }; + view_get_timestamp(ctx, &f); + ctx.log("timestamp.viewGetTimestamp ok"); +} diff --git a/contracts/wasm/timestamp/src/results.rs b/contracts/wasm/timestamp/src/results.rs new file mode 100644 index 0000000000..53e7d5cf08 --- /dev/null +++ b/contracts/wasm/timestamp/src/results.rs @@ -0,0 +1,37 @@ +// 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::*; +use crate::keys::*; + +#[derive(Clone, Copy)] +pub struct ImmutableGetTimestampResults { + pub(crate) id: i32, +} + +impl ImmutableGetTimestampResults { + pub fn timestamp(&self) -> ScImmutableInt64 { + ScImmutableInt64::new(self.id, idx_map(IDX_RESULT_TIMESTAMP)) + } +} + +#[derive(Clone, Copy)] +pub struct MutableGetTimestampResults { + pub(crate) id: i32, +} + +impl MutableGetTimestampResults { + pub fn timestamp(&self) -> ScMutableInt64 { + ScMutableInt64::new(self.id, idx_map(IDX_RESULT_TIMESTAMP)) + } +} diff --git a/contracts/wasm/timestamp/src/state.rs b/contracts/wasm/timestamp/src/state.rs new file mode 100644 index 0000000000..f5554bae10 --- /dev/null +++ b/contracts/wasm/timestamp/src/state.rs @@ -0,0 +1,37 @@ +// 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::*; +use crate::keys::*; + +#[derive(Clone, Copy)] +pub struct ImmutabletimestampState { + pub(crate) id: i32, +} + +impl ImmutabletimestampState { + pub fn timestamp(&self) -> ScImmutableInt64 { + ScImmutableInt64::new(self.id, idx_map(IDX_STATE_TIMESTAMP)) + } +} + +#[derive(Clone, Copy)] +pub struct MutabletimestampState { + pub(crate) id: i32, +} + +impl MutabletimestampState { + pub fn timestamp(&self) -> ScMutableInt64 { + ScMutableInt64::new(self.id, idx_map(IDX_STATE_TIMESTAMP)) + } +} diff --git a/contracts/wasm/timestamp/src/timestamp.rs b/contracts/wasm/timestamp/src/timestamp.rs new file mode 100644 index 0000000000..1ca7585bd1 --- /dev/null +++ b/contracts/wasm/timestamp/src/timestamp.rs @@ -0,0 +1,14 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use wasmlib::*; + +use crate::*; + +pub fn func_now(ctx: &ScFuncContext, f: &NowContext) { + f.state.timestamp().set_value(ctx.timestamp()); +} + +pub fn view_get_timestamp(_ctx: &ScViewContext, f: &GetTimestampContext) { + f.results.timestamp().set_value(f.state.timestamp().value()); +} diff --git a/contracts/wasm/timestamp/test/timestamp_bg.wasm b/contracts/wasm/timestamp/test/timestamp_bg.wasm new file mode 100644 index 0000000000..6b26a708a3 Binary files /dev/null and b/contracts/wasm/timestamp/test/timestamp_bg.wasm differ diff --git a/contracts/wasm/timestamp/test/timestamp_test.go b/contracts/wasm/timestamp/test/timestamp_test.go new file mode 100644 index 0000000000..5dbf04649e --- /dev/null +++ b/contracts/wasm/timestamp/test/timestamp_test.go @@ -0,0 +1,14 @@ +package test + +import ( + "testing" + + "github.com/iotaledger/wasp/contracts/wasm/timestamp/go/timestamp" + "github.com/iotaledger/wasp/packages/vm/wasmsolo" + "github.com/stretchr/testify/require" +) + +func TestDeploy(t *testing.T) { + ctx := wasmsolo.NewSoloContext(t, timestamp.ScName, timestamp.OnLoad) + require.NoError(t, ctx.ContractExists(timestamp.ScName)) +} diff --git a/contracts/wasm/timestamp/ts/timestamp/consts.ts b/contracts/wasm/timestamp/ts/timestamp/consts.ts new file mode 100644 index 0000000000..62157f5505 --- /dev/null +++ b/contracts/wasm/timestamp/ts/timestamp/consts.ts @@ -0,0 +1,22 @@ +// 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 const ScName = "timestamp"; +export const ScDescription = "Extremely simple timestamp server"; +export const HScName = new wasmlib.ScHname(0x3988002e); + +export const ResultTimestamp = "timestamp"; + +export const StateTimestamp = "timestamp"; + +export const FuncNow = "now"; +export const ViewGetTimestamp = "getTimestamp"; + +export const HFuncNow = new wasmlib.ScHname(0xd73b7fc9); +export const HViewGetTimestamp = new wasmlib.ScHname(0x40c6376a); diff --git a/contracts/wasm/timestamp/ts/timestamp/contract.ts b/contracts/wasm/timestamp/ts/timestamp/contract.ts new file mode 100644 index 0000000000..f95a487aa2 --- /dev/null +++ b/contracts/wasm/timestamp/ts/timestamp/contract.ts @@ -0,0 +1,39 @@ +// 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"; +import * as sc from "./index"; + +export class NowCall { + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncNow); +} + +export class NowContext { + state: sc.MutabletimestampState = new sc.MutabletimestampState(); +} + +export class GetTimestampCall { + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetTimestamp); + results: sc.ImmutableGetTimestampResults = new sc.ImmutableGetTimestampResults(); +} + +export class GetTimestampContext { + results: sc.MutableGetTimestampResults = new sc.MutableGetTimestampResults(); + state: sc.ImmutabletimestampState = new sc.ImmutabletimestampState(); +} + +export class ScFuncs { + static now(ctx: wasmlib.ScFuncCallContext): NowCall { + return new NowCall(); + } + + static getTimestamp(ctx: wasmlib.ScViewCallContext): GetTimestampCall { + let f = new GetTimestampCall(); + f.func.setPtrs(null, f.results); + return f; + } +} diff --git a/contracts/wasm/timestamp/ts/timestamp/index.ts b/contracts/wasm/timestamp/ts/timestamp/index.ts new file mode 100644 index 0000000000..0b905cf8fd --- /dev/null +++ b/contracts/wasm/timestamp/ts/timestamp/index.ts @@ -0,0 +1,15 @@ +// 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 "./timestamp"; + +export * from "./consts"; +export * from "./contract"; +export * from "./keys"; +export * from "./lib"; +export * from "./results"; +export * from "./state"; diff --git a/contracts/wasm/timestamp/ts/timestamp/keys.ts b/contracts/wasm/timestamp/ts/timestamp/keys.ts new file mode 100644 index 0000000000..3cfd4e84d0 --- /dev/null +++ b/contracts/wasm/timestamp/ts/timestamp/keys.ts @@ -0,0 +1,21 @@ +// 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"; +import * as sc from "./index"; + + +export const IdxResultTimestamp = 0; + +export const IdxStateTimestamp = 1; + +export let keyMap: string[] = [ + sc.ResultTimestamp, + sc.StateTimestamp, +]; + +export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/timestamp/ts/timestamp/lib.ts b/contracts/wasm/timestamp/ts/timestamp/lib.ts new file mode 100644 index 0000000000..80e29210f7 --- /dev/null +++ b/contracts/wasm/timestamp/ts/timestamp/lib.ts @@ -0,0 +1,40 @@ +// 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"; +import * as sc from "./index"; + +export function on_call(index: i32): void { + return wasmlib.onCall(index); +} + +export function on_load(): void { + let exports = new wasmlib.ScExports(); + exports.addFunc(sc.FuncNow, funcNowThunk); + exports.addView(sc.ViewGetTimestamp, viewGetTimestampThunk); + + for (let i = 0; i < sc.keyMap.length; i++) { + sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); + } +} + +function funcNowThunk(ctx: wasmlib.ScFuncContext): void { + ctx.log("timestamp.funcNow"); + let f = new sc.NowContext(); + f.state.mapID = wasmlib.OBJ_ID_STATE; + sc.funcNow(ctx, f); + ctx.log("timestamp.funcNow ok"); +} + +function viewGetTimestampThunk(ctx: wasmlib.ScViewContext): void { + ctx.log("timestamp.viewGetTimestamp"); + let f = new sc.GetTimestampContext(); + f.results.mapID = wasmlib.OBJ_ID_RESULTS; + f.state.mapID = wasmlib.OBJ_ID_STATE; + sc.viewGetTimestamp(ctx, f); + ctx.log("timestamp.viewGetTimestamp ok"); +} diff --git a/contracts/wasm/timestamp/ts/timestamp/results.ts b/contracts/wasm/timestamp/ts/timestamp/results.ts new file mode 100644 index 0000000000..3eb8e9ffba --- /dev/null +++ b/contracts/wasm/timestamp/ts/timestamp/results.ts @@ -0,0 +1,21 @@ +// 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"; +import * as sc from "./index"; + +export class ImmutableGetTimestampResults extends wasmlib.ScMapID { + timestamp(): wasmlib.ScImmutableInt64 { + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxResultTimestamp]); + } +} + +export class MutableGetTimestampResults extends wasmlib.ScMapID { + timestamp(): wasmlib.ScMutableInt64 { + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxResultTimestamp]); + } +} diff --git a/contracts/wasm/timestamp/ts/timestamp/state.ts b/contracts/wasm/timestamp/ts/timestamp/state.ts new file mode 100644 index 0000000000..cfa1eaab07 --- /dev/null +++ b/contracts/wasm/timestamp/ts/timestamp/state.ts @@ -0,0 +1,21 @@ +// 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"; +import * as sc from "./index"; + +export class ImmutabletimestampState extends wasmlib.ScMapID { + timestamp(): wasmlib.ScImmutableInt64 { + return new wasmlib.ScImmutableInt64(this.mapID, sc.idxMap[sc.IdxStateTimestamp]); + } +} + +export class MutabletimestampState extends wasmlib.ScMapID { + timestamp(): wasmlib.ScMutableInt64 { + return new wasmlib.ScMutableInt64(this.mapID, sc.idxMap[sc.IdxStateTimestamp]); + } +} diff --git a/contracts/wasm/timestamp/ts/timestamp/timestamp.ts b/contracts/wasm/timestamp/ts/timestamp/timestamp.ts new file mode 100644 index 0000000000..5c232cf49a --- /dev/null +++ b/contracts/wasm/timestamp/ts/timestamp/timestamp.ts @@ -0,0 +1,13 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import * as wasmlib from "wasmlib" +import * as sc from "./index"; + +export function funcNow(ctx: wasmlib.ScFuncContext, f: sc.NowContext): void { + f.state.timestamp().setValue(ctx.timestamp()); +} + +export function viewGetTimestamp(ctx: wasmlib.ScViewContext, f: sc.GetTimestampContext): void { + f.results.timestamp().setValue(f.state.timestamp().value()); +} diff --git a/contracts/wasm/timestamp/ts/timestamp/tsconfig.json b/contracts/wasm/timestamp/ts/timestamp/tsconfig.json new file mode 100644 index 0000000000..6fb4265c72 --- /dev/null +++ b/contracts/wasm/timestamp/ts/timestamp/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "assemblyscript/std/assembly.json", + "include": ["./*.ts"] +} diff --git a/contracts/wasm/tokenregistry/go/tokenregistry/consts.go b/contracts/wasm/tokenregistry/go/tokenregistry/consts.go index c4983f23a6..03f53793bd 100644 --- a/contracts/wasm/tokenregistry/go/tokenregistry/consts.go +++ b/contracts/wasm/tokenregistry/go/tokenregistry/consts.go @@ -10,19 +10,20 @@ package tokenregistry import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" const ( - ScName = "tokenregistry" - HScName = wasmlib.ScHname(0xe1ba0c78) + ScName = "tokenregistry" + ScDescription = "" + HScName = wasmlib.ScHname(0xe1ba0c78) ) const ( - ParamColor = wasmlib.Key("color") - ParamDescription = wasmlib.Key("description") - ParamUserDefined = wasmlib.Key("userDefined") + ParamColor = "color" + ParamDescription = "description" + ParamUserDefined = "userDefined" ) const ( - StateColorList = wasmlib.Key("colorList") - StateRegistry = wasmlib.Key("registry") + StateColorList = "colorList" + StateRegistry = "registry" ) const ( diff --git a/contracts/wasm/tokenregistry/go/tokenregistry/keys.go b/contracts/wasm/tokenregistry/go/tokenregistry/keys.go index fc2b5ee642..ec80cb792f 100644 --- a/contracts/wasm/tokenregistry/go/tokenregistry/keys.go +++ b/contracts/wasm/tokenregistry/go/tokenregistry/keys.go @@ -13,8 +13,9 @@ const ( IdxParamColor = 0 IdxParamDescription = 1 IdxParamUserDefined = 2 - IdxStateColorList = 3 - IdxStateRegistry = 4 + + IdxStateColorList = 3 + IdxStateRegistry = 4 ) const keyMapLen = 5 diff --git a/contracts/wasm/tokenregistry/go/tokenregistry/lib.go b/contracts/wasm/tokenregistry/go/tokenregistry/lib.go index a8a1e20fd8..1d16acbac7 100644 --- a/contracts/wasm/tokenregistry/go/tokenregistry/lib.go +++ b/contracts/wasm/tokenregistry/go/tokenregistry/lib.go @@ -47,6 +47,7 @@ type TransferOwnershipContext struct { func funcTransferOwnershipThunk(ctx wasmlib.ScFuncContext) { ctx.Log("tokenregistry.funcTransferOwnership") + // TODO the one who can transfer token ownership ctx.Require(ctx.Caller() == ctx.ContractCreator(), "no permission") @@ -70,6 +71,7 @@ type UpdateMetadataContext struct { func funcUpdateMetadataThunk(ctx wasmlib.ScFuncContext) { ctx.Log("tokenregistry.funcUpdateMetadata") + // TODO the one who can change the token info ctx.Require(ctx.Caller() == ctx.ContractCreator(), "no permission") diff --git a/contracts/wasm/tokenregistry/go/tokenregistry/structs.go b/contracts/wasm/tokenregistry/go/tokenregistry/structs.go index 71c0207191..7dbf217c6f 100644 --- a/contracts/wasm/tokenregistry/go/tokenregistry/structs.go +++ b/contracts/wasm/tokenregistry/go/tokenregistry/structs.go @@ -63,6 +63,10 @@ type MutableToken struct { keyID wasmlib.Key32 } +func (o MutableToken) Delete() { + wasmlib.DelKey(o.objID, o.keyID, wasmlib.TYPE_BYTES) +} + func (o MutableToken) Exists() bool { return wasmlib.Exists(o.objID, o.keyID, wasmlib.TYPE_BYTES) } diff --git a/contracts/wasm/tokenregistry/src/consts.rs b/contracts/wasm/tokenregistry/src/consts.rs index c29728984e..e6cdc316d6 100644 --- a/contracts/wasm/tokenregistry/src/consts.rs +++ b/contracts/wasm/tokenregistry/src/consts.rs @@ -5,30 +5,27 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; -pub const SC_NAME: &str = "tokenregistry"; -pub const HSC_NAME: ScHname = ScHname(0xe1ba0c78); - -pub const PARAM_COLOR: &str = "color"; -pub const PARAM_DESCRIPTION: &str = "description"; -pub const PARAM_USER_DEFINED: &str = "userDefined"; +pub const SC_NAME : &str = "tokenregistry"; +pub const SC_DESCRIPTION : &str = ""; +pub const HSC_NAME : ScHname = ScHname(0xe1ba0c78); -pub const STATE_COLOR_LIST: &str = "colorList"; -pub const STATE_REGISTRY: &str = "registry"; +pub const PARAM_COLOR : &str = "color"; +pub const PARAM_DESCRIPTION : &str = "description"; +pub const PARAM_USER_DEFINED : &str = "userDefined"; -pub const FUNC_MINT_SUPPLY: &str = "mintSupply"; -pub const FUNC_TRANSFER_OWNERSHIP: &str = "transferOwnership"; -pub const FUNC_UPDATE_METADATA: &str = "updateMetadata"; -pub const VIEW_GET_INFO: &str = "getInfo"; +pub const STATE_COLOR_LIST : &str = "colorList"; +pub const STATE_REGISTRY : &str = "registry"; -pub const HFUNC_MINT_SUPPLY: ScHname = ScHname(0x564349a7); -pub const HFUNC_TRANSFER_OWNERSHIP: ScHname = ScHname(0xbb9eb5af); -pub const HFUNC_UPDATE_METADATA: ScHname = ScHname(0xa26b23b6); -pub const HVIEW_GET_INFO: ScHname = ScHname(0xcfedba5f); +pub const FUNC_MINT_SUPPLY : &str = "mintSupply"; +pub const FUNC_TRANSFER_OWNERSHIP : &str = "transferOwnership"; +pub const FUNC_UPDATE_METADATA : &str = "updateMetadata"; +pub const VIEW_GET_INFO : &str = "getInfo"; -// @formatter:on +pub const HFUNC_MINT_SUPPLY : ScHname = ScHname(0x564349a7); +pub const HFUNC_TRANSFER_OWNERSHIP : ScHname = ScHname(0xbb9eb5af); +pub const HFUNC_UPDATE_METADATA : ScHname = ScHname(0xa26b23b6); +pub const HVIEW_GET_INFO : ScHname = ScHname(0xcfedba5f); diff --git a/contracts/wasm/tokenregistry/src/contract.rs b/contracts/wasm/tokenregistry/src/contract.rs index e6fb2016c3..d99016a400 100644 --- a/contracts/wasm/tokenregistry/src/contract.rs +++ b/contracts/wasm/tokenregistry/src/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -17,23 +15,23 @@ use crate::consts::*; use crate::params::*; pub struct MintSupplyCall { - pub func: ScFunc, - pub params: MutableMintSupplyParams, + pub func: ScFunc, + pub params: MutableMintSupplyParams, } pub struct TransferOwnershipCall { - pub func: ScFunc, - pub params: MutableTransferOwnershipParams, + pub func: ScFunc, + pub params: MutableTransferOwnershipParams, } pub struct UpdateMetadataCall { - pub func: ScFunc, - pub params: MutableUpdateMetadataParams, + pub func: ScFunc, + pub params: MutableUpdateMetadataParams, } pub struct GetInfoCall { - pub func: ScView, - pub params: MutableGetInfoParams, + pub func: ScView, + pub params: MutableGetInfoParams, } pub struct ScFuncs { @@ -42,36 +40,37 @@ pub struct ScFuncs { impl ScFuncs { pub fn mint_supply(_ctx: & dyn ScFuncCallContext) -> MintSupplyCall { let mut f = MintSupplyCall { - func: ScFunc::new(HSC_NAME, HFUNC_MINT_SUPPLY), + func: ScFunc::new(HSC_NAME, HFUNC_MINT_SUPPLY), params: MutableMintSupplyParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn transfer_ownership(_ctx: & dyn ScFuncCallContext) -> TransferOwnershipCall { let mut f = TransferOwnershipCall { - func: ScFunc::new(HSC_NAME, HFUNC_TRANSFER_OWNERSHIP), + func: ScFunc::new(HSC_NAME, HFUNC_TRANSFER_OWNERSHIP), params: MutableTransferOwnershipParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn update_metadata(_ctx: & dyn ScFuncCallContext) -> UpdateMetadataCall { let mut f = UpdateMetadataCall { - func: ScFunc::new(HSC_NAME, HFUNC_UPDATE_METADATA), + func: ScFunc::new(HSC_NAME, HFUNC_UPDATE_METADATA), params: MutableUpdateMetadataParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn get_info(_ctx: & dyn ScViewCallContext) -> GetInfoCall { let mut f = GetInfoCall { - func: ScView::new(HSC_NAME, HVIEW_GET_INFO), + func: ScView::new(HSC_NAME, HVIEW_GET_INFO), params: MutableGetInfoParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } } - -// @formatter:on diff --git a/contracts/wasm/tokenregistry/src/keys.rs b/contracts/wasm/tokenregistry/src/keys.rs index 30995b9ff8..4d155e37c3 100644 --- a/contracts/wasm/tokenregistry/src/keys.rs +++ b/contracts/wasm/tokenregistry/src/keys.rs @@ -5,28 +5,28 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use wasmlib::*; use crate::*; -pub(crate) const IDX_PARAM_COLOR: usize = 0; -pub(crate) const IDX_PARAM_DESCRIPTION: usize = 1; -pub(crate) const IDX_PARAM_USER_DEFINED: usize = 2; -pub(crate) const IDX_STATE_COLOR_LIST: usize = 3; -pub(crate) const IDX_STATE_REGISTRY: usize = 4; +pub(crate) const IDX_PARAM_COLOR : usize = 0; +pub(crate) const IDX_PARAM_DESCRIPTION : usize = 1; +pub(crate) const IDX_PARAM_USER_DEFINED : usize = 2; + + +pub(crate) const IDX_STATE_COLOR_LIST : usize = 3; +pub(crate) const IDX_STATE_REGISTRY : usize = 4; pub const KEY_MAP_LEN: usize = 5; pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ - PARAM_COLOR, - PARAM_DESCRIPTION, - PARAM_USER_DEFINED, - STATE_COLOR_LIST, - STATE_REGISTRY, + PARAM_COLOR, + PARAM_DESCRIPTION, + PARAM_USER_DEFINED, + STATE_COLOR_LIST, + STATE_REGISTRY, ]; pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; @@ -36,5 +36,3 @@ pub fn idx_map(idx: usize) -> Key32 { IDX_MAP[idx] } } - -// @formatter:on diff --git a/contracts/wasm/tokenregistry/src/lib.rs b/contracts/wasm/tokenregistry/src/lib.rs index 64d86e35f5..629e025911 100644 --- a/contracts/wasm/tokenregistry/src/lib.rs +++ b/contracts/wasm/tokenregistry/src/lib.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] #![allow(unused_imports)] @@ -30,10 +28,10 @@ mod tokenregistry; #[no_mangle] fn on_load() { let exports = ScExports::new(); - exports.add_func(FUNC_MINT_SUPPLY, func_mint_supply_thunk); + exports.add_func(FUNC_MINT_SUPPLY, func_mint_supply_thunk); exports.add_func(FUNC_TRANSFER_OWNERSHIP, func_transfer_ownership_thunk); - exports.add_func(FUNC_UPDATE_METADATA, func_update_metadata_thunk); - exports.add_view(VIEW_GET_INFO, view_get_info_thunk); + exports.add_func(FUNC_UPDATE_METADATA, func_update_metadata_thunk); + exports.add_view(VIEW_GET_INFO, view_get_info_thunk); unsafe { for i in 0..KEY_MAP_LEN { @@ -43,88 +41,88 @@ fn on_load() { } pub struct MintSupplyContext { - params: ImmutableMintSupplyParams, - state: MutableTokenRegistryState, + params: ImmutableMintSupplyParams, + state: MutableTokenRegistryState, } fn func_mint_supply_thunk(ctx: &ScFuncContext) { - ctx.log("tokenregistry.funcMintSupply"); - let f = MintSupplyContext { - params: ImmutableMintSupplyParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTokenRegistryState { - id: OBJ_ID_STATE, - }, - }; - func_mint_supply(ctx, &f); - ctx.log("tokenregistry.funcMintSupply ok"); + ctx.log("tokenregistry.funcMintSupply"); + let f = MintSupplyContext { + params: ImmutableMintSupplyParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTokenRegistryState { + id: OBJ_ID_STATE, + }, + }; + func_mint_supply(ctx, &f); + ctx.log("tokenregistry.funcMintSupply ok"); } pub struct TransferOwnershipContext { - params: ImmutableTransferOwnershipParams, - state: MutableTokenRegistryState, + params: ImmutableTransferOwnershipParams, + state: MutableTokenRegistryState, } fn func_transfer_ownership_thunk(ctx: &ScFuncContext) { - ctx.log("tokenregistry.funcTransferOwnership"); - // TODO the one who can transfer token ownership - ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); - - let f = TransferOwnershipContext { - params: ImmutableTransferOwnershipParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTokenRegistryState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.color().exists(), "missing mandatory color"); - func_transfer_ownership(ctx, &f); - ctx.log("tokenregistry.funcTransferOwnership ok"); + ctx.log("tokenregistry.funcTransferOwnership"); + + // TODO the one who can transfer token ownership + ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); + + let f = TransferOwnershipContext { + params: ImmutableTransferOwnershipParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTokenRegistryState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.color().exists(), "missing mandatory color"); + func_transfer_ownership(ctx, &f); + ctx.log("tokenregistry.funcTransferOwnership ok"); } pub struct UpdateMetadataContext { - params: ImmutableUpdateMetadataParams, - state: MutableTokenRegistryState, + params: ImmutableUpdateMetadataParams, + state: MutableTokenRegistryState, } fn func_update_metadata_thunk(ctx: &ScFuncContext) { - ctx.log("tokenregistry.funcUpdateMetadata"); - // TODO the one who can change the token info - ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); - - let f = UpdateMetadataContext { - params: ImmutableUpdateMetadataParams { - id: OBJ_ID_PARAMS, - }, - state: MutableTokenRegistryState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.color().exists(), "missing mandatory color"); - func_update_metadata(ctx, &f); - ctx.log("tokenregistry.funcUpdateMetadata ok"); + ctx.log("tokenregistry.funcUpdateMetadata"); + + // TODO the one who can change the token info + ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); + + let f = UpdateMetadataContext { + params: ImmutableUpdateMetadataParams { + id: OBJ_ID_PARAMS, + }, + state: MutableTokenRegistryState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.color().exists(), "missing mandatory color"); + func_update_metadata(ctx, &f); + ctx.log("tokenregistry.funcUpdateMetadata ok"); } pub struct GetInfoContext { - params: ImmutableGetInfoParams, - state: ImmutableTokenRegistryState, + params: ImmutableGetInfoParams, + state: ImmutableTokenRegistryState, } fn view_get_info_thunk(ctx: &ScViewContext) { - ctx.log("tokenregistry.viewGetInfo"); - let f = GetInfoContext { - params: ImmutableGetInfoParams { - id: OBJ_ID_PARAMS, - }, - state: ImmutableTokenRegistryState { - id: OBJ_ID_STATE, - }, - }; - ctx.require(f.params.color().exists(), "missing mandatory color"); - view_get_info(ctx, &f); - ctx.log("tokenregistry.viewGetInfo ok"); + ctx.log("tokenregistry.viewGetInfo"); + let f = GetInfoContext { + params: ImmutableGetInfoParams { + id: OBJ_ID_PARAMS, + }, + state: ImmutableTokenRegistryState { + id: OBJ_ID_STATE, + }, + }; + ctx.require(f.params.color().exists(), "missing mandatory color"); + view_get_info(ctx, &f); + ctx.log("tokenregistry.viewGetInfo ok"); } - -// @formatter:on diff --git a/contracts/wasm/tokenregistry/src/params.rs b/contracts/wasm/tokenregistry/src/params.rs index 5229406f17..6cf7b6ae67 100644 --- a/contracts/wasm/tokenregistry/src/params.rs +++ b/contracts/wasm/tokenregistry/src/params.rs @@ -13,6 +13,7 @@ use wasmlib::host::*; use crate::*; use crate::keys::*; +use crate::structs::*; #[derive(Clone, Copy)] pub struct ImmutableMintSupplyParams { @@ -21,12 +22,12 @@ pub struct ImmutableMintSupplyParams { impl ImmutableMintSupplyParams { pub fn description(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) + } pub fn user_defined(&self) -> ScImmutableString { - ScImmutableString::new(self.id, idx_map(IDX_PARAM_USER_DEFINED)) - } + ScImmutableString::new(self.id, idx_map(IDX_PARAM_USER_DEFINED)) + } } #[derive(Clone, Copy)] @@ -36,12 +37,12 @@ pub struct MutableMintSupplyParams { impl MutableMintSupplyParams { pub fn description(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_DESCRIPTION)) + } pub fn user_defined(&self) -> ScMutableString { - ScMutableString::new(self.id, idx_map(IDX_PARAM_USER_DEFINED)) - } + ScMutableString::new(self.id, idx_map(IDX_PARAM_USER_DEFINED)) + } } #[derive(Clone, Copy)] @@ -51,8 +52,8 @@ pub struct ImmutableTransferOwnershipParams { impl ImmutableTransferOwnershipParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } } #[derive(Clone, Copy)] @@ -62,8 +63,8 @@ pub struct MutableTransferOwnershipParams { impl MutableTransferOwnershipParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } } #[derive(Clone, Copy)] @@ -73,8 +74,8 @@ pub struct ImmutableUpdateMetadataParams { impl ImmutableUpdateMetadataParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } } #[derive(Clone, Copy)] @@ -84,8 +85,8 @@ pub struct MutableUpdateMetadataParams { impl MutableUpdateMetadataParams { pub fn color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScMutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } } #[derive(Clone, Copy)] @@ -95,8 +96,8 @@ pub struct ImmutableGetInfoParams { impl ImmutableGetInfoParams { pub fn color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) - } + ScImmutableColor::new(self.id, idx_map(IDX_PARAM_COLOR)) + } } #[derive(Clone, Copy)] @@ -106,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, idx_map(IDX_PARAM_COLOR)) + } } diff --git a/contracts/wasm/tokenregistry/src/state.rs b/contracts/wasm/tokenregistry/src/state.rs index d879c8403d..3726c7b438 100644 --- a/contracts/wasm/tokenregistry/src/state.rs +++ b/contracts/wasm/tokenregistry/src/state.rs @@ -16,7 +16,7 @@ use crate::keys::*; use crate::structs::*; pub struct ArrayOfImmutableColor { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfImmutableColor { @@ -30,7 +30,7 @@ impl ArrayOfImmutableColor { } pub struct MapColorToImmutableToken { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapColorToImmutableToken { @@ -46,18 +46,18 @@ 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); - ArrayOfImmutableColor { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, idx_map(IDX_STATE_COLOR_LIST), 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); - MapColorToImmutableToken { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_REGISTRY), TYPE_MAP); + MapColorToImmutableToken { obj_id: map_id } + } } pub struct ArrayOfMutableColor { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfMutableColor { @@ -75,12 +75,12 @@ impl ArrayOfMutableColor { } pub struct MapColorToMutableToken { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapColorToMutableToken { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_token(&self, key: &ScColor) -> MutableToken { @@ -95,12 +95,12 @@ pub struct MutableTokenRegistryState { impl MutableTokenRegistryState { pub fn color_list(&self) -> ArrayOfMutableColor { - let arr_id = get_object_id(self.id, idx_map(IDX_STATE_COLOR_LIST), TYPE_ARRAY | TYPE_COLOR); - ArrayOfMutableColor { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, idx_map(IDX_STATE_COLOR_LIST), 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); - MapColorToMutableToken { obj_id: map_id } - } + let map_id = get_object_id(self.id, idx_map(IDX_STATE_REGISTRY), TYPE_MAP); + MapColorToMutableToken { obj_id: map_id } + } } diff --git a/contracts/wasm/tokenregistry/src/structs.rs b/contracts/wasm/tokenregistry/src/structs.rs index 2394462603..d5dd0a4c6b 100644 --- a/contracts/wasm/tokenregistry/src/structs.rs +++ b/contracts/wasm/tokenregistry/src/structs.rs @@ -5,46 +5,45 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] +#![allow(unused_imports)] use wasmlib::*; use wasmlib::host::*; pub struct Token { - pub created: i64, // creation timestamp - pub description: String, // description what minted token represents - pub minted_by: ScAgentID, // original minter - pub owner: ScAgentID, // current owner - pub supply: i64, // amount of tokens originally minted - pub updated: i64, // last update timestamp - pub user_defined: String, // any user defined text + pub created : i64, // creation timestamp + pub description : String, // description what minted token represents + pub minted_by : ScAgentID, // original minter + pub owner : ScAgentID, // current owner + pub supply : i64, // amount of tokens originally minted + pub updated : i64, // last update timestamp + pub user_defined : String, // any user defined text } impl Token { pub fn from_bytes(bytes: &[u8]) -> Token { let mut decode = BytesDecoder::new(bytes); Token { - created: decode.int64(), - description: decode.string(), - minted_by: decode.agent_id(), - owner: decode.agent_id(), - supply: decode.int64(), - updated: decode.int64(), - user_defined: decode.string(), + created : decode.int64(), + description : decode.string(), + minted_by : decode.agent_id(), + owner : decode.agent_id(), + supply : decode.int64(), + updated : decode.int64(), + user_defined : decode.string(), } } pub fn to_bytes(&self) -> Vec { let mut encode = BytesEncoder::new(); - encode.int64(self.created); - encode.string(&self.description); - encode.agent_id(&self.minted_by); - encode.agent_id(&self.owner); - encode.int64(self.supply); - encode.int64(self.updated); - encode.string(&self.user_defined); + encode.int64(self.created); + encode.string(&self.description); + encode.agent_id(&self.minted_by); + encode.agent_id(&self.owner); + encode.int64(self.supply); + encode.int64(self.updated); + encode.string(&self.user_defined); return encode.data(); } } @@ -70,6 +69,10 @@ pub struct MutableToken { } impl MutableToken { + 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) } @@ -82,5 +85,3 @@ impl MutableToken { Token::from_bytes(&get_bytes(self.obj_id, self.key_id, TYPE_BYTES)) } } - -// @formatter:on diff --git a/contracts/wasm/tokenregistry/test/tokenregistry_bg.wasm b/contracts/wasm/tokenregistry/test/tokenregistry_bg.wasm index 31ceef70e0..27eecf21ae 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/consts.ts b/contracts/wasm/tokenregistry/ts/tokenregistry/consts.ts index 27aab17d0d..fd519a0bf0 100644 --- a/contracts/wasm/tokenregistry/ts/tokenregistry/consts.ts +++ b/contracts/wasm/tokenregistry/ts/tokenregistry/consts.ts @@ -5,10 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; -export const ScName = "tokenregistry"; -export const HScName = new wasmlib.ScHname(0xe1ba0c78); +export const ScName = "tokenregistry"; +export const ScDescription = ""; +export const HScName = new wasmlib.ScHname(0xe1ba0c78); export const ParamColor = "color"; export const ParamDescription = "description"; diff --git a/contracts/wasm/tokenregistry/ts/tokenregistry/contract.ts b/contracts/wasm/tokenregistry/ts/tokenregistry/contract.ts index 8570ad323a..c0b4241dbc 100644 --- a/contracts/wasm/tokenregistry/ts/tokenregistry/contract.ts +++ b/contracts/wasm/tokenregistry/ts/tokenregistry/contract.ts @@ -5,51 +5,50 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class MintSupplyCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncMintSupply); - params: sc.MutableMintSupplyParams = new sc.MutableMintSupplyParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncMintSupply); + params: sc.MutableMintSupplyParams = new sc.MutableMintSupplyParams(); } export class MintSupplyContext { - params: sc.ImmutableMintSupplyParams = new sc.ImmutableMintSupplyParams(); - state: sc.MutableTokenRegistryState = new sc.MutableTokenRegistryState(); + params: sc.ImmutableMintSupplyParams = new sc.ImmutableMintSupplyParams(); + state: sc.MutableTokenRegistryState = new sc.MutableTokenRegistryState(); } export class TransferOwnershipCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTransferOwnership); - params: sc.MutableTransferOwnershipParams = new sc.MutableTransferOwnershipParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncTransferOwnership); + params: sc.MutableTransferOwnershipParams = new sc.MutableTransferOwnershipParams(); } export class TransferOwnershipContext { - params: sc.ImmutableTransferOwnershipParams = new sc.ImmutableTransferOwnershipParams(); - state: sc.MutableTokenRegistryState = new sc.MutableTokenRegistryState(); + params: sc.ImmutableTransferOwnershipParams = new sc.ImmutableTransferOwnershipParams(); + state: sc.MutableTokenRegistryState = new sc.MutableTokenRegistryState(); } export class UpdateMetadataCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncUpdateMetadata); - params: sc.MutableUpdateMetadataParams = new sc.MutableUpdateMetadataParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncUpdateMetadata); + params: sc.MutableUpdateMetadataParams = new sc.MutableUpdateMetadataParams(); } export class UpdateMetadataContext { - params: sc.ImmutableUpdateMetadataParams = new sc.ImmutableUpdateMetadataParams(); - state: sc.MutableTokenRegistryState = new sc.MutableTokenRegistryState(); + params: sc.ImmutableUpdateMetadataParams = new sc.ImmutableUpdateMetadataParams(); + state: sc.MutableTokenRegistryState = new sc.MutableTokenRegistryState(); } export class GetInfoCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetInfo); - params: sc.MutableGetInfoParams = new sc.MutableGetInfoParams(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetInfo); + params: sc.MutableGetInfoParams = new sc.MutableGetInfoParams(); } export class GetInfoContext { - params: sc.ImmutableGetInfoParams = new sc.ImmutableGetInfoParams(); - state: sc.ImmutableTokenRegistryState = new sc.ImmutableTokenRegistryState(); + params: sc.ImmutableGetInfoParams = new sc.ImmutableGetInfoParams(); + state: sc.ImmutableTokenRegistryState = new sc.ImmutableTokenRegistryState(); } export class ScFuncs { - static mintSupply(ctx: wasmlib.ScFuncCallContext): MintSupplyCall { let f = new MintSupplyCall(); f.func.setPtrs(f.params, null); diff --git a/contracts/wasm/tokenregistry/ts/tokenregistry/keys.ts b/contracts/wasm/tokenregistry/ts/tokenregistry/keys.ts index d4325599ea..6e20801b3c 100644 --- a/contracts/wasm/tokenregistry/ts/tokenregistry/keys.ts +++ b/contracts/wasm/tokenregistry/ts/tokenregistry/keys.ts @@ -5,21 +5,23 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export const IdxParamColor = 0; export const IdxParamDescription = 1; export const IdxParamUserDefined = 2; -export const IdxStateColorList = 3; -export const IdxStateRegistry = 4; + + +export const IdxStateColorList = 3; +export const IdxStateRegistry = 4; export let keyMap: string[] = [ - sc.ParamColor, - sc.ParamDescription, - sc.ParamUserDefined, - sc.StateColorList, - sc.StateRegistry, + sc.ParamColor, + sc.ParamDescription, + sc.ParamUserDefined, + sc.StateColorList, + sc.StateRegistry, ]; export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); diff --git a/contracts/wasm/tokenregistry/ts/tokenregistry/lib.ts b/contracts/wasm/tokenregistry/ts/tokenregistry/lib.ts index 7678df9ec0..48b2839424 100644 --- a/contracts/wasm/tokenregistry/ts/tokenregistry/lib.ts +++ b/contracts/wasm/tokenregistry/ts/tokenregistry/lib.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export function on_call(index: i32): void { @@ -14,10 +14,10 @@ export function on_call(index: i32): void { export function on_load(): void { let exports = new wasmlib.ScExports(); - exports.addFunc(sc.FuncMintSupply, funcMintSupplyThunk); + exports.addFunc(sc.FuncMintSupply, funcMintSupplyThunk); exports.addFunc(sc.FuncTransferOwnership, funcTransferOwnershipThunk); - exports.addFunc(sc.FuncUpdateMetadata, funcUpdateMetadataThunk); - exports.addView(sc.ViewGetInfo, viewGetInfoThunk); + exports.addFunc(sc.FuncUpdateMetadata, funcUpdateMetadataThunk); + exports.addView(sc.ViewGetInfo, viewGetInfoThunk); for (let i = 0; i < sc.keyMap.length; i++) { sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); @@ -25,46 +25,48 @@ export function on_load(): void { } function funcMintSupplyThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("tokenregistry.funcMintSupply"); - let f = new sc.MintSupplyContext(); + ctx.log("tokenregistry.funcMintSupply"); + let f = new sc.MintSupplyContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - sc.funcMintSupply(ctx, f); - ctx.log("tokenregistry.funcMintSupply ok"); + sc.funcMintSupply(ctx, f); + ctx.log("tokenregistry.funcMintSupply ok"); } function funcTransferOwnershipThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("tokenregistry.funcTransferOwnership"); - // TODO the one who can transfer token ownership - ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + ctx.log("tokenregistry.funcTransferOwnership"); - let f = new sc.TransferOwnershipContext(); + // TODO the one who can transfer token ownership + ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + + let f = new sc.TransferOwnershipContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.color().exists(), "missing mandatory color") - sc.funcTransferOwnership(ctx, f); - ctx.log("tokenregistry.funcTransferOwnership ok"); + ctx.require(f.params.color().exists(), "missing mandatory color"); + sc.funcTransferOwnership(ctx, f); + ctx.log("tokenregistry.funcTransferOwnership ok"); } function funcUpdateMetadataThunk(ctx: wasmlib.ScFuncContext): void { - ctx.log("tokenregistry.funcUpdateMetadata"); - // TODO the one who can change the token info - ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + ctx.log("tokenregistry.funcUpdateMetadata"); + + // TODO the one who can change the token info + ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); - let f = new sc.UpdateMetadataContext(); + let f = new sc.UpdateMetadataContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.color().exists(), "missing mandatory color") - sc.funcUpdateMetadata(ctx, f); - ctx.log("tokenregistry.funcUpdateMetadata ok"); + ctx.require(f.params.color().exists(), "missing mandatory color"); + sc.funcUpdateMetadata(ctx, f); + ctx.log("tokenregistry.funcUpdateMetadata ok"); } function viewGetInfoThunk(ctx: wasmlib.ScViewContext): void { - ctx.log("tokenregistry.viewGetInfo"); - let f = new sc.GetInfoContext(); + ctx.log("tokenregistry.viewGetInfo"); + let f = new sc.GetInfoContext(); f.params.mapID = wasmlib.OBJ_ID_PARAMS; f.state.mapID = wasmlib.OBJ_ID_STATE; - ctx.require(f.params.color().exists(), "missing mandatory color") - sc.viewGetInfo(ctx, f); - ctx.log("tokenregistry.viewGetInfo ok"); + ctx.require(f.params.color().exists(), "missing mandatory color"); + sc.viewGetInfo(ctx, f); + ctx.log("tokenregistry.viewGetInfo ok"); } diff --git a/contracts/wasm/tokenregistry/ts/tokenregistry/params.ts b/contracts/wasm/tokenregistry/ts/tokenregistry/params.ts index 6c55fd2bfc..8d16af038f 100644 --- a/contracts/wasm/tokenregistry/ts/tokenregistry/params.ts +++ b/contracts/wasm/tokenregistry/ts/tokenregistry/params.ts @@ -5,69 +5,61 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; 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, sc.idxMap[sc.IdxParamDescription]); + } userDefined(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamUserDefined]); - } + return new wasmlib.ScImmutableString(this.mapID, sc.idxMap[sc.IdxParamUserDefined]); + } } 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, sc.idxMap[sc.IdxParamDescription]); + } userDefined(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamUserDefined]); - } + return new wasmlib.ScMutableString(this.mapID, sc.idxMap[sc.IdxParamUserDefined]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } } 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, sc.idxMap[sc.IdxParamColor]); + } } diff --git a/contracts/wasm/tokenregistry/ts/tokenregistry/state.ts b/contracts/wasm/tokenregistry/ts/tokenregistry/state.ts index e82e0fe03d..bdbf15f919 100644 --- a/contracts/wasm/tokenregistry/ts/tokenregistry/state.ts +++ b/contracts/wasm/tokenregistry/ts/tokenregistry/state.ts @@ -5,11 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ArrayOfImmutableColor { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -25,7 +25,7 @@ export class ArrayOfImmutableColor { } export class MapColorToImmutableToken { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -37,20 +37,19 @@ 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); - return new sc.ArrayOfImmutableColor(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateColorList], 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); - return new sc.MapColorToImmutableToken(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateRegistry], wasmlib.TYPE_MAP); + return new sc.MapColorToImmutableToken(mapID); + } } export class ArrayOfMutableColor { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -70,14 +69,14 @@ export class ArrayOfMutableColor { } export class MapColorToMutableToken { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getToken(key: wasmlib.ScColor): sc.MutableToken { @@ -86,14 +85,13 @@ export class MapColorToMutableToken { } export class MutableTokenRegistryState extends wasmlib.ScMapID { - colorList(): sc.ArrayOfMutableColor { - let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateColorList], wasmlib.TYPE_ARRAY|wasmlib.TYPE_COLOR); - return new sc.ArrayOfMutableColor(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateColorList], 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); - return new sc.MapColorToMutableToken(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, sc.idxMap[sc.IdxStateRegistry], wasmlib.TYPE_MAP); + return new sc.MapColorToMutableToken(mapID); + } } diff --git a/contracts/wasm/tokenregistry/ts/tokenregistry/structs.ts b/contracts/wasm/tokenregistry/ts/tokenregistry/structs.ts index 8bdb6867c1..e7617740b3 100644 --- a/contracts/wasm/tokenregistry/ts/tokenregistry/structs.ts +++ b/contracts/wasm/tokenregistry/ts/tokenregistry/structs.ts @@ -5,26 +5,26 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export class Token { - created : i64 = 0; // creation timestamp - description: string = ""; // description what minted token represents - mintedBy : wasmlib.ScAgentID = new wasmlib.ScAgentID(); // original minter - owner : wasmlib.ScAgentID = new wasmlib.ScAgentID(); // current owner - supply : i64 = 0; // amount of tokens originally minted - updated : i64 = 0; // last update timestamp - userDefined: string = ""; // any user defined text + created : i64 = 0; // creation timestamp + description : string = ""; // description what minted token represents + mintedBy : wasmlib.ScAgentID = new wasmlib.ScAgentID(); // original minter + owner : wasmlib.ScAgentID = new wasmlib.ScAgentID(); // current owner + supply : i64 = 0; // amount of tokens originally minted + updated : i64 = 0; // last update timestamp + userDefined : string = ""; // any user defined text static fromBytes(bytes: u8[]): Token { let decode = new wasmlib.BytesDecoder(bytes); let data = new Token(); - data.created = decode.int64(); + data.created = decode.int64(); data.description = decode.string(); - data.mintedBy = decode.agentID(); - data.owner = decode.agentID(); - data.supply = decode.int64(); - data.updated = decode.int64(); + data.mintedBy = decode.agentID(); + data.owner = decode.agentID(); + data.supply = decode.int64(); + data.updated = decode.int64(); data.userDefined = decode.string(); decode.close(); return data; @@ -32,13 +32,13 @@ export class Token { bytes(): u8[] { return new wasmlib.BytesEncoder(). - int64(this.created). - string(this.description). - agentID(this.mintedBy). - agentID(this.owner). - int64(this.supply). - int64(this.updated). - string(this.userDefined). + int64(this.created). + string(this.description). + agentID(this.mintedBy). + agentID(this.owner). + int64(this.supply). + int64(this.updated). + string(this.userDefined). data(); } } @@ -57,7 +57,7 @@ export class ImmutableToken { } value(): Token { - return Token.fromBytes(wasmlib.getBytes(this.objID, this.keyID,wasmlib. TYPE_BYTES)); + return Token.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); } } @@ -70,6 +70,10 @@ export class MutableToken { 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); } @@ -79,6 +83,6 @@ export class MutableToken { } value(): Token { - return Token.fromBytes(wasmlib.getBytes(this.objID, this.keyID,wasmlib. TYPE_BYTES)); + return Token.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); } } diff --git a/contracts/wasm/ts_build.cmd b/contracts/wasm/ts_build.cmd index 17634aa427..cdcf0d6155 100644 --- a/contracts/wasm/ts_build.cmd +++ b/contracts/wasm/ts_build.cmd @@ -1,8 +1,9 @@ @echo off cd %1 -if not exist schema.yaml goto :xit +if not exist schema.yaml if not exist schema.json goto :xit echo Building %1 schema -ts %2 +echo compiling %1_ts.wasm call asc ts/%1/lib.ts --lib d:/work/node_modules --binaryFile ts/pkg/%1_ts.wasm rem call asc ts/%1/lib.ts --lib d:/work/node_modules --binaryFile ts/pkg/%1_ts.wasm --textFile ts/pkg/%1_ts.wat :xit diff --git a/contracts/wasm/update_hardcoded.cmd b/contracts/wasm/update_hardcoded.cmd index e93c60ebf6..affb61cee6 100644 --- a/contracts/wasm/update_hardcoded.cmd +++ b/contracts/wasm/update_hardcoded.cmd @@ -2,4 +2,7 @@ for /d %%f in (*.) do if exist %%f\pkg\%%f*_bg.wasm copy /y %%f\pkg\%%f*_bg.wasm %%f\test\*.* if exist testcore\pkg\testcore_bg.wasm copy /y testcore\pkg\testcore_bg.wasm ..\..\packages\vm\core\testcore\sbtests\sbtestsc\*.* if exist inccounter\pkg\inccounter_bg.wasm copy /y inccounter\pkg\inccounter_bg.wasm ..\..\tools\cluster\tests\wasm\*.* - +cd ..\..\documentation\tutorial-examples +wasm-pack build +copy /y pkg\example_tutorial_bg.wasm test +cd ..\..\contracts\wasm diff --git a/documentation/ISCP architecture description v3.pdf b/documentation/ISCP architecture description v3.pdf deleted file mode 100644 index 7dcf7330db..0000000000 Binary files a/documentation/ISCP architecture description v3.pdf and /dev/null differ diff --git a/documentation/ISC_WP_Nov_10_2021.pdf b/documentation/ISC_WP_Nov_10_2021.pdf new file mode 100644 index 0000000000..0393f9ef01 Binary files /dev/null and b/documentation/ISC_WP_Nov_10_2021.pdf differ diff --git a/documentation/docs/misc/docker.md b/documentation/docs/guide/chains_and_nodes/docker_standalone.md similarity index 75% rename from documentation/docs/misc/docker.md rename to documentation/docs/guide/chains_and_nodes/docker_standalone.md index 29186ae906..0f2fd56038 100644 --- a/documentation/docs/misc/docker.md +++ b/documentation/docs/guide/chains_and_nodes/docker_standalone.md @@ -10,20 +10,12 @@ keywords: - configure - arguments --- -# Docker +# Docker (Standalone) -This page describes the configuration of the Wasp node in combination with Docker. If you followed the instructions in [Running a Node](../guide/chains_and_nodes/running-a-node.md), you can skip to [Configuring wasp-cli](../guide/chains_and_nodes/wasp-cli.md). +This page describes the configuration of a single Wasp node in combination with Docker. If you followed the instructions in [Running a Node](running-a-node.md), you can skip to [Configuring wasp-cli](wasp-cli.md). ## Introduction -The Dockerfile is separated into several stages which effectively splits Wasp into four small pieces: - -* Testing - * Unit testing - * Integration testing -* Wasp CLI -* Wasp Node - ## Running a Wasp Node Checkout the project, switch to 'develop' and build the main image: @@ -34,7 +26,7 @@ cd wasp docker build -t wasp-node . ``` -The build process will copy the docker_config.json file into the image, which will use it when the node gets started. +The build process will copy the docker_config.json file into the image, which will be used when the node gets started. By default, the build process will use `-tags rocksdb,builtin_static` as a build argument. This argument can be modified with `--build-arg BUILD_TAGS=`. 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 e15d5ccfd7..40e4e85728 100644 --- a/documentation/docs/guide/chains_and_nodes/running-a-node.md +++ b/documentation/docs/guide/chains_and_nodes/running-a-node.md @@ -16,7 +16,7 @@ keywords: # Running a Node In the following section, you can find information on how to use Wasp by cloning the repository and building the application. -If you prefer, you can also configure a node [using a docker image](../../misc/docker.md) (official images will be provided in the future). +If you prefer, you can also configure a node [using a docker image (standalone)](docker_standalone.md) or [docker (preconfigured)](docker_preconfigured.md) (official images will be provided in the future). ## Requirements @@ -30,7 +30,13 @@ If you prefer, you can also configure a node [using a docker image](../../misc/d - [Go 1.16](https://golang.org/doc/install) - [RocksDB](https://github.com/facebook/rocksdb/blob/master/INSTALL.md) - Access to a [GoShimmer](https://github.com/iotaledger/goshimmer) node for - production operation + production operation. + +:::warning + +GoShimmer is a developing prototype, so some things are prone to break. For a smooth development experience, you should use the GoShimmer code at [this commit](https://github.com/iotaledger/goshimmer/commit/25c827e8326a). + +::: :::info note @@ -182,7 +188,7 @@ Grafana provides a dashboard to visualize system metrics. It can use the prometh ## Goshimmer Provider -For the Wasp node to communicate with the L1 (Tangle/Goshimmer Network), it needs access to a Goshimmer node with the TXStream plugin enabled. You can use any publicly available node, or [set up your own node](https://wiki.iota.org/goshimmer/tutorials/setup/). +For the Wasp node to communicate with the L1 (Tangle/Goshimmer Network), it needs access to a Goshimmer node with the TXStream plugin enabled. You can use any [publicly available node](https://wiki.iota.org/wasp/guide/chains_and_nodes/testnet), or [set up your own node](https://wiki.iota.org/goshimmer/tutorials/setup/). :::info note diff --git a/documentation/docs/guide/core_concepts/consensus.md b/documentation/docs/guide/core_concepts/consensus.md index 8e37edfaa2..9caeab9032 100644 --- a/documentation/docs/guide/core_concepts/consensus.md +++ b/documentation/docs/guide/core_concepts/consensus.md @@ -48,5 +48,6 @@ The rest of the consensus algorithm is built on top of the ACS. Each node suppli It is ensured that all honest nodes have the same input for the VM. After running the selected batch, the VM results are then collectively signed using the threshold signature. The signed transaction can be published by any node at this point. In order to minimize the load on the IOTA network, the nodes calculate a delay for posting the transaction to the network based on a deterministic permutation of the nodes relative to the local perception of time. :::note -A more in-depth explanation of the topics described in this page can be found on the [architecture document](https://github.com/iotaledger/wasp/raw/master/documentation/ISCP%20architecture%20description%20v3.pdf) +The comprehensive overview of architectural design decisions of IOTA Smart Contracts can be found in the +[whitepaper](https://github.com/iotaledger/wasp/raw/master/documentation/ISC_WP_Nov_10_2021.pdf). ::: diff --git a/documentation/docs/guide/core_concepts/core_contracts/governance.md b/documentation/docs/guide/core_concepts/core_contracts/governance.md index e48b42601a..23dcb3bd6e 100644 --- a/documentation/docs/guide/core_concepts/core_contracts/governance.md +++ b/documentation/docs/guide/core_concepts/core_contracts/governance.md @@ -40,7 +40,7 @@ Adds an address to the list of identities that constitute the state controller, ### removeAllowedStateControllerAddress -Removes an address to the list of identities that constitute the state controller, this change will only become effective once `rotateStateController` is called +Removes an address from the list of identities that constitute the state controller, this change will only become effective once `rotateStateController` is called ### delegateChainOwnership diff --git a/documentation/docs/guide/core_concepts/iscp-architecture.md b/documentation/docs/guide/core_concepts/iscp-architecture.md index 667701e258..7b2f3bcba4 100644 --- a/documentation/docs/guide/core_concepts/iscp-architecture.md +++ b/documentation/docs/guide/core_concepts/iscp-architecture.md @@ -4,7 +4,7 @@ keywords: - Architecture - Ethereum - Implementation -description: IOTA Smart Contracts allow anyone to start their own chain and validators. Link to full technical description of the IOTA Smart Contracts architecture. +description: IOTA Smart Contracts allow anyone to start their own chain and validators. Link to full technical description of the IOTA Smart Contarcts architecture and whitepaper image: /img/multichain.png --- # IOTA Smart Contracts Architecture @@ -17,5 +17,5 @@ The multi-chain nature of the IOTA Smart Contracts makes it a more complex imple ![IOTA Smart Contracts multichain architecture](/img/multichain.png) -A full and extensive documentation of the IOTA Architecture describing all components in detail can be found in this -[technical description](https://github.com/iotaledger/wasp/raw/master/documentation/ISCP%20architecture%20description%20v3.pdf). +The comprehensive overview of architectural design decisions of IOTA Smart Contracts can be found in the +[whitepaper](https://files.iota.org/papers/ISC_WP_Nov_10_2021.pdf). diff --git a/documentation/docs/guide/core_concepts/smartcontract-interaction/off-ledger-requests.md b/documentation/docs/guide/core_concepts/smartcontract-interaction/off-ledger-requests.md index 970490261e..ec5d7842bc 100644 --- a/documentation/docs/guide/core_concepts/smartcontract-interaction/off-ledger-requests.md +++ b/documentation/docs/guide/core_concepts/smartcontract-interaction/off-ledger-requests.md @@ -17,7 +17,7 @@ You can send `off-ledger` requests by sending an API call to a WASP node, which ## Nonce -In order to [prevent replay attacks](../../../rfc/prevent-mev.md), off-ledger requests must include a special parameter, the `nonce`. +In order to prevent replay attacks, off-ledger requests must include a special parameter, the `nonce`. Nonces are account-bound; the current nonce for a given account can be obtained via the [`accounts`](../core_contracts/accounts.md) core contract `getAccountNonce` view. :::info Important diff --git a/documentation/docs/guide/development_tools/docker_preconfigured.md b/documentation/docs/guide/development_tools/docker_preconfigured.md new file mode 100644 index 0000000000..b252b26ed5 --- /dev/null +++ b/documentation/docs/guide/development_tools/docker_preconfigured.md @@ -0,0 +1,76 @@ +--- +description: How to run the preconfigured Docker setup. +image: /img/logo/WASP_logo_dark.png +keywords: +- ISCP +- Smart Contracts +- Running a node +- docker +- image +- build +- configure +- arguments +- GoShimmer +--- +# Preconfigured Development Docker setup + +This page describes the usage of the preconfigured developer Docker setup. + +## Introduction + +To diminish the time spent on configuration and research, we have created a docker-compose setup that ships a preconfigured Wasp and GoShimmer (v0.7.7) node, that are connected with each other - ready to run out of the box. + +## Running the setup + +Checkout the project, switch to 'develop' and start with docker-compose: + +``` +git clone -b develop https://github.com/iotaledger/wasp.git +cd tools/devnet +docker-compose up +``` + +Docker will build a lightly modified GoShimmer (v0.7.7) image and a Wasp image based on the contents of the checked out develop branch. If you do modifications inside the branch, docker-compose will include them into the Wasp image too. + +## Usage + +Wasp is configured to allow any connection coming from wasp-cli. This is fine for development purposes, but please make sure to not run it on a publicly available server, or to create matching firewall filter rules. + +Besides this, everything should simply work as expected. Faucet requests will be handled accordingly, you will be able to deploy and run smart contracts. All useful ports such as: + +* Wasp Dashboard (7000) +* Wasp API (9090) +* GoShimmer Dashboard (8081) +* GoShimmer API (8080) + +are available to the local machine. + +## Wasp-CLI configuration + +As all ports are locally available, this `wasp-cli.json` configuration is to be used: + +``` +{ + "goshimmer": { + "api": "127.0.0.1:8080", + "faucetpowtarget": -1 + }, + "wasp": { + "0": { + "api": "127.0.0.1:9090", + "nanomsg": "127.0.0.1:5550", + "peering": "127.0.0.1:4000" + } + } +} +``` + +Run `wasp-cli init` to generate a seed, and you are ready to go. + +See [Configuring wasp-cli](/smart-contracts/guide/chains_and_nodes/wasp-cli) for further information. + +## Notes about GoShimmer + +As GoShimmer runs as a standalone node, it establishes no connection to other GoShimmer nodes. Running it in this way is unusual, but fine for development purposes. Warnings about Tangle Time not synced or similar can be ignored. + +GoShimmer keeps the tangle tips inside memory only and will lose it after a restart. To recover these tips from the database, a fork was required and is to be found [here](https://github.com/lmoe/goshimmer). It is included in this package. \ No newline at end of file diff --git a/documentation/docs/guide/schema/events.mdx b/documentation/docs/guide/schema/events.mdx new file mode 100644 index 0000000000..8ea06c9848 --- /dev/null +++ b/documentation/docs/guide/schema/events.mdx @@ -0,0 +1,301 @@ +--- +keywords: +- functions +- state +- structures +- storage +- named fields +description: The smart contracts can trigger events that the user can subscribe to and that convey changes to its state. +image: /img/logo/WASP_logo_dark.png +--- + +import Tabs from "@theme/Tabs" +import TabItem from "@theme/TabItem" + +# Triggering Events + +Smart contracts do not live in a vacuum. Even though they run in a very limited +sandbox, from a larger perspective there will have to be a way for users to interact +with them. Since smart contracts are essentially event-driven, and requests run +asynchronously from the user's perspective, there is a need for triggering events by +the smart contracts themselves. Of course, it would be possible for users to +periodically call a view function to retrieve the latest state of the smart contract, +but this burdens the nodes unnecessarily. A better way is to have the smart contracts +trigger events that the user can subscribe to and that convey changes to its state. + +To support events the ISCP sandbox provides a very rudimentary interface. The function +call context exposes this interface through its `event()` function, which is passed a +completely arbitrary text string. It is up to the smart contract creator to format +this text string and it's up to the user to interpret this text string correctly. This +is error-prone, inconsistent, and means that a lot of code needs to be written both on +the smart contract side that generates these events, and on the client side that handles +these events. And with any change to the formatting of these events both ends need to be +modified to stay in sync. + +This is why the [schema tool](usage.mdx) allows you to define your own structured events. +The schema tool will generate a structure that will become part of all func call contexts. +Events can only be triggered from within a func. They will become part of the state of the +smart contract because every event is logged in the core `eventlog` contract. +Therefore, they cannot be triggered from a view. + +For each event defined in the `events` section of the schema definition file, this +events structure will contain a member function that takes the defined types of parameters +and will automatically encode the event as a consistently formatted string and pass it +to the ISCP context's `event()` function. The string consists of the name of the event, +a timestamp, and string representations of each field, all separated by vertical bars. + +Here is the `events` section that can be found in the demo `fairroulette` smart contract: + + + + + +```json +"events": { + "bet": { + "address": "Address // address of better", + "amount": "Int64 // amount of iotas to bet", + "number": "Int64 // number to bet on", + }, + "payout": { + "address": "Address // address of winner", + "amount": "Int64 // amount of iotas won", + }, + "round": { + "number": "Int64 // current betting round number" + }, + "start": { + }, + "stop": { + }, + "winner": { + "number": "Int64 // the winning number" + } +} +``` + + + + + +```yaml +events: + bet: + address: Address // address of better + amount: Int64 // amount of iotas to bet + number: Int64 // number to bet on + payout: + address: Address // address of winner + amount: Int64 // amount of iotas won + round: + number: Int64 // current betting round number + start: + stop: + winner: + number: Int64 // the winning number +``` + + + + +The schema tool will generate `events.xx` which contains the following code for the +FairRouletteEvents struct: + + + + + +```go +package fairroulette + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" + +type FairRouletteEvents struct{} + +func (e FairRouletteEvents) Bet(address wasmlib.ScAddress, amount int64, number int64) { + wasmlib.NewEventEncoder("fairroulette.bet"). + Address(address). + Int64(amount). + Int64(number). + Emit() +} + +func (e FairRouletteEvents) Payout(address wasmlib.ScAddress, amount int64) { + wasmlib.NewEventEncoder("fairroulette.payout"). + Address(address). + Int64(amount). + Emit() +} + +func (e FairRouletteEvents) Round(number int64) { + wasmlib.NewEventEncoder("fairroulette.round"). + Int64(number). + Emit() +} + +func (e FairRouletteEvents) Start() { + wasmlib.NewEventEncoder("fairroulette.start"). + Emit() +} + +func (e FairRouletteEvents) Stop() { + wasmlib.NewEventEncoder("fairroulette.stop"). + Emit() +} + +func (e FairRouletteEvents) Winner(number int64) { + wasmlib.NewEventEncoder("fairroulette.winner"). + Int64(number). + Emit() +} +``` + + + + +```rust +use wasmlib::*; + +pub struct FairRouletteEvents { +} + +impl FairRouletteEvents { + pub fn bet(&self, address: &ScAddress, amount: i64, number: i64) { + let mut encoder = EventEncoder::new("fairroulette.bet"); + encoder.address(&address); + encoder.int64(amount); + encoder.int64(number); + encoder.emit(); + } + + pub fn payout(&self, address: &ScAddress, amount: i64) { + let mut encoder = EventEncoder::new("fairroulette.payout"); + encoder.address(&address); + encoder.int64(amount); + encoder.emit(); + } + + pub fn round(&self, number: i64) { + let mut encoder = EventEncoder::new("fairroulette.round"); + encoder.int64(number); + encoder.emit(); + } + + pub fn start(&self) { + EventEncoder::new("fairroulette.start").emit(); + } + + pub fn stop(&self) { + EventEncoder::new("fairroulette.stop").emit(); + } + + pub fn winner(&self, number: i64) { + let mut encoder = EventEncoder::new("fairroulette.winner"); + encoder.int64(number); + encoder.emit(); + } +} +``` + + + + +```ts +import * as wasmlib from "wasmlib"; + +export class FairRouletteEvents { + bet(address: wasmlib.ScAddress, amount: i64, number: i64): void { + new wasmlib.EventEncoder("fairroulette.bet"). + address(address). + int64(amount). + int64(number). + emit(); + } + + payout(address: wasmlib.ScAddress, amount: i64): void { + new wasmlib.EventEncoder("fairroulette.payout"). + address(address). + int64(amount). + emit(); + } + + round(number: i64): void { + new wasmlib.EventEncoder("fairroulette.round"). + int64(number). + emit(); + } + + start(): void { + new wasmlib.EventEncoder("fairroulette.start"). + emit(); + } + + stop(): void { + new wasmlib.EventEncoder("fairroulette.stop"). + emit(); + } + + winner(number: i64): void { + new wasmlib.EventEncoder("fairroulette.winner"). + int64(number). + emit(); + } +} +``` + + + + +Notice how the generated functions use the WasmLib EventEncoder to encode the +parameters into a single string before emitting it. Here is the way in which +`fairroulette` emits the `bet` event in its smart contract code: + + + + + + +```go + f.Events.Bet(bet.Better.Address(), bet.Amount, bet.Number) +``` + + + + +```rust + f.events.bet(&bet.better.address(), bet.amount, bet.number); +``` + + + + +```ts + f.events.bet(bet.better.address(), bet.amount, bet.number); +``` + + + + +The smart contract client code can listen in to the event stream and respond to the +events it deems noteworthy. The schema tool will shortly also be generating the client +side code that properly parses these events and passes a type-safe structure to the +client code. + +In the next section we will explore how the schema tool helps to simplify +[function definitions](funcs.mdx). diff --git a/documentation/docs/guide/schema/funcdesc.mdx b/documentation/docs/guide/schema/funcdesc.mdx index 572bc2a9b5..71f56c0a7d 100644 --- a/documentation/docs/guide/schema/funcdesc.mdx +++ b/documentation/docs/guide/schema/funcdesc.mdx @@ -195,7 +195,7 @@ impl ScFuncs { ```ts -import * as wasmlib from "../wasmlib" +import * as wasmlib from "wasmlib" import * as sc from "./index"; export class DivideCall { diff --git a/documentation/docs/guide/schema/init.mdx b/documentation/docs/guide/schema/init.mdx index a87ea6601a..9d6cb2297c 100644 --- a/documentation/docs/guide/schema/init.mdx +++ b/documentation/docs/guide/schema/init.mdx @@ -151,7 +151,7 @@ pub fn func_init(ctx: &ScFuncContext, f: &InitContext) { // step by step what is happening in the code. We also unnecessarily annotate // all 'let' statements with their assignment type to improve understanding. -import * as wasmlib from "../wasmlib" +import * as wasmlib from "wasmlib" import * as sc from "./index"; // 'init' is used as a way to initialize a smart contract. It is an optional diff --git a/documentation/docs/guide/schema/state.mdx b/documentation/docs/guide/schema/state.mdx index 67d17d90eb..f032e1072b 100644 --- a/documentation/docs/guide/schema/state.mdx +++ b/documentation/docs/guide/schema/state.mdx @@ -182,5 +182,5 @@ homogenous types. In the above example both `ArrayOfMutableAddress` and `MapAddressToMutableInt64` are examples of such automatically generated proxy types. See the full `state.xx` for more details. -In the next section we will explore how the schema tool helps to simplify [function -definitions](funcs.mdx). \ No newline at end of file +In the next section we will explore how the schema tool helps to simplify [triggering +events](events.mdx). \ No newline at end of file diff --git a/documentation/docs/guide/schema/structs.mdx b/documentation/docs/guide/schema/structs.mdx index d80d6568cd..e1b44f52ca 100644 --- a/documentation/docs/guide/schema/structs.mdx +++ b/documentation/docs/guide/schema/structs.mdx @@ -220,7 +220,7 @@ impl MutableBet { ```ts -import * as wasmlib from "../wasmlib" +import * as wasmlib from "wasmlib" export class Bet { amount: i64 = 0; // bet amount @@ -448,7 +448,7 @@ impl MutableBettingState { ```ts -import * as wasmlib from "../wasmlib" +import * as wasmlib from "wasmlib" import * as sc from "./index"; export class ArrayOfImmutableBet { diff --git a/documentation/docs/guide/schema/typedefs.mdx b/documentation/docs/guide/schema/typedefs.mdx index 274f078c89..c757ea7058 100644 --- a/documentation/docs/guide/schema/typedefs.mdx +++ b/documentation/docs/guide/schema/typedefs.mdx @@ -161,7 +161,7 @@ impl ArrayOfMutableBet { ```ts -import * as wasmlib from "../wasmlib" +import * as wasmlib from "wasmlib" import * as sc from "./index"; export class ImmutableBettingRound extends ArrayOfImmutableBet { @@ -389,7 +389,7 @@ impl MutableBettingState { ```ts -import * as wasmlib from "../wasmlib" +import * as wasmlib from "wasmlib" import * as sc from "./index"; export class ArrayOfImmutableBettingRound { diff --git a/documentation/docs/guide/schema/usage.mdx b/documentation/docs/guide/schema/usage.mdx index 0fbb5e03f3..076bf53a9a 100644 --- a/documentation/docs/guide/schema/usage.mdx +++ b/documentation/docs/guide/schema/usage.mdx @@ -59,6 +59,7 @@ this: { "name": "MySmartContract", "description": "MySmartContract description", + "events": {} "structs": {}, "typedefs": {}, "state": { @@ -93,6 +94,7 @@ this: ```yaml name: MySmartContract description: MySmartContract description +events: {} structs: {} typedefs: {} state: @@ -220,7 +222,7 @@ regenerated and overwritten whenever the schema tool is run again. ```bash -asc lib.ts --binaryFile output_ts.wasm +asc lib.ts --binaryFile output_ts.wasm --lib path/to/node_modules ``` This will use the TypeScript source files in the current folder. The only file in this @@ -299,7 +301,7 @@ pub fn view_get_owner(_ctx: &ScViewContext, f: &GetOwnerContext) { ```ts -import * as wasmlib from "../wasmlib" +import * as wasmlib from "wasmlib" import * as sc from "./index"; export function funcInit(ctx: wasmlib.ScFuncContext, f: sc.InitContext): void { diff --git a/documentation/docs/guide/wasm_vm/types.mdx b/documentation/docs/guide/wasm_vm/types.mdx index b566b545af..170731f00f 100644 --- a/documentation/docs/guide/wasm_vm/types.mdx +++ b/documentation/docs/guide/wasm_vm/types.mdx @@ -15,11 +15,17 @@ direct support for the following value data types: ## Basic Value Data Types -- `Int16` - 16-bit signed integer value.allocation +- `Bool` - boolean value (0 or 1). +- `Int8` - 8-bit signed integer value. +- `Int16` - 16-bit signed integer value. - `Int32` - 32-bit signed integer value. - `Int64` - 64-bit signed integer value. - `Bytes` - An arbitrary-length byte array. - `String` - An UTF-8 encoded string value. +- `Uint8` - 8-bit unsigned integer value. +- `Uint16` - 16-bit unsigned integer value. +- `Uint32` - 32-bit unsigned integer value. +- `Uint64` - 64-bit unsigned integer value. ## IOTA Smart Contracts-specific Value Data Types @@ -40,60 +46,71 @@ data types. More detailed explanations about their specific uses can be found in all be serialized into and deserialized from a byte array. Each value data type can also be used as a key in key/value maps. -WasmLib implements [value proxies](proxies.mdx#value-proxies) for each value type, as well as a set of -[container proxies](proxies.mdx#container-proxies), [map proxies](proxies.mdx#map-proxies) that allow the value types to -be used as key and/or stored value and [array proxies](#array-proxies) for arrays of each of -these value types, and for arrays of maps. +WasmLib implements [value proxies](proxies.mdx#value-proxies) for each value type, as well +as a set of [container proxies](proxies.mdx#container-proxies), +[map proxies](proxies.mdx#map-proxies) that allow the value types to be used as key and/or +stored value and [array proxies](#array-proxies) for arrays of each of these value types, +and for arrays of maps. -Another thing to consider is that some data provided by the host is mutable, -whereas other data may be immutable. To facilitate this distinction, each proxy type comes -in two flavors that reflect this, and makes sure the data can only be used as intended. The -rule is that from an immutable container proxy you can only derive immutable container and -value proxies. The referenced data can never be changed through immutable proxies. +Another thing to consider is that some data provided by the host is mutable, whereas other +data may be immutable. To facilitate this distinction, each proxy type comes in two +flavors that reflect this, and makes sure that the data can only be used as intended. +The rule is that from an immutable container proxy you can only derive immutable container +and value proxies. The referenced data can never be changed through immutable proxies. Separating these constraints for types into separate proxy types allows the use of compile-time type-checking to enforce these constraints. To guard against client code that tries to bypass them, the IOTA Smart Contracts sandbox will also check these constraints at runtime on the host. ## Full Matrix of WasmLib Types (excluding array proxies) -| ISCP type | WasmLib type | Mutable proxy | Immutable proxy | -| ---------- | ---------------- | ----------------------- | ------------------------- | -| Bytes | *byte array* | ScMutable**Bytes** | ScImmutable**Bytes** | -| Int16 | *16-bit integer* | ScMutable**Int16** | ScImmutable**Int16** | -| Int32 | *32-bit integer* | ScMutable**Int32** | ScImmutable**Int32** | -| Int64 | *64-bit integer* | ScMutable**Int64** | ScImmutable**Int64** | -| String | *UTF-8 string* | ScMutable**String** | ScImmutable**String** | -| | | | | -| Address | Sc**Address** | ScMutable**Address** | ScImmutable**Address** | -| AgentId | Sc**AgentId** | ScMutable**AgentId** | ScImmutable**AgentId** | -| ChainId | Sc**ChainId** | ScMutable**ChainId** | ScImmutable**ChainId** | -| Color | Sc**Color** | ScMutable**Color** | ScImmutable**Color** | -| ContractId | Sc**ContractId** | ScMutable**ContractId** | ScImmutable**ContractId** | -| HName | Sc**HName** | ScMutable**HName** | ScImmutable**HName** | -| Hash | Sc**Hash** | ScMutable**Hash** | ScImmutable**Hash** | -| Map | Sc**Map** | ScMutable**Map** | ScImmutable**Map** | -| RequestId | Sc**RequestId** | ScMutable**RequestId** | ScImmutable**RequestId** | +| ISCP type | WasmLib type | Mutable proxy | Immutable proxy | +| ---------- | ----------------- | ----------------------- | ------------------------- | +| Bool | *boolean* | ScMutable**Bool** | ScImmutable**Bool** | +| Bytes | *byte array* | ScMutable**Bytes** | ScImmutable**Bytes** | +| Int8 | *8-bit signed* | ScMutable**Int8** | ScImmutable**Int8** | +| Int16 | *16-bit signed* | ScMutable**Int16** | ScImmutable**Int16** | +| Int32 | *32-bit signed* | ScMutable**Int32** | ScImmutable**Int32** | +| Int64 | *64-bit signed* | ScMutable**Int64** | ScImmutable**Int64** | +| String | *UTF-8 string* | ScMutable**String** | ScImmutable**String** | +| Uint8 | *8-bit unsigned* | ScMutable**Uint8** | ScImmutable**Uint8** | +| Uint16 | *16-bit unsigned* | ScMutable**Uint16** | ScImmutable**Uint16** | +| Uint32 | *32-bit unsigned* | ScMutable**Uint32** | ScImmutable**Uint32** | +| Uint64 | *64-bit unsigned* | ScMutable**Uint64** | ScImmutable**Uint64** | +| | | | | +| Address | Sc**Address** | ScMutable**Address** | ScImmutable**Address** | +| AgentId | Sc**AgentId** | ScMutable**AgentId** | ScImmutable**AgentId** | +| ChainId | Sc**ChainId** | ScMutable**ChainId** | ScImmutable**ChainId** | +| Color | Sc**Color** | ScMutable**Color** | ScImmutable**Color** | +| Hname | Sc**Hname** | ScMutable**Hname** | ScImmutable**Hname** | +| Hash | Sc**Hash** | ScMutable**Hash** | ScImmutable**Hash** | +| Map | Sc**Map** | ScMutable**Map** | ScImmutable**Map** | +| RequestId | Sc**RequestId** | ScMutable**RequestId** | ScImmutable**RequestId** | -The consistent naming makes it easy to remember the type names and how Bytes, Int16, -Int32, Int64, and String are the odd ones out. They are implemented in WasmLib by the +The consistent naming makes it easy to remember the type names. Bool, Bytes, String, +and the integer types are the odd ones out. They are implemented in WasmLib by the closest equivalents in the chosen implementation programming language. ## Full Matrix of WasmLib Types for Array Proxies | ISCP type | Mutable array proxy | Immutable array proxy | | ---------- | ---------------------------- | ------------------------------ | +| Bool | ScMutable**Bool**Array | ScImmutable**Bool**Array | | Bytes | ScMutable**Bytes**Array | ScImmutable**Bytes**Array | +| Int8 | ScMutable**Int8**Array | ScImmutable**Int8**Array | | Int16 | ScMutable**Int16**Array | ScImmutable**Int16**Array | | Int32 | ScMutable**Int32**Array | ScImmutable**Int32**Array | | Int64 | ScMutable**Int64**Array | ScImmutable**Int64**Array | | String | ScMutable**String**Array | ScImmutable**String**Array | +| Uint8 | ScMutable**Uint8**Array | ScImmutable**Uint8**Array | +| Uint16 | ScMutable**Uint16**Array | ScImmutable**Uint16**Array | +| Uint32 | ScMutable**Uint32**Array | ScImmutable**Uint32**Array | +| Uint64 | ScMutable**Uint64**Array | ScImmutable**Uint64**Array | | | | | | Address | ScMutable**Address**Array | ScImmutable**Address**Array | | AgentId | ScMutable**AgentId**Array | ScImmutable**AgentId**Array | | ChainId | ScMutable**ChainId**Array | ScImmutable**ChainId**Array | | Color | ScMutable**Color**Array | ScImmutable**Color**Array | -| ContractId | ScMutable**ContractId**Array | ScImmutable**ContractId**Array | -| HName | ScMutable**HName**Array | ScImmutable**HName**Array | +| Hname | ScMutable**Hname**Array | ScImmutable**Hname**Array | | Hash | ScMutable**Hash**Array | ScImmutable**Hash**Array | | Map | ScMutable**Map**Array | ScImmutable**Map**Array | | RequestId | ScMutable**RequestId**Array | ScImmutable**RequestId**Array | diff --git a/documentation/sidebars.js b/documentation/sidebars.js index 61eb907815..821c6b897d 100644 --- a/documentation/sidebars.js +++ b/documentation/sidebars.js @@ -216,8 +216,8 @@ module.exports = { }, { type: 'doc', - label: 'Using Docker', - id: 'misc/docker', + label: 'Using Docker (Standalone)', + id: 'guide/chains_and_nodes/docker_standalone', }, { type: 'doc', @@ -300,6 +300,11 @@ module.exports = { label: 'Smart Contract State', id: 'guide/schema/state', }, + { + type: 'doc', + label: 'Triggering Events', + id: 'guide/schema/events', + }, { type: 'doc', label: 'Function Definitions', @@ -427,6 +432,17 @@ module.exports = { }, ] }, + { + type: 'category', + label: 'Development tools', + items: [ + { + type: 'doc', + label: 'Preconfigured Development Docker setup', + id: 'guide/development_tools/docker_preconfigured', + }, + ] + }, { type: 'doc', label: 'Contribute', diff --git a/documentation/docs/misc/accounts.md b/documentation/temp/misc/accounts.md similarity index 100% rename from documentation/docs/misc/accounts.md rename to documentation/temp/misc/accounts.md diff --git a/documentation/docs/misc/coretypes.md b/documentation/temp/misc/coretypes.md similarity index 100% rename from documentation/docs/misc/coretypes.md rename to documentation/temp/misc/coretypes.md diff --git a/documentation/docs/misc/deploy.md b/documentation/temp/misc/deploy.md similarity index 100% rename from documentation/docs/misc/deploy.md rename to documentation/temp/misc/deploy.md diff --git a/documentation/docs/misc/install.md b/documentation/temp/misc/install.md similarity index 100% rename from documentation/docs/misc/install.md rename to documentation/temp/misc/install.md diff --git a/documentation/docs/misc/invoking.md b/documentation/temp/misc/invoking.md similarity index 100% rename from documentation/docs/misc/invoking.md rename to documentation/temp/misc/invoking.md diff --git a/documentation/docs/misc/publisher.md b/documentation/temp/misc/publisher.md similarity index 100% rename from documentation/docs/misc/publisher.md rename to documentation/temp/misc/publisher.md diff --git a/documentation/docs/misc/runwasp.md b/documentation/temp/misc/runwasp.md similarity index 100% rename from documentation/docs/misc/runwasp.md rename to documentation/temp/misc/runwasp.md diff --git a/documentation/docs/misc/utxo.md b/documentation/temp/misc/utxo.md similarity index 100% rename from documentation/docs/misc/utxo.md rename to documentation/temp/misc/utxo.md diff --git a/documentation/docs/profiling.md b/documentation/temp/profiling.md similarity index 100% rename from documentation/docs/profiling.md rename to documentation/temp/profiling.md diff --git a/documentation/docs/rfc/prevent-mev.md b/documentation/temp/rfc/prevent-mev.md similarity index 100% rename from documentation/docs/rfc/prevent-mev.md rename to documentation/temp/rfc/prevent-mev.md diff --git a/documentation/docs/rfc/replay-off-ledger.md b/documentation/temp/rfc/replay-off-ledger.md similarity index 100% rename from documentation/docs/rfc/replay-off-ledger.md rename to documentation/temp/rfc/replay-off-ledger.md diff --git a/documentation/docs/tutorial/01.md b/documentation/temp/tutorial/01.md similarity index 100% rename from documentation/docs/tutorial/01.md rename to documentation/temp/tutorial/01.md diff --git a/documentation/docs/tutorial/02.md b/documentation/temp/tutorial/02.md similarity index 100% rename from documentation/docs/tutorial/02.md rename to documentation/temp/tutorial/02.md diff --git a/documentation/docs/tutorial/03.md b/documentation/temp/tutorial/03.md similarity index 100% rename from documentation/docs/tutorial/03.md rename to documentation/temp/tutorial/03.md diff --git a/documentation/docs/tutorial/04.md b/documentation/temp/tutorial/04.md similarity index 100% rename from documentation/docs/tutorial/04.md rename to documentation/temp/tutorial/04.md diff --git a/documentation/docs/tutorial/05.md b/documentation/temp/tutorial/05.md similarity index 100% rename from documentation/docs/tutorial/05.md rename to documentation/temp/tutorial/05.md diff --git a/documentation/docs/tutorial/06.md b/documentation/temp/tutorial/06.md similarity index 100% rename from documentation/docs/tutorial/06.md rename to documentation/temp/tutorial/06.md diff --git a/documentation/docs/tutorial/07.md b/documentation/temp/tutorial/07.md similarity index 100% rename from documentation/docs/tutorial/07.md rename to documentation/temp/tutorial/07.md diff --git a/documentation/docs/tutorial/08.md b/documentation/temp/tutorial/08.md similarity index 100% rename from documentation/docs/tutorial/08.md rename to documentation/temp/tutorial/08.md diff --git a/documentation/docs/tutorial/09.md b/documentation/temp/tutorial/09.md similarity index 100% rename from documentation/docs/tutorial/09.md rename to documentation/temp/tutorial/09.md diff --git a/documentation/docs/tutorial/10.md b/documentation/temp/tutorial/10.md similarity index 100% rename from documentation/docs/tutorial/10.md rename to documentation/temp/tutorial/10.md diff --git a/documentation/docs/tutorial/11.md b/documentation/temp/tutorial/11.md similarity index 100% rename from documentation/docs/tutorial/11.md rename to documentation/temp/tutorial/11.md diff --git a/documentation/docs/tutorial/12.md b/documentation/temp/tutorial/12.md similarity index 100% rename from documentation/docs/tutorial/12.md rename to documentation/temp/tutorial/12.md diff --git a/documentation/docs/tutorial/readme.md b/documentation/temp/tutorial/readme.md similarity index 100% rename from documentation/docs/tutorial/readme.md rename to documentation/temp/tutorial/readme.md diff --git a/documentation/docs/welcome.md b/documentation/temp/welcome.md similarity index 100% rename from documentation/docs/welcome.md rename to documentation/temp/welcome.md diff --git a/documentation/tutorial-examples/test/example_tutorial_bg.wasm b/documentation/tutorial-examples/test/example_tutorial_bg.wasm index 0fdb6aa458..ad488b5f96 100644 Binary files a/documentation/tutorial-examples/test/example_tutorial_bg.wasm and b/documentation/tutorial-examples/test/example_tutorial_bg.wasm differ diff --git a/go.mod b/go.mod index 06bfcd5faf..669a802d98 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,9 @@ 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.21.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/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 @@ -34,7 +36,6 @@ require ( go.uber.org/zap v1.16.0 golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 - gopkg.in/eapache/channels.v1 v1.1.0 gopkg.in/yaml.v2 v2.4.0 nhooyr.io/websocket v1.8.7 ) diff --git a/go.sum b/go.sum index c6ebbb0c29..6ba6d789cd 100644 --- a/go.sum +++ b/go.sum @@ -153,6 +153,8 @@ github.com/bygui86/multi-profile/v2 v2.1.0 h1:x/jPqeL/6hJqLXoDI/H5zLPsSFbDR6IEbr github.com/bygui86/multi-profile/v2 v2.1.0/go.mod h1:f4qCZiQo1nnJdwbPoADUtdDXg3hhnpfgZ9iq3/kW4BA= github.com/bytecodealliance/wasmtime-go v0.21.0 h1:8C6fNmpfzF6QQ9h0PCvGaYORhtgMvANCumafDPDmBSU= 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/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= @@ -258,7 +260,6 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= @@ -1289,6 +1290,10 @@ github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73 github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/second-state/WasmEdge-go v0.8.2 h1:dD5+ZKY9Vr+Ye5F9VZGP/WP2MnXfORQocUxXQvXUVE0= +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/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= @@ -1423,6 +1428,8 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= +github.com/wasmerio/wasmer-go v1.0.4 h1:MnqHoOGfiQ8MMq2RF6wyCeebKOe84G88h5yv+vmxJgs= +github.com/wasmerio/wasmer-go v1.0.4/go.mod h1:0gzVdSfg6pysA6QVp6iVRPTagC6Wq9pOE8J86WKb2Fk= github.com/weaveworks/common v0.0.0-20200512154658-384f10054ec5/go.mod h1:c98fKi5B9u8OsKGiWHLRKus6ToQ1Tubeow44ECO1uxY= github.com/weaveworks/promrus v1.2.0/go.mod h1:SaE82+OJ91yqjrE1rsvBWVzNZKcHYFtMUyS1+Ogs/KA= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= @@ -1916,8 +1923,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/eapache/channels.v1 v1.1.0 h1:5bGAyKKvyCTWjSj7mhefG6Lc68VyN4MH1v8/7OoeeB4= -gopkg.in/eapache/channels.v1 v1.1.0/go.mod h1:BHIBujSvu9yMTrTYbTCjDD43gUhtmaOtTWDe7sTv1js= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= diff --git a/packages/chain/chain.go b/packages/chain/chain.go index 1936660d7b..ef7b0a1f9f 100644 --- a/packages/chain/chain.go +++ b/packages/chain/chain.go @@ -7,8 +7,6 @@ import ( "fmt" "time" - "github.com/iotaledger/wasp/packages/iscp/request" - "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/logger" @@ -16,7 +14,7 @@ import ( "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/coreutil" - "github.com/iotaledger/wasp/packages/peering" + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" "github.com/iotaledger/wasp/packages/state" "github.com/iotaledger/wasp/packages/tcrypto" "github.com/iotaledger/wasp/packages/util/ready" @@ -26,21 +24,27 @@ import ( type ChainCore interface { ID() *iscp.ChainID GetCommitteeInfo() *CommitteeInfo - ReceiveMessage(interface{}) - Events() ChainEvents + StateCandidateToStateManager(state.VirtualStateAccess, ledgerstate.OutputID) + TriggerChainTransition(*ChainTransitionEventData) Processors() *processors.Cache GlobalStateSync() coreutil.ChainStateSync GetStateReader() state.OptimisticStateReader Log() *logger.Logger + + // Most of these methods are made public for mocking in tests + EnqueueDismissChain(reason string) // This one should really be public + EnqueueLedgerState(chainOutput *ledgerstate.AliasOutput, timestamp time.Time) + EnqueueOffLedgerRequestMsg(msg *messages.OffLedgerRequestMsgIn) + EnqueueRequestAckMsg(msg *messages.RequestAckMsgIn) + EnqueueMissingRequestIDsMsg(msg *messages.MissingRequestIDsMsgIn) + EnqueueMissingRequestMsg(msg *messages.MissingRequestMsg) + EnqueueTimerTick(tick int) } // ChainEntry interface to access chain from the chain registry side type ChainEntry interface { ReceiveTransaction(*ledgerstate.Transaction) - ReceiveInclusionState(ledgerstate.TransactionID, ledgerstate.InclusionState) ReceiveState(stateOutput *ledgerstate.AliasOutput, timestamp time.Time) - ReceiveOutput(output ledgerstate.Output) - ReceiveOffLedgerRequest(req *request.OffLedger, senderNetID string) Dismiss(reason string) IsDismissed() bool @@ -49,18 +53,19 @@ type ChainEntry interface { // ChainRequests is an interface to query status of the request type ChainRequests interface { GetRequestProcessingStatus(id iscp.RequestID) RequestProcessingStatus - EventRequestProcessed() *events.Event + AttachToRequestProcessed(func(iscp.RequestID)) (attachID *events.Closure) + DetachFromRequestProcessed(attachID *events.Closure) } -type ChainEvents interface { - RequestProcessed() *events.Event - ChainTransition() *events.Event +type ChainMetrics interface { + GetNodeConnectionMetrics() nodeconnmetrics.NodeConnectionMessagesMetrics } type Chain interface { ChainCore ChainRequests ChainEntry + ChainMetrics } // Committee is ordered (indexed 0..size-1) list of peers which run the consensus @@ -70,12 +75,9 @@ type Committee interface { Quorum() uint16 OwnPeerIndex() uint16 DKShare() *tcrypto.DKShare - SendMsg(targetPeerIndex uint16, msgType byte, msgData []byte) error - SendMsgToPeers(msgType byte, msgData []byte, ts int64, except ...uint16) IsAlivePeer(peerIndex uint16) bool QuorumIsAlive(quorum ...uint16) bool PeerStatus() []*PeerStatus - Attach(chain ChainCore) IsReady() bool Close() RunACSConsensus(value []byte, sessionID uint64, stateIndex uint32, callback func(sessionID uint64, acs [][]byte)) @@ -83,35 +85,76 @@ type Committee interface { GetRandomValidators(upToN int) []string } +type ( + NodeConnectionHandleTransactionFun func(*ledgerstate.Transaction) + NodeConnectionHandleInclusionStateFun func(ledgerstate.TransactionID, ledgerstate.InclusionState) + NodeConnectionHandleOutputFun func(ledgerstate.Output) + NodeConnectionHandleUnspentAliasOutputFun func(*ledgerstate.AliasOutput, time.Time) +) + type NodeConnection interface { - PullBacklog(addr *ledgerstate.AliasAddress) + 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) - PullConfirmedTransaction(addr ledgerstate.Address, txid ledgerstate.TransactionID) 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) + DetachFromUnspentAliasOutputReceived(*ledgerstate.AliasAddress) + Close() +} + +type ChainNodeConnection interface { + AttachToTransactionReceived(NodeConnectionHandleTransactionFun) + 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() + DetachFromUnspentAliasOutputReceived() + Close() } type StateManager interface { Ready() *ready.Ready - EventGetBlockMsg(msg *messages.GetBlockMsg) - EventBlockMsg(msg *messages.BlockMsg) - EventStateMsg(msg *messages.StateMsg) - EventOutputMsg(msg ledgerstate.Output) - EventStateCandidateMsg(msg *messages.StateCandidateMsg) - EventTimerMsg(msg messages.TimerTick) + EnqueueGetBlockMsg(msg *messages.GetBlockMsgIn) + EnqueueBlockMsg(msg *messages.BlockMsgIn) + EnqueueStateMsg(msg *messages.StateMsg) + EnqueueOutputMsg(msg ledgerstate.Output) + EnqueueStateCandidateMsg(state.VirtualStateAccess, ledgerstate.OutputID) + EnqueueTimerMsg(msg messages.TimerTick) GetStatusSnapshot() *SyncInfo Close() } type Consensus interface { - EventStateTransitionMsg(*messages.StateTransitionMsg) - EventSignedResultMsg(*messages.SignedResultMsg) - EventSignedResultAckMsg(*messages.SignedResultAckMsg) - EventInclusionsStateMsg(*messages.InclusionStateMsg) - EventAsynchronousCommonSubsetMsg(msg *messages.AsynchronousCommonSubsetMsg) - EventVMResultMsg(msg *messages.VMResultMsg) - EventTimerMsg(messages.TimerTick) + EnqueueStateTransitionMsg(state.VirtualStateAccess, *ledgerstate.AliasOutput, time.Time) + EnqueueSignedResultMsg(*messages.SignedResultMsgIn) + EnqueueSignedResultAckMsg(*messages.SignedResultAckMsgIn) + EnqueueInclusionsStateMsg(ledgerstate.TransactionID, ledgerstate.InclusionState) + EnqueueAsynchronousCommonSubsetMsg(msg *messages.AsynchronousCommonSubsetMsg) + EnqueueVMResultMsg(msg *messages.VMResultMsg) + EnqueueTimerMsg(messages.TimerTick) IsReady() bool Close() GetStatusSnapshot() *ConsensusInfo @@ -134,7 +177,6 @@ type Mempool interface { type AsynchronousCommonSubsetRunner interface { RunACSConsensus(value []byte, sessionID uint64, stateIndex uint32, callback func(sessionID uint64, acs [][]byte)) - TryHandleMessage(recv *peering.RecvEvent) bool Close() } @@ -206,3 +248,10 @@ const ( // TimerTickPeriod time tick for consensus and state manager objects TimerTickPeriod = 100 * time.Millisecond ) + +const ( + PeerMsgTypeMissingRequestIDs = iota + PeerMsgTypeMissingRequest + PeerMsgTypeOffLedgerRequest + PeerMsgTypeRequestAck +) diff --git a/packages/chain/chainimpl/chainimpl.go b/packages/chain/chainimpl/chainimpl.go index 63b7e2aab2..c1a72b1686 100644 --- a/packages/chain/chainimpl/chainimpl.go +++ b/packages/chain/chainimpl/chainimpl.go @@ -4,23 +4,17 @@ package chainimpl import ( - "bytes" "sync" "time" - "github.com/iotaledger/goshimmer/packages/ledgerstate" - txstream "github.com/iotaledger/goshimmer/packages/txstream/client" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/kvstore" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/chain" - "github.com/iotaledger/wasp/packages/chain/committee" - "github.com/iotaledger/wasp/packages/chain/consensus" "github.com/iotaledger/wasp/packages/chain/mempool" "github.com/iotaledger/wasp/packages/chain/messages" "github.com/iotaledger/wasp/packages/chain/nodeconnimpl" "github.com/iotaledger/wasp/packages/chain/statemgr" - "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/coreutil" "github.com/iotaledger/wasp/packages/kv" @@ -30,52 +24,61 @@ import ( "github.com/iotaledger/wasp/packages/publisher" "github.com/iotaledger/wasp/packages/registry" "github.com/iotaledger/wasp/packages/state" - "github.com/iotaledger/wasp/packages/util" + "github.com/iotaledger/wasp/packages/util/pipe" "github.com/iotaledger/wasp/packages/vm/core/blocklog" "github.com/iotaledger/wasp/packages/vm/processors" "go.uber.org/atomic" - "golang.org/x/xerrors" - "gopkg.in/eapache/channels.v1" ) +const maxMsgBuffer = 1000 + var ( _ chain.Chain = &chainObj{} _ chain.ChainCore = &chainObj{} _ chain.ChainEntry = &chainObj{} _ chain.ChainRequests = &chainObj{} - _ chain.ChainEvents = &chainObj{} + _ chain.ChainMetrics = &chainObj{} ) type chainObj struct { - committee atomic.Value - mempool chain.Mempool - mempoolLastCleanedIndex uint32 - dismissed atomic.Bool - dismissOnce sync.Once - chainID *iscp.ChainID - chainStateSync coreutil.ChainStateSync - stateReader state.OptimisticStateReader - procset *processors.Cache - chMsg *channels.InfiniteChannel - stateMgr chain.StateManager - consensus chain.Consensus - log *logger.Logger - nodeConn chain.NodeConnection - db kvstore.KVStore - peerNetworkConfig registry.PeerNetworkConfigProvider - netProvider peering.NetworkProvider - dksProvider registry.DKShareRegistryProvider - committeeRegistry registry.CommitteeRegistryProvider - blobProvider registry.BlobCache - eventRequestProcessed *events.Event - eventChainTransition *events.Event - peers *peering.PeerDomainProvider - offLedgerReqsAcksMutex sync.RWMutex - offLedgerReqsAcks map[iscp.RequestID][]string - offledgerBroadcastUpToNPeers int - offledgerBroadcastInterval time.Duration - pullMissingRequestsFromCommittee bool - chainMetrics metrics.ChainMetrics + committee atomic.Value + mempool chain.Mempool + mempoolLastCleanedIndex uint32 + dismissed atomic.Bool + dismissOnce sync.Once + chainID *iscp.ChainID + chainStateSync coreutil.ChainStateSync + stateReader state.OptimisticStateReader + procset *processors.Cache + stateMgr chain.StateManager + consensus chain.Consensus + 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 + eventChainTransitionClosure *events.Closure + receiveChainPeerMessagesAttachID interface{} + detachFromCommitteePeerMessagesFun func() + chainPeers peering.PeerDomainProvider + offLedgerReqsAcksMutex sync.RWMutex + offLedgerReqsAcks map[iscp.RequestID][]string + offledgerBroadcastUpToNPeers int + offledgerBroadcastInterval time.Duration + pullMissingRequestsFromCommittee bool + chainMetrics metrics.ChainMetrics + dismissChainMsgPipe pipe.Pipe + stateMsgPipe pipe.Pipe + offLedgerRequestPeerMsgPipe pipe.Pipe + requestAckPeerMsgPipe pipe.Pipe + missingRequestIDsPeerMsgPipe pipe.Pipe + missingRequestPeerMsgPipe pipe.Pipe + timerTickMsgPipe pipe.Pipe } type committeeStruct struct { @@ -86,7 +89,7 @@ type committeeStruct struct { func NewChain( chainID *iscp.ChainID, log *logger.Logger, - txstreamClient *txstream.Client, + nc chain.NodeConnection, peerNetConfig registry.PeerNetworkConfigProvider, db kvstore.KVStore, netProvider peering.NetworkProvider, @@ -106,10 +109,9 @@ func NewChain( ret := &chainObj{ mempool: mempool.New(state.NewOptimisticStateReader(db, chainStateSync), blobProvider, chainLog, chainMetrics), procset: processors.MustNew(processorConfig), - chMsg: channels.NewInfiniteChannel(), chainID: chainID, log: chainLog, - nodeConn: nodeconnimpl.New(txstreamClient, chainLog), + nodeConn: nodeconnimpl.NewChainNodeConnection(chainID, nc, chainLog), db: db, chainStateSync: chainStateSync, stateReader: state.NewOptimisticStateReader(db, chainStateSync), @@ -129,152 +131,93 @@ func NewChain( offledgerBroadcastInterval: offledgerBroadcastInterval, pullMissingRequestsFromCommittee: pullMissingRequestsFromCommittee, chainMetrics: chainMetrics, + dismissChainMsgPipe: pipe.NewLimitInfinitePipe(1), + stateMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + offLedgerRequestPeerMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + requestAckPeerMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + missingRequestIDsPeerMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + missingRequestPeerMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + timerTickMsgPipe: pipe.NewLimitInfinitePipe(1), } ret.committee.Store(&committeeStruct{}) - ret.eventChainTransition.Attach(events.NewClosure(ret.processChainTransition)) - peers, err := netProvider.PeerDomain(peerNetConfig.Neighbors()) + var err error + ret.chainPeers, err = netProvider.PeerDomain(chainID.Array(), peerNetConfig.Neighbors()) if err != nil { log.Errorf("NewChain: %v", err) return nil } - ret.stateMgr = statemgr.New(db, ret, peers, ret.nodeConn) - ret.peers = &peers - var peeringID peering.PeeringID = ret.chainID.Array() - peers.Attach(&peeringID, func(recv *peering.RecvEvent) { - ret.ReceiveMessage(recv.Msg) - }) - go func() { - for msg := range ret.chMsg.Out() { - ret.dispatchMessage(msg) - } - }() + ret.stateMgr = statemgr.New(db, ret, ret.chainPeers, ret.nodeConn, chainMetrics) + + ret.eventChainTransitionClosure = events.NewClosure(ret.processChainTransition) + ret.eventChainTransition.Attach(ret.eventChainTransitionClosure) + ret.nodeConn.AttachToTransactionReceived(ret.ReceiveTransaction) + ret.nodeConn.AttachToUnspentAliasOutputReceived(ret.ReceiveState) + ret.receiveChainPeerMessagesAttachID = ret.chainPeers.Attach(peering.PeerMessageReceiverChain, ret.receiveChainPeerMessages) + go ret.recvLoop() ret.startTimer() return ret } -func (c *chainObj) dispatchMessage(msg interface{}) { - switch msgt := msg.(type) { - case *peering.PeerMessage: - c.processPeerMessage(msgt) - case *messages.DismissChainMsg: - c.Dismiss(msgt.Reason) - case *messages.StateTransitionMsg: - if c.consensus != nil { - c.consensus.EventStateTransitionMsg(msgt) - } - case *messages.StateCandidateMsg: - c.stateMgr.EventStateCandidateMsg(msgt) - case *messages.InclusionStateMsg: - if c.consensus != nil { - c.consensus.EventInclusionsStateMsg(msgt) - } - case *messages.StateMsg: - c.processStateMessage(msgt) - case *messages.VMResultMsg: - // VM finished working - if c.consensus != nil { - c.consensus.EventVMResultMsg(msgt) - } - case *messages.AsynchronousCommonSubsetMsg: - if c.consensus != nil { - c.consensus.EventAsynchronousCommonSubsetMsg(msgt) - } - case messages.TimerTick: - if msgt%2 == 0 { - c.stateMgr.EventTimerMsg(msgt / 2) - } else if c.consensus != nil { - c.consensus.EventTimerMsg(msgt / 2) - } - if msgt%40 == 0 { - stats := c.mempool.Info() - c.log.Debugf("mempool total = %d, ready = %d, in = %d, out = %d", stats.TotalPool, stats.ReadyCounter, stats.InPoolCounter, stats.OutPoolCounter) +func (c *chainObj) startTimer() { + go func() { + c.stateMgr.Ready().MustWait() + tick := 0 + for !c.IsDismissed() { + c.EnqueueTimerTick(tick) + tick++ + time.Sleep(chain.TimerTickPeriod) } - } + }() } -//nolint:funlen -func (c *chainObj) processPeerMessage(msg *peering.PeerMessage) { - rdr := bytes.NewReader(msg.MsgData) - - switch msg.MsgType { - case messages.MsgGetBlock: - msgt := &messages.GetBlockMsg{} - if err := msgt.Read(rdr); err != nil { - c.log.Error(err) - return - } - msgt.SenderNetID = msg.SenderNetID - c.stateMgr.EventGetBlockMsg(msgt) - - case messages.MsgBlock: - msgt := &messages.BlockMsg{} - if err := msgt.Read(rdr); err != nil { - c.log.Error(err) - return - } - msgt.SenderNetID = msg.SenderNetID - c.stateMgr.EventBlockMsg(msgt) +func (c *chainObj) receiveCommitteePeerMessages(peerMsg *peering.PeerMessageGroupIn) { + if peerMsg.MsgType != chain.PeerMsgTypeMissingRequestIDs { + c.log.Warnf("Wrong type of chain message (with committee peering ID): %v, ignoring it", peerMsg.MsgType) + return + } + msg, err := messages.NewMissingRequestIDsMsg(peerMsg.MsgData) + if err != nil { + c.log.Error(err) + return + } + c.EnqueueMissingRequestIDsMsg(&messages.MissingRequestIDsMsgIn{ + MissingRequestIDsMsg: *msg, + SenderNetID: peerMsg.SenderNetID, + }) +} - case messages.MsgSignedResult: - msgt := &messages.SignedResultMsg{} - if err := msgt.Read(rdr); err != nil { - c.log.Error(err) - return - } - msgt.SenderIndex = msg.SenderIndex - if c.consensus != nil { - c.consensus.EventSignedResultMsg(msgt) - } - case messages.MsgSignedResultAck: - if c.consensus == nil { - return - } - msgt := &messages.SignedResultAckMsg{} - if err := msgt.Read(rdr); err != nil { - c.log.Error(err) - return - } - msgt.SenderIndex = msg.SenderIndex - c.consensus.EventSignedResultAckMsg(msgt) - case messages.MsgOffLedgerRequest: - msgt, err := messages.OffLedgerRequestMsgFromBytes(msg.MsgData) +func (c *chainObj) receiveChainPeerMessages(peerMsg *peering.PeerMessageIn) { + switch peerMsg.MsgType { + case chain.PeerMsgTypeOffLedgerRequest: + msg, err := messages.NewOffLedgerRequestMsg(peerMsg.MsgData) if err != nil { c.log.Error(err) return } - c.ReceiveOffLedgerRequest(msgt.Req, msg.SenderNetID) - case messages.MsgRequestAck: - msgt, err := messages.RequestAckMsgFromBytes(msg.MsgData) - if err != nil { - c.log.Error(err) - return - } - c.ReceiveRequestAckMessage(msgt.ReqID, msg.SenderNetID) - case messages.MsgMissingRequestIDs: - if !c.pullMissingRequestsFromCommittee { - return - } - msgt, err := messages.MissingRequestIDsMsgFromBytes(msg.MsgData) + c.EnqueueOffLedgerRequestMsg(&messages.OffLedgerRequestMsgIn{ + OffLedgerRequestMsg: *msg, + SenderNetID: peerMsg.SenderNetID, + }) + case chain.PeerMsgTypeRequestAck: + msg, err := messages.NewRequestAckMsg(peerMsg.MsgData) if err != nil { c.log.Error(err) return } - c.SendMissingRequestsToPeer(msgt, msg.SenderNetID) - case messages.MsgMissingRequest: - if !c.pullMissingRequestsFromCommittee { - return - } - msgt, err := messages.MissingRequestMsgFromBytes(msg.MsgData) + c.EnqueueRequestAckMsg(&messages.RequestAckMsgIn{ + RequestAckMsg: *msg, + SenderNetID: peerMsg.SenderNetID, + }) + case chain.PeerMsgTypeMissingRequest: + msg, err := messages.NewMissingRequestMsg(peerMsg.MsgData) if err != nil { c.log.Error(err) return } - if c.consensus.ShouldReceiveMissingRequest(msgt.Request) { - c.mempool.ReceiveRequest(msgt.Request) - } + c.EnqueueMissingRequestMsg(msg) default: - c.log.Errorf("processPeerMessage: wrong msg type") + c.log.Warnf("Wrong type of chain message (with chain peering ID): %v, ignoring it", peerMsg.MsgType) } } @@ -324,12 +267,11 @@ func (c *chainObj) processChainTransition(msg *chain.ChainTransitionEventData) { chain.LogGovernanceTransition(msg, c.log) chain.PublishGovernanceTransition(msg.ChainOutput) } - // send to consensus - c.ReceiveMessage(&messages.StateTransitionMsg{ - State: msg.VirtualState, - StateOutput: msg.ChainOutput, - StateTimestamp: msg.OutputTimestamp, - }) + if c.consensus == nil { + c.log.Warnf("processChainTransition: skipping notifying consensus as it is not initiated") + } else { + c.consensus.EnqueueStateTransitionMsg(msg.VirtualState, msg.ChainOutput, msg.OutputTimestamp) + } c.log.Debugf("processChainTransition completed: state index: %d, state hash: %s", stateIndex, msg.VirtualState.StateCommitment().String()) } @@ -354,118 +296,6 @@ func (c *chainObj) publishNewBlockEvents(blockIndex uint32) { }() } -// processStateMessage processes the only chain output which exists on the chain's address -// If necessary, it creates/changes/rotates committee object -func (c *chainObj) processStateMessage(msg *messages.StateMsg) { - sh, err := hashing.HashValueFromBytes(msg.ChainOutput.GetStateData()) - if err != nil { - c.log.Error(xerrors.Errorf("parsing state hash: %w", err)) - return - } - c.log.Debugf("processStateMessage. stateIndex: %d, stateHash: %s, stateAddr: %s, state transition: %v", - msg.ChainOutput.GetStateIndex(), sh.String(), - msg.ChainOutput.GetStateAddress().Base58(), !msg.ChainOutput.GetIsGovernanceUpdated(), - ) - cmt := c.getCommittee() - - if cmt != nil { - err = c.rotateCommitteeIfNeeded(msg.ChainOutput, cmt) - } else { - err = c.createCommitteeIfNeeded(msg.ChainOutput) - } - if err != nil { - c.log.Errorf("processStateMessage: %v", err) - return - } - c.stateMgr.EventStateMsg(msg) -} - -func (c *chainObj) rotateCommitteeIfNeeded(anchorOutput *ledgerstate.AliasOutput, currentCmt chain.Committee) error { - if currentCmt.Address().Equals(anchorOutput.GetStateAddress()) { - // nothing changed. no rotation - return nil - } - // address changed - if !anchorOutput.GetIsGovernanceUpdated() { - return xerrors.Errorf("rotateCommitteeIfNeeded: inconsistency. Governance transition expected... New output: %s", anchorOutput.String()) - } - rec, err := c.getOwnCommitteeRecord(anchorOutput.GetStateAddress()) - if err != nil { - return xerrors.Errorf("rotateCommitteeIfNeeded: %w", err) - } - // rotation needed - // close current in any case - c.log.Infof("CLOSING COMMITTEE for %s", currentCmt.Address().Base58()) - - currentCmt.Close() - c.consensus.Close() - c.setCommittee(nil) - c.consensus = nil - if rec != nil { - // create new if committee record is available - if err = c.createNewCommitteeAndConsensus(rec); err != nil { - return xerrors.Errorf("rotateCommitteeIfNeeded: creating committee and consensus: %v", err) - } - } - return nil -} - -func (c *chainObj) createCommitteeIfNeeded(anchorOutput *ledgerstate.AliasOutput) error { - // check if I am in the committee - rec, err := c.getOwnCommitteeRecord(anchorOutput.GetStateAddress()) - if err != nil { - return xerrors.Errorf("rotateCommitteeIfNeeded: %w", err) - } - if rec != nil { - // create if record is present - if err = c.createNewCommitteeAndConsensus(rec); err != nil { - return xerrors.Errorf("rotateCommitteeIfNeeded: creating committee and consensus: %v", 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 - } - // 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") - } - return rec, nil -} - -func (c *chainObj) createNewCommitteeAndConsensus(cmtRec *registry.CommitteeRecord) error { - c.log.Debugf("createNewCommitteeAndConsensus: creating a new committee...") - cmt, err := committee.New( - cmtRec, - 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) - } - cmt.Attach(c) - c.log.Debugf("creating new consensus object...") - c.consensus = consensus.New(c, c.mempool, cmt, c.nodeConn, c.pullMissingRequestsFromCommittee, c.chainMetrics) - c.setCommittee(cmt) - - c.log.Infof("NEW COMMITTEE OF VALIDATORS has been initialized for the state address %s", cmtRec.Address.Base58()) - return nil -} - func (c *chainObj) getCommittee() chain.Committee { ret := c.committee.Load().(*committeeStruct) if !ret.valid { diff --git a/packages/chain/chainimpl/chainimpl_test.go b/packages/chain/chainimpl/chainimpl_test.go new file mode 100644 index 0000000000..8670c53fe9 --- /dev/null +++ b/packages/chain/chainimpl/chainimpl_test.go @@ -0,0 +1,22 @@ +package chainimpl + +import ( + "testing" + + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/testutil" + "github.com/stretchr/testify/require" +) + +func TestValidateOffledger(t *testing.T) { + c := &chainObj{ + chainID: iscp.RandomChainID(), + } + req := testutil.DummyOffledgerRequest(c.chainID) + require.True(t, c.isRequestValid(req)) + req.WithNonce(999) // signature must be invalid after request content changes + require.False(t, c.isRequestValid(req)) + + wrongChainReq := testutil.DummyOffledgerRequest(iscp.RandomChainID()) + require.False(t, c.isRequestValid(wrongChainReq)) +} diff --git a/packages/chain/chainimpl/core.go b/packages/chain/chainimpl/core.go new file mode 100644 index 0000000000..3c05d06d99 --- /dev/null +++ b/packages/chain/chainimpl/core.go @@ -0,0 +1,59 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// Provides implementations for chain.ChainCore methods except the Enqueue*, +// which are provided in eventproc.go +package chainimpl + +import ( + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/wasp/packages/chain" + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/iscp/coreutil" + "github.com/iotaledger/wasp/packages/state" + "github.com/iotaledger/wasp/packages/vm/processors" +) + +func (c *chainObj) ID() *iscp.ChainID { + return c.chainID +} + +func (c *chainObj) GetCommitteeInfo() *chain.CommitteeInfo { + cmt := c.getCommittee() + if cmt == nil { + return nil + } + return &chain.CommitteeInfo{ + Address: cmt.DKShare().Address, + Size: cmt.Size(), + Quorum: cmt.Quorum(), + QuorumIsAlive: cmt.QuorumIsAlive(), + PeerStatus: cmt.PeerStatus(), + } +} + +func (c *chainObj) StateCandidateToStateManager(virtualState state.VirtualStateAccess, outputID ledgerstate.OutputID) { + c.stateMgr.EnqueueStateCandidateMsg(virtualState, outputID) +} + +func (c *chainObj) TriggerChainTransition(data *chain.ChainTransitionEventData) { + c.eventChainTransition.Trigger(data) +} + +func (c *chainObj) Processors() *processors.Cache { + return c.procset +} + +func (c *chainObj) GlobalStateSync() coreutil.ChainStateSync { + return c.chainStateSync +} + +// GetStateReader returns a new copy of the optimistic state reader, with own baseline +func (c *chainObj) GetStateReader() state.OptimisticStateReader { + return state.NewOptimisticStateReader(c.db, c.chainStateSync) +} + +func (c *chainObj) Log() *logger.Logger { + return c.log +} diff --git a/packages/chain/chainimpl/entry.go b/packages/chain/chainimpl/entry.go new file mode 100644 index 0000000000..bd7c889cb9 --- /dev/null +++ b/packages/chain/chainimpl/entry.go @@ -0,0 +1,79 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// Provides implementations for chain.ChainEntry methods +package chainimpl + +import ( + "time" + + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/iscp/request" + "github.com/iotaledger/wasp/packages/publisher" + "github.com/iotaledger/wasp/packages/transaction" +) + +func (c *chainObj) ReceiveTransaction(tx *ledgerstate.Transaction) { + c.log.Debugf("ReceiveTransaction: %s", tx.ID().Base58()) + reqs, err := request.OnLedgerFromTransaction(tx, c.chainID.AsAddress()) + if err != nil { + c.log.Warnf("failed to parse transaction %s: %v", tx.ID().Base58(), err) + return + } + for _, req := range reqs { + c.mempool.ReceiveRequest(req) + } + if chainOut := transaction.GetAliasOutput(tx, c.chainID.AsAddress()); chainOut != nil { + c.ReceiveState(chainOut, tx.Essence().Timestamp()) + } +} + +func (c *chainObj) ReceiveState(stateOutput *ledgerstate.AliasOutput, timestamp time.Time) { + c.log.Debugf("ReceiveState #%d: outputID: %s, stateAddr: %s", + stateOutput.GetStateIndex(), iscp.OID(stateOutput.ID()), stateOutput.GetStateAddress().Base58()) + c.EnqueueLedgerState(stateOutput, timestamp) +} + +func (c *chainObj) Dismiss(reason string) { + c.log.Infof("Dismiss chain. Reason: '%s'", reason) + + c.dismissOnce.Do(func() { + c.dismissed.Store(true) + c.chainPeers.Detach(c.receiveChainPeerMessagesAttachID) + c.nodeConn.DetachFromUnspentAliasOutputReceived() + c.nodeConn.DetachFromTransactionReceived() + c.eventChainTransition.Detach(c.eventChainTransitionClosure) + + c.mempool.Close() + c.stateMgr.Close() + cmt := c.getCommittee() + if cmt != nil { + c.detachFromCommitteePeerMessagesFun() + cmt.Close() + } + if c.consensus != nil { + c.consensus.Close() + } + + c.eventRequestProcessed.DetachAll() + c.eventChainTransition.DetachAll() + c.chainPeers.Close() + c.nodeConn.Close() + + c.dismissChainMsgPipe.Close() + c.stateMsgPipe.Close() + c.offLedgerRequestPeerMsgPipe.Close() + c.requestAckPeerMsgPipe.Close() + c.missingRequestIDsPeerMsgPipe.Close() + c.missingRequestPeerMsgPipe.Close() + c.timerTickMsgPipe.Close() + }) + + publisher.Publish("dismissed_chain", c.chainID.Base58()) + c.log.Debug("Chain dismissed") +} + +func (c *chainObj) IsDismissed() bool { + return c.dismissed.Load() +} diff --git a/packages/chain/chainimpl/eventproc.go b/packages/chain/chainimpl/eventproc.go new file mode 100644 index 0000000000..59bc90b82b --- /dev/null +++ b/packages/chain/chainimpl/eventproc.go @@ -0,0 +1,392 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package chainimpl + +import ( + "time" + + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/wasp/packages/chain" + "github.com/iotaledger/wasp/packages/chain/committee" + "github.com/iotaledger/wasp/packages/chain/consensus" + "github.com/iotaledger/wasp/packages/chain/messages" + "github.com/iotaledger/wasp/packages/hashing" + "github.com/iotaledger/wasp/packages/iscp" + "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" + "golang.org/x/xerrors" +) + +func (c *chainObj) recvLoop() { + dismissChainMsgChannel := c.dismissChainMsgPipe.Out() + stateMsgChannel := c.stateMsgPipe.Out() + offLedgerRequestMsgChannel := c.offLedgerRequestPeerMsgPipe.Out() + requestAckMsgChannel := c.requestAckPeerMsgPipe.Out() + missingRequestIDsMsgChannel := c.missingRequestIDsPeerMsgPipe.Out() + missingRequestMsgChannel := c.missingRequestPeerMsgPipe.Out() + timerTickMsgChannel := c.timerTickMsgPipe.Out() + for { + select { + case msg, ok := <-dismissChainMsgChannel: + if ok { + c.handleDismissChain(msg.(DismissChainMsg)) + } else { + dismissChainMsgChannel = nil + } + case msg, ok := <-stateMsgChannel: + if ok { + c.handleLedgerState(msg.(*messages.StateMsg)) + } else { + stateMsgChannel = nil + } + case msg, ok := <-offLedgerRequestMsgChannel: + if ok { + c.handleOffLedgerRequestMsg(msg.(*messages.OffLedgerRequestMsgIn)) + } else { + offLedgerRequestMsgChannel = nil + } + case msg, ok := <-requestAckMsgChannel: + if ok { + c.handleRequestAckPeerMsg(msg.(*messages.RequestAckMsgIn)) + } else { + requestAckMsgChannel = nil + } + case msg, ok := <-missingRequestIDsMsgChannel: + if ok { + c.handleMissingRequestIDsMsg(msg.(*messages.MissingRequestIDsMsgIn)) + } else { + missingRequestIDsMsgChannel = nil + } + case msg, ok := <-missingRequestMsgChannel: + if ok { + c.handleMissingRequestMsg(msg.(*messages.MissingRequestMsg)) + } else { + missingRequestMsgChannel = nil + } + case msg, ok := <-timerTickMsgChannel: + if ok { + c.handleTimerTick(msg.(messages.TimerTick)) + } else { + timerTickMsgChannel = nil + } + } + if dismissChainMsgChannel == nil && + stateMsgChannel == nil && + offLedgerRequestMsgChannel == nil && + requestAckMsgChannel == nil && + missingRequestIDsMsgChannel == nil && + missingRequestMsgChannel == nil && + timerTickMsgChannel == nil { + return + } + } +} + +func (c *chainObj) EnqueueDismissChain(reason string) { + c.dismissChainMsgPipe.In() <- DismissChainMsg{Reason: reason} + c.chainMetrics.CountMessages() +} + +func (c *chainObj) handleDismissChain(msg DismissChainMsg) { + c.log.Debugf("handleDismissChain message received, reason=%s", msg.Reason) + c.Dismiss(msg.Reason) +} + +func (c *chainObj) EnqueueLedgerState(chainOutput *ledgerstate.AliasOutput, timestamp time.Time) { + c.stateMsgPipe.In() <- &messages.StateMsg{ + ChainOutput: chainOutput, + Timestamp: timestamp, + } + c.chainMetrics.CountMessages() +} + +// 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: ", + msg.ChainOutput.GetStateIndex(), msg.ChainOutput.GetStateAddress().Base58(), !msg.ChainOutput.GetIsGovernanceUpdated(), msg.Timestamp) + sh, err := hashing.HashValueFromBytes(msg.ChainOutput.GetStateData()) + if err != nil { + c.log.Error(xerrors.Errorf("parsing state hash: %w", err)) + return + } + c.log.Debugf("handleLedgerState stateHash: %s", sh.String()) + cmt := c.getCommittee() + + if cmt != nil { + err = c.rotateCommitteeIfNeeded(msg.ChainOutput, cmt) + } else { + err = c.createCommitteeIfNeeded(msg.ChainOutput) + } + if err != nil { + c.log.Errorf("processStateMessage: %v", err) + return + } + c.stateMgr.EnqueueStateMsg(msg) + c.log.Debugf("handleLedgerState passed to state manager") +} + +func (c *chainObj) rotateCommitteeIfNeeded(anchorOutput *ledgerstate.AliasOutput, currentCmt chain.Committee) error { + if currentCmt.Address().Equals(anchorOutput.GetStateAddress()) { + // nothing changed. no rotation + return nil + } + // address changed + if !anchorOutput.GetIsGovernanceUpdated() { + return xerrors.Errorf("rotateCommitteeIfNeeded: inconsistency. Governance transition expected... New output: %s", anchorOutput.String()) + } + rec, err := c.getOwnCommitteeRecord(anchorOutput.GetStateAddress()) + if err != nil { + return xerrors.Errorf("rotateCommitteeIfNeeded: %w", err) + } + // rotation needed + // close current in any case + c.log.Infof("CLOSING COMMITTEE for %s", currentCmt.Address().Base58()) + + currentCmt.Close() + c.consensus.Close() + c.setCommittee(nil) + c.consensus = nil + if rec != nil { + // create new if committee record is available + if err = c.createNewCommitteeAndConsensus(rec); err != nil { + return xerrors.Errorf("rotateCommitteeIfNeeded: creating committee and consensus: %v", err) + } + } + return nil +} + +func (c *chainObj) createCommitteeIfNeeded(anchorOutput *ledgerstate.AliasOutput) error { + // check if I am in the committee + rec, err := c.getOwnCommitteeRecord(anchorOutput.GetStateAddress()) + if err != nil { + return xerrors.Errorf("rotateCommitteeIfNeeded: %w", err) + } + if rec != nil { + // create if record is present + if err = c.createNewCommitteeAndConsensus(rec); err != nil { + return xerrors.Errorf("rotateCommitteeIfNeeded: creating committee and consensus: %v", 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 + } + // 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") + } + return rec, nil +} + +func (c *chainObj) createNewCommitteeAndConsensus(cmtRec *registry.CommitteeRecord) error { + c.log.Debugf("createNewCommitteeAndConsensus: creating a new committee...") + if c.detachFromCommitteePeerMessagesFun != nil { + c.detachFromCommitteePeerMessagesFun() + } + cmt, cmtPeerGroup, err := committee.New( + cmtRec, + 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) + } + 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.setCommittee(cmt) + + c.log.Infof("NEW COMMITTEE OF VALIDATORS has been initialized for the state address %s", cmtRec.Address.Base58()) + return nil +} + +func (c *chainObj) EnqueueOffLedgerRequestMsg(msg *messages.OffLedgerRequestMsgIn) { + c.offLedgerRequestPeerMsgPipe.In() <- msg + c.chainMetrics.CountMessages() +} + +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) + + if !c.isRequestValid(msg.Req) { + // this means some node broadcasted an invalid request (bad chainID or signature) + // TODO should the sender node be punished somehow? + c.log.Errorf("handleOffLedgerRequestMsg message ignored: request is not valid") + return + } + if !c.mempool.ReceiveRequest(msg.Req) { + c.log.Errorf("handleOffLedgerRequestMsg message ignored: mempool hasn't accepted it") + return + } + c.broadcastOffLedgerRequest(msg.Req) + 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 == "" { + return + } + msg := &messages.RequestAckMsg{ReqID: &reqID} + c.chainPeers.SendMsgByNetID(peerID, peering.PeerMessageReceiverChain, chain.PeerMsgTypeRequestAck, msg.Bytes()) +} + +func (c *chainObj) isRequestValid(req *request.OffLedger) bool { + return req.ChainID().Equals(c.ID()) && req.VerifySignature() +} + +func (c *chainObj) broadcastOffLedgerRequest(req *request.OffLedger) { + c.log.Debugf("broadcastOffLedgerRequest: toNPeers: %d, reqID: %s", c.offledgerBroadcastUpToNPeers, req.ID().Base58()) + msg := &messages.OffLedgerRequestMsg{ + ChainID: c.chainID, + Req: req, + } + cmt := c.getCommittee() + getPeerIDs := c.chainPeers.GetRandomPeers + + if cmt != nil { + getPeerIDs = 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()) + } + } + } + + ticker := time.NewTicker(c.offledgerBroadcastInterval) + stopBroadcast := func() { + c.offLedgerReqsAcksMutex.Lock() + delete(c.offLedgerReqsAcks, req.ID()) + c.offLedgerReqsAcksMutex.Unlock() + ticker.Stop() + } + + go func() { + defer stopBroadcast() + for { + <-ticker.C + // check if processed (request already left the mempool) + if !c.mempool.HasRequest(req.ID()) { + return + } + c.offLedgerReqsAcksMutex.RLock() + ackPeers := c.offLedgerReqsAcks[(*req).ID()] + c.offLedgerReqsAcksMutex.RUnlock() + if cmt != nil && len(ackPeers) >= int(cmt.Size())-1 { + // this node is part of the committee and the message has already been received by every other committee node + return + } + sendMessage(ackPeers) + } + }() +} + +func shouldSendToPeer(peerID string, ackPeers []string) bool { + for _, p := range ackPeers { + if p == peerID { + return false + } + } + return true +} + +func (c *chainObj) EnqueueRequestAckMsg(msg *messages.RequestAckMsgIn) { + c.requestAckPeerMsgPipe.In() <- msg + c.chainMetrics.CountMessages() +} + +func (c *chainObj) handleRequestAckPeerMsg(msg *messages.RequestAckMsgIn) { + c.log.Debugf("handleRequestAckPeerMsg message received from peer %v, reqID: %s", msg.SenderNetID, msg.ReqID.Base58()) + c.offLedgerReqsAcksMutex.Lock() + defer c.offLedgerReqsAcksMutex.Unlock() + c.offLedgerReqsAcks[*msg.ReqID] = append(c.offLedgerReqsAcks[*msg.ReqID], msg.SenderNetID) + c.chainMetrics.CountRequestAckMessages() + c.log.Debugf("handleRequestAckPeerMsg comleted: reqID: %s", msg.ReqID.Base58()) +} + +func (c *chainObj) EnqueueMissingRequestIDsMsg(msg *messages.MissingRequestIDsMsgIn) { + c.missingRequestIDsPeerMsgPipe.In() <- msg + c.chainMetrics.CountMessages() +} + +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)) + if !c.pullMissingRequestsFromCommittee { + c.log.Warnf("handleMissingRequestIDsMsg ignored: pull from committee disabled") + return + } + for _, reqID := range msg.IDs { + 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) + } else { + c.log.Warnf("handleMissingRequestIDsMsg: reqID %s not found.", reqID.Base58()) + } + } + c.log.Debugf("handleMissingRequestIDsMsg completed") +} + +func (c *chainObj) EnqueueMissingRequestMsg(msg *messages.MissingRequestMsg) { + c.missingRequestPeerMsgPipe.In() <- msg + c.chainMetrics.CountMessages() +} + +func (c *chainObj) handleMissingRequestMsg(msg *messages.MissingRequestMsg) { + c.log.Debugf("handleMissingRequestMsg message received, reqID: %v", msg.Request.ID().Base58()) + if !c.pullMissingRequestsFromCommittee { + c.log.Warnf("handleMissingRequestMsg ignored: pull from committee disabled") + return + } + if c.consensus.ShouldReceiveMissingRequest(msg.Request) { + c.mempool.ReceiveRequest(msg.Request) + c.log.Warnf("handleMissingRequestMsg request with ID %v added to mempool", msg.Request.ID().Base58()) + } else { + c.log.Warnf("handleMissingRequestMsg ignored: consensus denied the need of request with ID %v", msg.Request.ID().Base58()) + } +} + +func (c *chainObj) EnqueueTimerTick(tick int) { + c.timerTickMsgPipe.In() <- messages.TimerTick(tick) + c.chainMetrics.CountMessages() +} + +func (c *chainObj) handleTimerTick(msg messages.TimerTick) { + if msg%2 == 0 { + c.stateMgr.EnqueueTimerMsg(msg / 2) + } else if c.consensus != nil { + c.consensus.EnqueueTimerMsg(msg / 2) + } + if msg%40 == 0 { + stats := c.mempool.Info() + c.log.Debugf("mempool total = %d, ready = %d, in = %d, out = %d", stats.TotalPool, stats.ReadyCounter, stats.InPoolCounter, stats.OutPoolCounter) + } +} diff --git a/packages/chain/chainimpl/interface.go b/packages/chain/chainimpl/interface.go deleted file mode 100644 index b37166f0fd..0000000000 --- a/packages/chain/chainimpl/interface.go +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package chainimpl - -import ( - "time" - - "github.com/iotaledger/goshimmer/packages/ledgerstate" - "github.com/iotaledger/hive.go/events" - "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/wasp/packages/chain" - "github.com/iotaledger/wasp/packages/chain/messages" - "github.com/iotaledger/wasp/packages/iscp" - "github.com/iotaledger/wasp/packages/iscp/coreutil" - "github.com/iotaledger/wasp/packages/iscp/request" - "github.com/iotaledger/wasp/packages/publisher" - "github.com/iotaledger/wasp/packages/registry" - "github.com/iotaledger/wasp/packages/state" - "github.com/iotaledger/wasp/packages/transaction" - "github.com/iotaledger/wasp/packages/vm/core/blocklog" - "github.com/iotaledger/wasp/packages/vm/processors" -) - -func (c *chainObj) ID() *iscp.ChainID { - return c.chainID -} - -func (c *chainObj) GlobalStateSync() coreutil.ChainStateSync { - return c.chainStateSync -} - -func (c *chainObj) GetCommitteeInfo() *chain.CommitteeInfo { - cmt := c.getCommittee() - if cmt == nil { - return nil - } - return &chain.CommitteeInfo{ - Address: cmt.DKShare().Address, - Size: cmt.Size(), - Quorum: cmt.Quorum(), - QuorumIsAlive: cmt.QuorumIsAlive(), - PeerStatus: cmt.PeerStatus(), - } -} - -func (c *chainObj) startTimer() { - go func() { - c.stateMgr.Ready().MustWait() - tick := 0 - for !c.IsDismissed() { - time.Sleep(chain.TimerTickPeriod) - c.ReceiveMessage(messages.TimerTick(tick)) - tick++ - } - }() -} - -func (c *chainObj) Dismiss(reason string) { - c.log.Infof("Dismiss chain. Reason: '%s'", reason) - - c.dismissOnce.Do(func() { - c.dismissed.Store(true) - - c.chMsg.Close() - - c.mempool.Close() - c.stateMgr.Close() - cmt := c.getCommittee() - if cmt != nil { - cmt.Close() - } - if c.consensus != nil { - c.consensus.Close() - } - c.eventRequestProcessed.DetachAll() - c.eventChainTransition.DetachAll() - }) - - publisher.Publish("dismissed_chain", c.chainID.Base58()) -} - -func (c *chainObj) IsDismissed() bool { - return c.dismissed.Load() -} - -// ReceiveMessage accepts an incoming message asynchronously. -func (c *chainObj) ReceiveMessage(msg interface{}) { - c.receiveMessage(msg) - c.chainMetrics.CountMessages() -} - -func (c *chainObj) receiveMessage(msg interface{}) { - if c.IsDismissed() { - return - } - c.chMsg.In() <- msg -} - -func shouldSendToPeer(peerID string, ackPeers []string) bool { - for _, p := range ackPeers { - if p == peerID { - return false - } - } - return true -} - -func (c *chainObj) broadcastOffLedgerRequest(req *request.OffLedger) { - c.log.Debugf("broadcastOffLedgerRequest: toNPeers: %d, reqID: %s", c.offledgerBroadcastUpToNPeers, req.ID().Base58()) - msgData := messages.NewOffLedgerRequestMsg(c.chainID, req).Bytes() - committee := c.getCommittee() - getPeerIDs := (*c.peers).GetRandomPeers - - if committee != nil { - getPeerIDs = committee.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.peers).SendSimple(peerID, messages.MsgOffLedgerRequest, msgData) - } - } - } - - ticker := time.NewTicker(c.offledgerBroadcastInterval) - stopBroadcast := func() { - c.offLedgerReqsAcksMutex.Lock() - delete(c.offLedgerReqsAcks, req.ID()) - c.offLedgerReqsAcksMutex.Unlock() - ticker.Stop() - } - - go func() { - defer stopBroadcast() - for { - <-ticker.C - // check if processed (request already left the mempool) - if !c.mempool.HasRequest(req.ID()) { - return - } - c.offLedgerReqsAcksMutex.RLock() - ackPeers := c.offLedgerReqsAcks[(*req).ID()] - c.offLedgerReqsAcksMutex.RUnlock() - if committee != nil && len(ackPeers) >= int(committee.Size())-1 { - // this node is part of the committee and the message has already been received by every other committee node - return - } - sendMessage(ackPeers) - } - }() -} - -func (c *chainObj) ReceiveOffLedgerRequest(req *request.OffLedger, senderNetID string) { - c.log.Debugf("ReceiveOffLedgerRequest: reqID: %s, peerID: %s", req.ID().Base58(), senderNetID) - c.sendRequestAcknowledgementMsg(req.ID(), senderNetID) - if !c.mempool.ReceiveRequest(req) { - return - } - c.log.Debugf("ReceiveOffLedgerRequest - added to mempool: reqID: %s, peerID: %s", req.ID().Base58(), senderNetID) - c.broadcastOffLedgerRequest(req) -} - -func (c *chainObj) sendRequestAcknowledgementMsg(reqID iscp.RequestID, peerID string) { - c.log.Debugf("sendRequestAcknowledgementMsg: reqID: %s, peerID: %s", reqID.Base58(), peerID) - if peerID == "" { - return - } - msgData := messages.NewRequestAckMsg(reqID).Bytes() - (*c.peers).SendSimple(peerID, messages.MsgRequestAck, msgData) -} - -func (c *chainObj) ReceiveRequestAckMessage(reqID *iscp.RequestID, peerID string) { - c.log.Debugf("ReceiveRequestAckMessage: reqID: %s, peerID: %s", reqID.Base58(), peerID) - c.offLedgerReqsAcksMutex.Lock() - defer c.offLedgerReqsAcksMutex.Unlock() - c.offLedgerReqsAcks[*reqID] = append(c.offLedgerReqsAcks[*reqID], peerID) - c.chainMetrics.CountRequestAckMessages() -} - -// SendMissingRequestsToPeer sends the requested missing requests by a peer -func (c *chainObj) SendMissingRequestsToPeer(msg *messages.MissingRequestIDsMsg, peerID string) { - for _, reqID := range msg.IDs { - c.log.Debugf("Sending MissingRequestsToPeer: reqID: %s, peerID: %s", reqID.Base58(), peerID) - if req := c.mempool.GetRequest(reqID); req != nil { - msg := messages.NewMissingRequestMsg(req) - (*c.peers).SendSimple(peerID, messages.MsgMissingRequest, msg.Bytes()) - } - } -} - -func (c *chainObj) ReceiveTransaction(tx *ledgerstate.Transaction) { - c.log.Debugf("ReceiveTransaction: %s", tx.ID().Base58()) - reqs, err := request.OnLedgerFromTransaction(tx, c.chainID.AsAddress()) - if err != nil { - c.log.Warnf("failed to parse transaction %s: %v", tx.ID().Base58(), err) - return - } - for _, req := range reqs { - c.ReceiveRequest(req) - } - if chainOut := transaction.GetAliasOutput(tx, c.chainID.AsAddress()); chainOut != nil { - c.ReceiveState(chainOut, tx.Essence().Timestamp()) - } -} - -func (c *chainObj) ReceiveRequest(req iscp.Request) { - c.log.Debugf("ReceiveRequest: %s", req.ID()) - c.mempool.ReceiveRequests(req) -} - -func (c *chainObj) ReceiveState(stateOutput *ledgerstate.AliasOutput, timestamp time.Time) { - c.log.Debugf("ReceiveState #%d: outputID: %s, stateAddr: %s", - stateOutput.GetStateIndex(), iscp.OID(stateOutput.ID()), stateOutput.GetStateAddress().Base58()) - c.ReceiveMessage(&messages.StateMsg{ - ChainOutput: stateOutput, - Timestamp: timestamp, - }) -} - -func (c *chainObj) ReceiveInclusionState(txID ledgerstate.TransactionID, inclusionState ledgerstate.InclusionState) { - c.ReceiveMessage(&messages.InclusionStateMsg{ - TxID: txID, - State: inclusionState, - }) // TODO special entry point -} - -func (c *chainObj) ReceiveOutput(output ledgerstate.Output) { - c.stateMgr.EventOutputMsg(output) -} - -func (c *chainObj) BlobCache() registry.BlobCache { - return c.blobProvider -} - -func (c *chainObj) GetRequestProcessingStatus(reqID iscp.RequestID) chain.RequestProcessingStatus { - if c.IsDismissed() { - return chain.RequestProcessingStatusUnknown - } - if c.consensus != nil { - if c.mempool.HasRequest(reqID) { - return chain.RequestProcessingStatusBacklog - } - } - c.stateReader.SetBaseline() - processed, err := blocklog.IsRequestProcessed(c.stateReader.KVStoreReader(), &reqID) - if err != nil || !processed { - return chain.RequestProcessingStatusUnknown - } - return chain.RequestProcessingStatusCompleted -} - -func (c *chainObj) Processors() *processors.Cache { - return c.procset -} - -func (c *chainObj) EventRequestProcessed() *events.Event { - return c.eventRequestProcessed -} - -func (c *chainObj) RequestProcessed() *events.Event { - return c.eventRequestProcessed -} - -func (c *chainObj) ChainTransition() *events.Event { - return c.eventChainTransition -} - -func (c *chainObj) Events() chain.ChainEvents { - return c -} - -// GetStateReader returns a new copy of the optimistic state reader, with own baseline -func (c *chainObj) GetStateReader() state.OptimisticStateReader { - return state.NewOptimisticStateReader(c.db, c.chainStateSync) -} - -func (c *chainObj) Log() *logger.Logger { - return c.log -} diff --git a/packages/chain/chainimpl/messages.go b/packages/chain/chainimpl/messages.go new file mode 100644 index 0000000000..90e8ca5228 --- /dev/null +++ b/packages/chain/chainimpl/messages.go @@ -0,0 +1,24 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +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 new file mode 100644 index 0000000000..650f96769d --- /dev/null +++ b/packages/chain/chainimpl/metrics.go @@ -0,0 +1,13 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// Provides implementations for chain.ChainMetrics methods +package chainimpl + +import ( + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" +) + +func (c *chainObj) GetNodeConnectionMetrics() nodeconnmetrics.NodeConnectionMessagesMetrics { + return c.nodeConn.GetMetrics() +} diff --git a/packages/chain/chainimpl/requests.go b/packages/chain/chainimpl/requests.go new file mode 100644 index 0000000000..b3db610ba2 --- /dev/null +++ b/packages/chain/chainimpl/requests.go @@ -0,0 +1,39 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// Provides implementations for chain.ChainRequests methods +package chainimpl + +import ( + "github.com/iotaledger/hive.go/events" + "github.com/iotaledger/wasp/packages/chain" + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/vm/core/blocklog" +) + +func (c *chainObj) GetRequestProcessingStatus(reqID iscp.RequestID) chain.RequestProcessingStatus { + if c.IsDismissed() { + return chain.RequestProcessingStatusUnknown + } + if c.consensus != nil { + if c.mempool.HasRequest(reqID) { + return chain.RequestProcessingStatusBacklog + } + } + c.stateReader.SetBaseline() + processed, err := blocklog.IsRequestProcessed(c.stateReader.KVStoreReader(), &reqID) + if err != nil || !processed { + return chain.RequestProcessingStatusUnknown + } + return chain.RequestProcessingStatusCompleted +} + +func (c *chainObj) AttachToRequestProcessed(handler func(iscp.RequestID)) *events.Closure { + closure := events.NewClosure(handler) + c.eventRequestProcessed.Attach(closure) + return closure +} + +func (c *chainObj) DetachFromRequestProcessed(attachID *events.Closure) { + c.eventRequestProcessed.Detach(attachID) +} diff --git a/packages/chain/committee/committee.go b/packages/chain/committee/committee.go index 2a2758a899..027422dbda 100644 --- a/packages/chain/committee/committee.go +++ b/packages/chain/committee/committee.go @@ -5,7 +5,6 @@ package committee import ( "crypto/rand" - "fmt" "time" "github.com/iotaledger/goshimmer/packages/ledgerstate" @@ -27,15 +26,15 @@ type committee struct { peerConfig registry.PeerNetworkConfigProvider validatorNodes peering.GroupProvider acsRunner chain.AsynchronousCommonSubsetRunner - peeringID peering.PeeringID size uint16 quorum uint16 ownIndex uint16 dkshare *tcrypto.DKShare - attachID interface{} log *logger.Logger } +var _ chain.Committee = &committee{} + const waitReady = false func New( @@ -46,23 +45,18 @@ func New( dksProvider registry.DKShareRegistryProvider, log *logger.Logger, acsRunner ...chain.AsynchronousCommonSubsetRunner, // Only for mocking. -) (chain.Committee, error) { +) (chain.Committee, peering.GroupProvider, error) { // load DKShare from the registry dkshare, err := dksProvider.LoadDKShare(cmtRec.Address) if err != nil { - return nil, xerrors.Errorf("NewCommittee: failed loading DKShare for address %s: %w", cmtRec.Address.Base58(), err) + return nil, nil, xerrors.Errorf("NewCommittee: failed loading DKShare for address %s: %w", cmtRec.Address.Base58(), err) } if dkshare.Index == nil { - return nil, xerrors.Errorf("NewCommittee: wrong DKShare record for address %s: %w", cmtRec.Address.Base58(), err) + 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, xerrors.Errorf("NewCommittee: %w", err) - } - var peers peering.GroupProvider - if peers, err = netProvider.PeerGroup(cmtRec.Nodes); err != nil { - return nil, xerrors.Errorf("NewCommittee: failed to create peer group for committee: %+v: %w", cmtRec.Nodes, err) + return nil, nil, xerrors.Errorf("NewCommittee: %w", err) } - log.Debugf("NewCommittee: peer group: %+v", cmtRec.Nodes) // peerGroupID is calculated by XORing chainID and stateAddr. // It allows to use same statAddr for different chains peerGroupID := cmtRec.Address.Array() @@ -73,11 +67,15 @@ func New( for i := range peerGroupID { 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) + } + log.Debugf("NewCommittee: peer group: %+v", cmtRec.Nodes) ret := &committee{ isReady: atomic.NewBool(false), address: cmtRec.Address, validatorNodes: peers, - peeringID: peerGroupID, peerConfig: peerConfig, size: dkshare.N, quorum: dkshare.T, @@ -89,18 +87,17 @@ func New( ret.acsRunner = acsRunner[0] } else { // That's the default implementation of the ACS. - // We use it, of the mocked variant was not passed. + // We use it, if the mocked variant was not passed. ret.acsRunner = commonsubset.NewCommonSubsetCoordinator( - peerGroupID, netProvider, - peers, + ret.validatorNodes, dkshare, log, ) } go ret.waitReady(waitReady) - return ret, nil + return ret, ret.validatorNodes, nil } func (c *committee) Address() ledgerstate.Address { @@ -127,30 +124,6 @@ func (c *committee) DKShare() *tcrypto.DKShare { return c.dkshare } -func (c *committee) SendMsg(targetPeerIndex uint16, msgType byte, msgData []byte) error { - if peer, ok := c.validatorNodes.OtherNodes()[targetPeerIndex]; ok { - peer.SendMsg(&peering.PeerMessage{ - PeeringID: c.peeringID, - SenderIndex: c.ownIndex, - MsgType: msgType, - MsgData: msgData, - }) - return nil - } - return fmt.Errorf("SendMsg: wrong peer index") -} - -func (c *committee) SendMsgToPeers(msgType byte, msgData []byte, ts int64, except ...uint16) { - msg := &peering.PeerMessage{ - PeeringID: c.peeringID, - SenderIndex: c.ownIndex, - Timestamp: ts, - MsgType: msgType, - MsgData: msgData, - } - c.validatorNodes.Broadcast(msg, false, except...) -} - func (c *committee) IsAlivePeer(peerIndex uint16) bool { allNodes := c.validatorNodes.AllNodes() if int(peerIndex) >= len(allNodes) { @@ -202,21 +175,9 @@ func (c *committee) PeerStatus() []*chain.PeerStatus { return ret } -func (c *committee) Attach(ch chain.ChainCore) { - c.attachID = c.validatorNodes.Attach(&c.peeringID, func(recv *peering.RecvEvent) { - if c.acsRunner != nil && c.acsRunner.TryHandleMessage(recv) { - return - } - ch.ReceiveMessage(recv.Msg) - }) -} - func (c *committee) Close() { c.acsRunner.Close() c.isReady.Store(false) - if c.attachID != nil { - c.validatorNodes.Detach(c.attachID) - } c.validatorNodes.Close() } diff --git a/packages/chain/committee/committee_test.go b/packages/chain/committee/committee_test.go index 53a4e74704..696af24d72 100644 --- a/packages/chain/committee/committee_test.go +++ b/packages/chain/committee/committee_test.go @@ -35,7 +35,7 @@ func TestCommitteeBasic(t *testing.T) { Address: stateAddr, Nodes: netIDs, } - c, err := New(cmtRec, nil, net0, cfg0, dksRegistries[0], log) + c, _, err := New(cmtRec, nil, net0, cfg0, dksRegistries[0], log) require.NoError(t, err) require.True(t, c.Address().Equals(stateAddr)) require.EqualValues(t, 4, c.Size()) diff --git a/packages/chain/consensus/action.go b/packages/chain/consensus/action.go index f9adaad88e..7dd8db883b 100644 --- a/packages/chain/consensus/action.go +++ b/packages/chain/consensus/action.go @@ -11,12 +11,14 @@ import ( "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/hive.go/identity" + "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/chain/messages" "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/request" "github.com/iotaledger/wasp/packages/iscp/rotate" "github.com/iotaledger/wasp/packages/kv/dict" + "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/transaction" "github.com/iotaledger/wasp/packages/util" "github.com/iotaledger/wasp/packages/vm" @@ -24,7 +26,7 @@ import ( ) // takeAction triggers actions whenever relevant -func (c *Consensus) takeAction() { +func (c *consensus) takeAction() { if !c.workflow.stateReceived || !c.workflow.inProgress { c.log.Debugf("takeAction skipped: stateReceived: %v, workflow in progress: %v", c.workflow.stateReceived, c.workflow.inProgress) @@ -41,7 +43,7 @@ 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() { +func (c *consensus) proposeBatchIfNeeded() { if c.workflow.batchProposalSent { c.log.Debugf("proposeBatch not needed: batch proposal already sent") return @@ -55,6 +57,7 @@ func (c *Consensus) proposeBatchIfNeeded() { return } if time.Now().Before(c.stateTimestamp.Add(c.timers.ProposeBatchDelayForNewState)) { + c.log.Debugf("proposeBatch not needed: delayed for %v from %v", c.timers.ProposeBatchDelayForNewState, c.stateTimestamp) return } reqs := c.mempool.ReadyNow() @@ -67,7 +70,7 @@ func (c *Consensus) proposeBatchIfNeeded() { // call the ACS consensus. The call should spawn goroutine itself c.committee.RunACSConsensus(proposal.Bytes(), c.acsSessionID, c.stateOutput.GetStateIndex(), func(sessionID uint64, acs [][]byte) { c.log.Debugf("proposeBatch RunACSConsensus callback: responding to ACS session ID %v: len = %d", sessionID, len(acs)) - go c.chain.ReceiveMessage(&messages.AsynchronousCommonSubsetMsg{ + go c.EnqueueAsynchronousCommonSubsetMsg(&messages.AsynchronousCommonSubsetMsg{ ProposedBatchesBin: acs, SessionID: sessionID, }) @@ -80,7 +83,7 @@ func (c *Consensus) proposeBatchIfNeeded() { // 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() { +func (c *consensus) runVMIfNeeded() { if !c.workflow.consensusBatchKnown { c.log.Debugf("runVM not needed: consensus batch is not known") return @@ -146,13 +149,14 @@ func (c *Consensus) runVMIfNeeded() { ) c.workflow.vmStarted = true vmTask.StartTime = time.Now() + c.consensusMetrics.CountVMRuns() go c.vmRunner.Run(vmTask) } else { c.log.Errorf("runVM: error preparing VM task") } } -func (c *Consensus) pollMissingRequests(missingRequestIndexes []int) { +func (c *consensus) pollMissingRequests(missingRequestIndexes []int) { // some requests are not ready, so skip VM call this time. Maybe next time will be more luck c.delayRunVMUntil = time.Now().Add(c.timers.VMRunRetryToWaitForReadyRequests) c.log.Infof( // Was silently failing when entire arrays were logged instead of counts. @@ -165,20 +169,22 @@ func (c *Consensus) pollMissingRequests(missingRequestIndexes []int) { return } missingRequestIds := []iscp.RequestID{} + missingRequestIDsString := "" for _, idx := range missingRequestIndexes { reqID := c.consensusBatch.RequestIDs[idx] reqHash := c.consensusBatch.RequestHashes[idx] c.missingRequestsFromBatch[reqID] = reqHash missingRequestIds = append(missingRequestIds, reqID) + missingRequestIDsString += reqID.Base58() + ", " } - c.log.Debugf("runVMIfNeeded: asking for missing requests, ids: %v", missingRequestIds) - msgData := messages.NewMissingRequestIDsMsg(missingRequestIds).Bytes() - c.committee.SendMsgToPeers(messages.MsgMissingRequestIDs, msgData, time.Now().UnixNano()) + c.log.Debugf("runVMIfNeeded: asking for missing requests, ids: [%v]", missingRequestIDsString) + msg := &messages.MissingRequestIDsMsg{IDs: missingRequestIds} + c.committeePeerGroup.SendMsgBroadcast(peering.PeerMessageReceiverChain, chain.PeerMsgTypeMissingRequestIDs, msg.Bytes()) } // sortBatch deterministically sorts batch based on the value extracted from the consensus entropy // It is needed for determinism and as a MEV prevention measure see [prevent-mev.md] -func (c *Consensus) sortBatch(reqs []iscp.Request) { +func (c *consensus) sortBatch(reqs []iscp.Request) { if len(reqs) <= 1 { return } @@ -210,7 +216,7 @@ func (c *Consensus) sortBatch(reqs []iscp.Request) { } } -func (c *Consensus) prepareVMTask(reqs []iscp.Request) *vm.VMTask { +func (c *consensus) prepareVMTask(reqs []iscp.Request) *vm.VMTask { stateBaseline := c.chain.GlobalStateSync().GetSolidIndexBaseline() if !stateBaseline.IsValid() { c.log.Debugf("prepareVMTask: solid state baseline is invalid. Do not even start the VM") @@ -235,7 +241,7 @@ func (c *Consensus) prepareVMTask(reqs []iscp.Request) *vm.VMTask { } c.log.Debugf("runVM OnFinish callback: responding by state index: %d state hash: %s", task.VirtualStateAccess.BlockIndex(), task.VirtualStateAccess.StateCommitment()) - c.chain.ReceiveMessage(&messages.VMResultMsg{ + c.EnqueueVMResultMsg(&messages.VMResultMsg{ Task: task, }) elapsed := time.Since(task.StartTime) @@ -245,7 +251,7 @@ func (c *Consensus) prepareVMTask(reqs []iscp.Request) *vm.VMTask { return task } -func (c *Consensus) broadcastSignedResultIfNeeded() { +func (c *consensus) broadcastSignedResultIfNeeded() { if !c.workflow.vmResultSigned { c.log.Debugf("broadcastSignedResult not needed: vm result is not signed") return @@ -260,7 +266,7 @@ func (c *Consensus) broadcastSignedResultIfNeeded() { EssenceHash: signedResult.EssenceHash, SigShare: signedResult.SigShare, } - c.committee.SendMsgToPeers(messages.MsgSignedResult, util.MustBytes(msg), time.Now().UnixNano(), c.resultSigAck...) + c.committeePeerGroup.SendMsgBroadcast(peering.PeerMessageReceiverConsensus, peerMsgTypeSignedResult, util.MustBytes(msg), c.resultSigAck...) c.delaySendingSignedResult = time.Now().Add(c.timers.BroadcastSignedResultRetry) c.log.Debugf("broadcastSignedResult: broadcasted: essence hash: %s, chain input %s", @@ -275,7 +281,7 @@ func (c *Consensus) broadcastSignedResultIfNeeded() { // Then it deterministically calculates a priority sequence among contributing nodes for posting // 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() { +func (c *consensus) checkQuorum() { if c.workflow.transactionFinalized { c.log.Debugf("checkQuorum not needed: transaction already finalized") return @@ -336,10 +342,7 @@ func (c *Consensus) checkQuorum() { // if it is not state controller rotation, sending message to state manager // Otherwise state manager is not notified chainOutputID := chainOutput.ID() - go c.chain.ReceiveMessage(&messages.StateCandidateMsg{ - State: c.resultState, - ApprovingOutputID: chainOutputID, - }) + c.chain.StateCandidateToStateManager(c.resultState, chainOutputID) c.log.Debugf("checkQuorum: StateCandidateMsg sent for state index %v, approving output ID %v", c.resultState.BlockIndex(), iscp.OID(chainOutputID)) } @@ -362,7 +365,7 @@ func (c *Consensus) checkQuorum() { } // postTransactionIfNeeded posts a finalized transaction upon deadline unless it was evidenced on L1 before the deadline. -func (c *Consensus) postTransactionIfNeeded() { +func (c *consensus) postTransactionIfNeeded() { if !c.workflow.transactionFinalized { c.log.Debugf("postTransaction not needed: transaction is not finalized") return @@ -392,7 +395,7 @@ func (c *Consensus) postTransactionIfNeeded() { // 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() { +func (c *consensus) pullInclusionStateIfNeeded() { if !c.workflow.transactionFinalized { c.log.Debugf("pullInclusionState not needed: transaction is not finalized") return @@ -405,13 +408,13 @@ func (c *Consensus) pullInclusionStateIfNeeded() { c.log.Debugf("pullInclusionState not needed: delayed till %v", c.pullInclusionStateDeadline) return } - c.nodeConn.PullTransactionInclusionState(c.chain.ID().AsAddress(), c.finalTx.ID()) + c.nodeConn.PullTransactionInclusionState(c.finalTx.ID()) c.pullInclusionStateDeadline = time.Now().Add(c.timers.PullInclusionStateRetry) c.log.Debugf("pullInclusionState: request for inclusion state sent") } // prepareBatchProposal creates a batch proposal structure out of requests -func (c *Consensus) prepareBatchProposal(reqs []iscp.Request) *BatchProposal { +func (c *consensus) prepareBatchProposal(reqs []iscp.Request) *BatchProposal { ts := time.Now() if !ts.After(c.stateTimestamp) { ts = c.stateTimestamp.Add(1 * time.Nanosecond) @@ -445,7 +448,7 @@ func (c *Consensus) prepareBatchProposal(reqs []iscp.Request) *BatchProposal { // receiveACS processed new ACS received from ACS consensus //nolint:funlen -func (c *Consensus) receiveACS(values [][]byte, sessionID uint64) { +func (c *consensus) receiveACS(values [][]byte, sessionID uint64) { if c.acsSessionID != sessionID { c.log.Debugf("receiveACS: session id missmatch: expected %v, received %v", c.acsSessionID, sessionID) return @@ -559,7 +562,7 @@ func (c *Consensus) receiveACS(values [][]byte, sessionID uint64) { c.runVMIfNeeded() } -func (c *Consensus) processInclusionState(msg *messages.InclusionStateMsg) { +func (c *consensus) processInclusionState(msg *messages.InclusionStateMsg) { if !c.workflow.transactionFinalized { c.log.Debugf("processInclusionState: transaction finalized -> skipping.") return @@ -585,7 +588,7 @@ func (c *Consensus) processInclusionState(msg *messages.InclusionStateMsg) { } } -func (c *Consensus) finalizeTransaction(sigSharesToAggregate [][]byte) (*ledgerstate.Transaction, *ledgerstate.AliasOutput, error) { +func (c *consensus) finalizeTransaction(sigSharesToAggregate [][]byte) (*ledgerstate.Transaction, *ledgerstate.AliasOutput, error) { signatureWithPK, err := c.committee.DKShare().RecoverFullSignature(sigSharesToAggregate, c.resultTxEssence.Bytes()) if err != nil { return nil, nil, xerrors.Errorf("finalizeTransaction RecoverFullSignature fail: %w", err) @@ -618,10 +621,23 @@ func (c *Consensus) finalizeTransaction(sigSharesToAggregate [][]byte) (*ledgers return tx, chained, nil } -func (c *Consensus) setNewState(msg *messages.StateTransitionMsg) { +func (c *consensus) setNewState(msg *messages.StateTransitionMsg) bool { if msg.State.BlockIndex() != msg.StateOutput.GetStateIndex() { - c.log.Panicf("consensus::setNewState: state index is inconsistent: block: #%d != chain output: #%d", + // NOTE: should be a panic. However this situation may occur (and occurs) in normal circumstations: + // 1) State manager synchronizes to state index n and passes state transmission message through event to consensus asynchronously + // 2) Consensus is overwhelmed and receives a message after delay + // 3) Meanwhile state manager is quick enough to synchronize to state index n+1 and commits a block of state index n+1 + // 4) Only then the consensus receives a message sent in step 1. Due to imperfect implementation of virtual state copying it thinks + // that state is at index n+1, however chain output is (as was transmitted) and at index n. + // The virtual state copying (earlier called "cloning") works in a following way: it copies all the mutations, stored in buffered KVS, + // however it obtains the same kvs object to access the database. BlockIndex method of virtual state checks if there are mutations editing + // the index value. If so, it returns the newest value in respect to mutations. Otherwise it checks the database for newest index value. + // In the described scenario, there are no mutations neither in step 1, nor in step 3, because just before completing state synchronization + // all the mutations are written to the DB. However, reading the same DB in step 1 results in index n and in step 4 (after the commit of block + // index n+1) -- in index n+1. Thus effectively the virtual state received is different than the virtual state sent. + c.log.Errorf("consensus::setNewState: state index is inconsistent: block: #%d != chain output: #%d", msg.State.BlockIndex(), msg.StateOutput.GetStateIndex()) + return false } c.stateOutput = msg.StateOutput @@ -635,9 +651,10 @@ func (c *Consensus) setNewState(msg *messages.StateTransitionMsg) { c.log.Debugf("SET NEW STATE #%d%s, output: %s, hash: %s", msg.StateOutput.GetStateIndex(), r, iscp.OID(msg.StateOutput.ID()), msg.State.StateCommitment().String()) c.resetWorkflow() + return true } -func (c *Consensus) resetWorkflow() { +func (c *consensus) resetWorkflow() { for i := range c.resultSignatures { c.resultSignatures[i] = nil } @@ -655,7 +672,7 @@ func (c *Consensus) resetWorkflow() { c.log.Debugf("Workflow reset") } -func (c *Consensus) processVMResult(result *vm.VMTask) { +func (c *consensus) processVMResult(result *vm.VMTask) { if !c.workflow.vmStarted || c.workflow.vmResultSigned || c.acsSessionID != result.ACSSessionID { @@ -684,11 +701,13 @@ func (c *Consensus) processVMResult(result *vm.VMTask) { sigShare, err := c.committee.DKShare().SignShare(essenceBytes) c.assert.RequireNoError(err, "processVMResult: ") - c.resultSignatures[c.committee.OwnPeerIndex()] = &messages.SignedResultMsg{ - SenderIndex: c.committee.OwnPeerIndex(), - ChainInputID: result.ChainInput.ID(), - EssenceHash: essenceHash, - SigShare: sigShare, + c.resultSignatures[c.committee.OwnPeerIndex()] = &messages.SignedResultMsgIn{ + SignedResultMsg: messages.SignedResultMsg{ + ChainInputID: result.ChainInput.ID(), + EssenceHash: essenceHash, + SigShare: sigShare, + }, + SenderIndex: c.committee.OwnPeerIndex(), } c.workflow.vmResultSigned = true @@ -696,7 +715,7 @@ func (c *Consensus) processVMResult(result *vm.VMTask) { c.log.Debugf("processVMResult signed: essence hash: %s", essenceHash.String()) } -func (c *Consensus) makeRotateStateControllerTransaction(task *vm.VMTask) *ledgerstate.TransactionEssence { +func (c *consensus) makeRotateStateControllerTransaction(task *vm.VMTask) *ledgerstate.TransactionEssence { c.log.Debugf("makeRotateStateControllerTransaction: %s", task.RotationAddress.Base58()) // TODO access and consensus pledge @@ -711,7 +730,7 @@ func (c *Consensus) makeRotateStateControllerTransaction(task *vm.VMTask) *ledge return essence } -func (c *Consensus) receiveSignedResult(msg *messages.SignedResultMsg) { +func (c *consensus) receiveSignedResult(msg *messages.SignedResultMsgIn) { if c.resultSignatures[msg.SenderIndex] != nil { if c.resultSignatures[msg.SenderIndex].EssenceHash != msg.EssenceHash || !bytes.Equal(c.resultSignatures[msg.SenderIndex].SigShare[:], msg.SigShare[:]) { @@ -746,12 +765,10 @@ func (c *Consensus) receiveSignedResult(msg *messages.SignedResultMsg) { ChainInputID: msg.ChainInputID, EssenceHash: msg.EssenceHash, } - if err := c.committee.SendMsg(msg.SenderIndex, messages.MsgSignedResultAck, util.MustBytes(msgAck)); err != nil { - c.log.Errorf("receiveSignedResult: failed to send acknowledgement: %v", err) - } + c.committeePeerGroup.SendMsgByIndex(msg.SenderIndex, peering.PeerMessageReceiverConsensus, peerMsgTypeSignedResultAck, util.MustBytes(msgAck)) } -func (c *Consensus) receiveSignedResultAck(msg *messages.SignedResultAckMsg) { +func (c *consensus) receiveSignedResultAck(msg *messages.SignedResultAckMsgIn) { own := c.resultSignatures[c.committee.OwnPeerIndex()] if own == nil || msg.EssenceHash != own.EssenceHash || msg.ChainInputID != own.ChainInputID { return @@ -767,7 +784,7 @@ func (c *Consensus) receiveSignedResultAck(msg *messages.SignedResultAckMsg) { // TODO mutex inside is not good // ShouldReceiveMissingRequest returns whether the request is missing, if the incoming request matches the expects ID/Hash it is removed from the list -func (c *Consensus) ShouldReceiveMissingRequest(req iscp.Request) bool { +func (c *consensus) ShouldReceiveMissingRequest(req iscp.Request) bool { c.log.Debugf("ShouldReceiveMissingRequest: reqID %s, hash %v", req.ID(), req.Hash()) c.missingRequestsMutex.Lock() @@ -785,7 +802,7 @@ func (c *Consensus) ShouldReceiveMissingRequest(req iscp.Request) bool { return result } -func (c *Consensus) cleanMissingRequests() { +func (c *consensus) cleanMissingRequests() { c.missingRequestsMutex.Lock() defer c.missingRequestsMutex.Unlock() diff --git a/packages/chain/consensus/batch_proposal.go b/packages/chain/consensus/batch_proposal.go index de4a1fc5e6..072d1f6cb7 100644 --- a/packages/chain/consensus/batch_proposal.go +++ b/packages/chain/consensus/batch_proposal.go @@ -145,7 +145,7 @@ func (b *BatchProposal) EnsureTimestampConsistent(requests []iscp.Request, state // Timestamp is calculated by taking maximal proposed timestamp excluding F highest proposals. // // TODO final version of pledges and fee destination -func (c *Consensus) calcBatchParameters(props []*BatchProposal) (*consensusBatchParams, error) { +func (c *consensus) calcBatchParameters(props []*BatchProposal) (*consensusBatchParams, error) { var retTS time.Time ts := make([]time.Time, len(props)) diff --git a/packages/chain/consensus/commonsubset/commonsubset.go b/packages/chain/consensus/commonsubset/commonsubset.go index e39938c08a..5dffeca7aa 100644 --- a/packages/chain/consensus/commonsubset/commonsubset.go +++ b/packages/chain/consensus/commonsubset/commonsubset.go @@ -46,7 +46,6 @@ import ( ) const ( - acsMsgType = 50 + peering.FirstUserMsgCode resendPeriod = 500 * time.Millisecond ) @@ -63,11 +62,10 @@ type CommonSubset struct { recvMsgBatches []map[uint32]uint32 // [PeerId]ReceivedMbID -> AckedInMb (0 -- unacked). It remains 0, if acked in non-data message. sentMsgBatches map[uint32]*msgBatch // BatchID -> MsgBatch - sessionID uint64 // Unique identifier for this consensus instance. Used to route messages. - stateIndex uint32 // Sequence number of the CS transaction we are agreeing on. - peeringID peering.PeeringID // ID for the communication group. - netGroup peering.GroupProvider // Group of nodes we are communicating with. - netOwnIndex uint16 // Our index in the group. + sessionID uint64 // Unique identifier for this consensus instance. Used to route messages. + stateIndex uint32 // Sequence number of the CS transaction we are agreeing on. + committeePeerGroup peering.GroupProvider + netOwnIndex uint16 // Our index in the group. inputCh chan []byte // For our input to the consensus. recvCh chan *msgBatch // For incoming messages. @@ -80,15 +78,14 @@ type CommonSubset struct { func NewCommonSubset( sessionID uint64, stateIndex uint32, - peeringID peering.PeeringID, - netGroup peering.GroupProvider, + committeePeerGroup peering.GroupProvider, dkShare *tcrypto.DKShare, allRandom bool, // Set to true to have real CC rounds for each epoch. That's for testing mostly. outputCh chan map[uint16][]byte, log *logger.Logger, ) (*CommonSubset, error) { - ownIndex := netGroup.SelfIndex() - allNodes := netGroup.AllNodes() + ownIndex := committeePeerGroup.SelfIndex() + allNodes := committeePeerGroup.AllNodes() nodeCount := len(allNodes) nodes := make([]uint64, nodeCount) nodePos := 0 @@ -110,22 +107,21 @@ func NewCommonSubset( CommonCoin: commoncoin.NewBlsCommonCoin(dkShare, salt[:], allRandom), } cs := CommonSubset{ - impl: hbbft.NewACS(acsCfg), - batchCounter: 0, - missingAcks: make(map[uint32]time.Time), - pendingAcks: make([][]uint32, nodeCount), - recvMsgBatches: make([]map[uint32]uint32, nodeCount), - sentMsgBatches: make(map[uint32]*msgBatch), - sessionID: sessionID, - stateIndex: stateIndex, - peeringID: peeringID, - netGroup: netGroup, - netOwnIndex: ownIndex, - inputCh: make(chan []byte, 1), - recvCh: make(chan *msgBatch, 1), - closeCh: make(chan bool), - outputCh: outputCh, - log: log, + impl: hbbft.NewACS(acsCfg), + batchCounter: 0, + missingAcks: make(map[uint32]time.Time), + pendingAcks: make([][]uint32, nodeCount), + recvMsgBatches: make([]map[uint32]uint32, nodeCount), + sentMsgBatches: make(map[uint32]*msgBatch), + sessionID: sessionID, + stateIndex: stateIndex, + committeePeerGroup: committeePeerGroup, + netOwnIndex: ownIndex, + inputCh: make(chan []byte, 1), + recvCh: make(chan *msgBatch, 1), + closeCh: make(chan bool), + outputCh: outputCh, + log: log, } for i := range cs.recvMsgBatches { cs.recvMsgBatches[i] = make(map[uint32]uint32) @@ -147,22 +143,6 @@ func (cs *CommonSubset) Input(input []byte) { cs.inputCh <- input } -// TryHandleMessage checks, if the RecvEvent is of suitable type and -// processed the message as an input from a peer if the type matches. -// This one is called from the ACS tests. -func (cs *CommonSubset) TryHandleMessage(recv *peering.RecvEvent) bool { - if recv.Msg.MsgType != acsMsgType { - return false - } - mb := msgBatch{} - if err := mb.FromBytes(recv.Msg.MsgData); err != nil { - cs.log.Errorf("Cannot decode message: %v", err) - return true - } - cs.HandleMsgBatch(&mb) - return true -} - // HandleMsgBatch accepts a parsed msgBatch as an input from other node. // This function is used in the CommonSubsetCoordinator to avoid parsing // the received message multiple times. @@ -396,13 +376,7 @@ func (cs *CommonSubset) send(msgBatch *msgBatch) { return } cs.log.Debugf("ACS::IO - Sending a msgBatch=%+v", msgBatch) - cs.netGroup.SendMsgByIndex(msgBatch.dst, &peering.PeerMessage{ - PeeringID: cs.peeringID, - SenderIndex: cs.netOwnIndex, - Timestamp: 0, - MsgType: acsMsgType, - MsgData: msgBatch.Bytes(), - }) + cs.committeePeerGroup.SendMsgByIndex(msgBatch.dst, peering.PeerMessageReceiverCommonSubset, peerMsgTypeBatch, msgBatch.Bytes()) } // endregion /////////////////////////////////////////////////////////////////// @@ -430,6 +404,15 @@ const ( acsMsgTypeAbaDoneRequest byte = 7 << 4 ) +func newMsgBatch(data []byte) (*msgBatch, error) { + mb := &msgBatch{} + r := bytes.NewReader(data) + if err := mb.Read(r); err != nil { + return nil, err + } + return mb, nil +} + func (b *msgBatch) NeedsAck() bool { return b.id != 0 } @@ -740,11 +723,6 @@ func (b *msgBatch) Read(r io.Reader) error { return nil } -func (b *msgBatch) FromBytes(buf []byte) error { - r := bytes.NewReader(buf) - return b.Read(r) -} - func (b *msgBatch) Bytes() []byte { var buf bytes.Buffer _ = b.Write(&buf) diff --git a/packages/chain/consensus/commonsubset/commonsubset_test.go b/packages/chain/consensus/commonsubset/commonsubset_test.go index f64a7304bb..53a67c4f7e 100644 --- a/packages/chain/consensus/commonsubset/commonsubset_test.go +++ b/packages/chain/consensus/commonsubset/commonsubset_test.go @@ -1,17 +1,17 @@ // Copyright 2020 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -package commonsubset_test +package commonsubset import ( "bytes" + "crypto/rand" "fmt" "sync" "testing" "time" "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/wasp/packages/chain/consensus/commonsubset" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/tcrypto" "github.com/iotaledger/wasp/packages/testutil" @@ -59,20 +59,13 @@ func testBasic(t *testing.T, peerCount, threshold uint16, allRandom bool) { dkShares[i] = dkShare } - acsPeers := make([]*commonsubset.CommonSubset, peerCount) - for i := range acsPeers { - ii := i // Use a local copy in the callback. - networkProviders[ii].Attach(&peeringID, func(recv *peering.RecvEvent) { - if acsPeers[ii] != nil { - require.True(t, acsPeers[ii].TryHandleMessage(recv)) - } - }) - } + acsPeers := make([]*CommonSubset, peerCount) for a := range acsPeers { - group, err := networkProviders[a].PeerGroup(peerNetIDs) + group, err := networkProviders[a].PeerGroup(peeringID, peerNetIDs) require.Nil(t, err) acsLog := testlogger.WithLevel(log.Named(fmt.Sprintf("ACS[%02d]", a)), logger.LevelInfo, false) - acsPeers[a], err = commonsubset.NewCommonSubset(0, 0, peeringID, group, dkShares[a], allRandom, nil, acsLog) + acsPeers[a], err = NewCommonSubset(0, 0, group, dkShares[a], allRandom, nil, acsLog) + group.Attach(peering.PeerMessageReceiverCommonSubset, makeReceiveCommitteePeerMessagesFun(acsPeers[a], log)) require.Nil(t, err) } t.Logf("ACS Nodes created.") @@ -115,20 +108,13 @@ func TestRandomized(t *testing.T) { dkShares[i] = dkShare } - acsPeers := make([]*commonsubset.CommonSubset, peerCount) - for i := range acsPeers { - ii := i // Use a local copy in the callback. - networkProviders[ii].Attach(&peeringID, func(recv *peering.RecvEvent) { - if acsPeers[ii] != nil { - require.True(t, acsPeers[ii].TryHandleMessage(recv)) - } - }) - } + acsPeers := make([]*CommonSubset, peerCount) for a := range acsPeers { - group, err := networkProviders[a].PeerGroup(peerNetIDs) + group, err := networkProviders[a].PeerGroup(peeringID, peerNetIDs) require.Nil(t, err) acsLog := testlogger.WithLevel(log.Named(fmt.Sprintf("ACS[%02d]", a)), logger.LevelInfo, false) - acsPeers[a], err = commonsubset.NewCommonSubset(0, 0, peeringID, group, dkShares[a], true, nil, acsLog) + acsPeers[a], err = NewCommonSubset(0, 0, group, dkShares[a], true, nil, acsLog) + group.Attach(peering.PeerMessageReceiverCommonSubset, makeReceiveCommitteePeerMessagesFun(acsPeers[a], log)) require.Nil(t, err) } t.Logf("ACS Nodes created.") @@ -176,13 +162,28 @@ func TestRandomized(t *testing.T) { require.NoError(t, networkCloser.Close()) } +func makeReceiveCommitteePeerMessagesFun(peer *CommonSubset, log *logger.Logger) func(peerMsg *peering.PeerMessageGroupIn) { + return func(peerMsg *peering.PeerMessageGroupIn) { + if peerMsg.MsgType != peerMsgTypeBatch { + panic(fmt.Errorf("Wrong type of committee message: %v", peerMsg.MsgType)) + } + mb, err := newMsgBatch(peerMsg.MsgData) + if err != nil { + log.Error(err) + return + } + peer.HandleMsgBatch(mb) + } +} + func TestCoordinator(t *testing.T) { - t.Run("N=1/T=1", func(tt *testing.T) { testCoordinator(tt, 1, 1) }) - t.Run("N=4/T=3", func(tt *testing.T) { testCoordinator(tt, 4, 3) }) - t.Run("N=10/T=7", func(tt *testing.T) { testCoordinator(tt, 10, 7) }) + t.Run("N=1/T=1/P=1E2", func(tt *testing.T) { testCoordinator(tt, 1, 1, 100) }) + t.Run("N=4/T=3/P=1E2", func(tt *testing.T) { testCoordinator(tt, 4, 3, 100) }) + t.Run("N=10/T=7/P=1E2", func(tt *testing.T) { testCoordinator(tt, 10, 7, 100) }) + t.Run("N=10/T=7/P=1E5", func(tt *testing.T) { testCoordinator(tt, 10, 7, 100000) }) } -func testCoordinator(t *testing.T, peerCount, threshold uint16) { +func testCoordinator(t *testing.T, peerCount, threshold uint16, inputLen int) { log := testlogger.NewLogger(t) defer log.Sync() peeringID := peering.RandomPeeringID() @@ -202,18 +203,12 @@ func testCoordinator(t *testing.T, peerCount, threshold uint16) { dkShares[i] = dkShare } - acsCoords := make([]*commonsubset.CommonSubsetCoordinator, peerCount) + acsCoords := make([]*CommonSubsetCoordinator, peerCount) for i := range acsCoords { - ii := i // Use a local copy in the callback. - group, err := networkProviders[i].PeerGroup(peerNetIDs) + group, err := networkProviders[i].PeerGroup(peeringID, peerNetIDs) require.Nil(t, err) acsLog := testlogger.WithLevel(log.Named(fmt.Sprintf("CSC[%02d]", i)), logger.LevelInfo, false) - acsCoords[i] = commonsubset.NewCommonSubsetCoordinator(peeringID, networkProviders[i], group, dkShares[i], acsLog) - networkProviders[ii].Attach(&peeringID, func(recv *peering.RecvEvent) { - if acsCoords[ii] != nil { - require.True(t, acsCoords[ii].TryHandleMessage(recv)) - } - }) + acsCoords[i] = NewCommonSubsetCoordinator(networkProviders[i], group, dkShares[i], acsLog) } t.Logf("ACS Nodes created.") @@ -223,7 +218,8 @@ func testCoordinator(t *testing.T, peerCount, threshold uint16) { resultsWG.Add(int(peerCount)) for i := range acsCoords { ii := i - input := []byte(peerNetIDs[i]) + input := make([]byte, inputLen) + _, _ = rand.Read(input) acsCoords[i].RunACSConsensus(input, sessionID, 1, func(sid uint64, res [][]byte) { results[ii] = res resultsWG.Done() @@ -244,12 +240,13 @@ func testCoordinator(t *testing.T, peerCount, threshold uint16) { } func TestRandomizedWithCC(t *testing.T) { - t.Run("N=1/T=1", func(tt *testing.T) { testRandomizedWithCC(tt, 1, 1) }) - t.Run("N=4/T=3", func(tt *testing.T) { testRandomizedWithCC(tt, 4, 3) }) - t.Run("N=10/T=7", func(tt *testing.T) { testRandomizedWithCC(tt, 10, 7) }) + t.Run("N=1/T=1/P=1E2", func(tt *testing.T) { testRandomizedWithCC(tt, 1, 1, 100) }) + t.Run("N=4/T=3/P=1E2", func(tt *testing.T) { testRandomizedWithCC(tt, 4, 3, 100) }) + t.Run("N=10/T=7/P=1E2", func(tt *testing.T) { testRandomizedWithCC(tt, 10, 7, 100) }) + t.Run("N=10/T=7/P=1E5", func(tt *testing.T) { testRandomizedWithCC(tt, 10, 7, 100000) }) } -func testRandomizedWithCC(t *testing.T, peerCount, threshold uint16) { +func testRandomizedWithCC(t *testing.T, peerCount, threshold uint16, inputLen int) { log := testlogger.NewLogger(t) defer log.Sync() peeringID := peering.RandomPeeringID() @@ -268,19 +265,13 @@ func testRandomizedWithCC(t *testing.T, peerCount, threshold uint16) { } dkAddress, dkShares := testpeers.SetupDkgPregenerated(t, threshold, peerNetIDs, tcrypto.DefaultSuite()) - acsCoords := make([]*commonsubset.CommonSubsetCoordinator, peerCount) + acsCoords := make([]*CommonSubsetCoordinator, peerCount) for i := range acsCoords { - ii := i // Use a local copy in the callback. - group, err := networkProviders[i].PeerGroup(peerNetIDs) + group, err := networkProviders[i].PeerGroup(peeringID, peerNetIDs) require.Nil(t, err) dkShare, err := dkShares[i].LoadDKShare(dkAddress) require.Nil(t, err) - acsCoords[i] = commonsubset.NewCommonSubsetCoordinator(peeringID, networkProviders[i], group, dkShare, logs[i]) - networkProviders[ii].Attach(&peeringID, func(recv *peering.RecvEvent) { - if acsCoords[ii] != nil { - acsCoords[ii].TryHandleMessage(recv) - } - }) + acsCoords[i] = NewCommonSubsetCoordinator(networkProviders[i], group, dkShare, logs[i]) } t.Logf("ACS Nodes created.") @@ -290,7 +281,8 @@ func testRandomizedWithCC(t *testing.T, peerCount, threshold uint16) { resultsWG.Add(int(peerCount)) for i := range acsCoords { ii := i - input := []byte(peerNetIDs[i]) + input := make([]byte, inputLen) + _, _ = rand.Read(input) acsCoords[i].RunACSConsensus(input, sessionID, 1, func(sid uint64, res [][]byte) { results[ii] = res resultsWG.Done() diff --git a/packages/chain/consensus/commonsubset/commonsubsetcoordinator.go b/packages/chain/consensus/commonsubset/commonsubsetcoordinator.go index f4b858b4bd..9110522e14 100644 --- a/packages/chain/consensus/commonsubset/commonsubsetcoordinator.go +++ b/packages/chain/consensus/commonsubset/commonsubsetcoordinator.go @@ -16,6 +16,8 @@ import ( const ( futureInstances = 5 // How many future instances to accept. pastInstances = 2 // How many past instance to keep not closed. + + peerMsgTypeBatch = iota ) // CommonSubsetCoordinator is responsible for maintaining a series of ACS @@ -42,37 +44,38 @@ const ( // until they will be discarded because of the growing StateIndex in the new branch. // type CommonSubsetCoordinator struct { - csInsts map[uint64]*CommonSubset // The actual instances can be created on request or on peer message. - csAsked map[uint64]bool // Indicates, which instances are already asked by this nodes. - currentStateIndex uint32 // Last state index passed by this node. - lock sync.RWMutex + csInsts map[uint64]*CommonSubset // The actual instances can be created on request or on peer message. + csAsked map[uint64]bool // Indicates, which instances are already asked by this nodes. + currentStateIndex uint32 // Last state index passed by this node. + receivePeerMessagesAttachID interface{} + lock sync.RWMutex - peeringID peering.PeeringID - netGroup peering.GroupProvider - dkShare *tcrypto.DKShare - log *logger.Logger + netGroup peering.GroupProvider + dkShare *tcrypto.DKShare + log *logger.Logger } func NewCommonSubsetCoordinator( - peeringID peering.PeeringID, net peering.NetworkProvider, netGroup peering.GroupProvider, dkShare *tcrypto.DKShare, log *logger.Logger, ) *CommonSubsetCoordinator { - return &CommonSubsetCoordinator{ - csInsts: make(map[uint64]*CommonSubset), - csAsked: make(map[uint64]bool), - lock: sync.RWMutex{}, - peeringID: peeringID, - netGroup: netGroup, - dkShare: dkShare, - log: log, + ret := &CommonSubsetCoordinator{ + csInsts: make(map[uint64]*CommonSubset), + csAsked: make(map[uint64]bool), + lock: sync.RWMutex{}, + netGroup: netGroup, + dkShare: dkShare, + log: log, } + ret.receivePeerMessagesAttachID = ret.netGroup.Attach(peering.PeerMessageReceiverCommonSubset, ret.receiveCommitteePeerMessages) + return ret } // Close implements the AsynchronousCommonSubsetRunner interface. func (csc *CommonSubsetCoordinator) Close() { + csc.netGroup.Detach(csc.receivePeerMessagesAttachID) for i := range csc.csInsts { csc.csInsts[i].Close() } @@ -104,24 +107,23 @@ func (csc *CommonSubsetCoordinator) RunACSConsensus( // TryHandleMessage implements the AsynchronousCommonSubsetRunner interface. // It handles the network messages, if they are of correct type. -func (csc *CommonSubsetCoordinator) TryHandleMessage(recv *peering.RecvEvent) bool { - if recv.Msg.MsgType != acsMsgType { - return false +func (csc *CommonSubsetCoordinator) receiveCommitteePeerMessages(peerMsg *peering.PeerMessageGroupIn) { + if peerMsg.MsgType != peerMsgTypeBatch { + csc.log.Warnf("Wrong type of committee message: %v, ignoring it", peerMsg.MsgType) + return } - mb := msgBatch{} - if err := mb.FromBytes(recv.Msg.MsgData); err != nil { - csc.log.Errorf("Cannot decode message: %v", err) - return true + mb, err := newMsgBatch(peerMsg.MsgData) + if err != nil { + csc.log.Error(err) + return } - csc.log.Debugf("ACS::IO - Received a msgBatch=%+v", mb) - var err error + csc.log.Debugf("ACS::IO - Received a msgBatch=%+v", *mb) var cs *CommonSubset if cs, err = csc.getOrCreateCS(mb.sessionID, mb.stateIndex, nil); err != nil { csc.log.Debugf("Unable to get a CommonSubset instance for sessionID=%v, reason=%v", mb.sessionID, err) - return true + return } - cs.HandleMsgBatch(&mb) - return true + cs.HandleMsgBatch(mb) } func (csc *CommonSubsetCoordinator) getOrCreateCS( @@ -167,7 +169,7 @@ func (csc *CommonSubsetCoordinator) getOrCreateCS( var err error var newCS *CommonSubset outCh := make(chan map[uint16][]byte, 1) - if newCS, err = NewCommonSubset(sessionID, stateIndex, csc.peeringID, csc.netGroup, csc.dkShare, false, outCh, csc.log); err != nil { + if newCS, err = NewCommonSubset(sessionID, stateIndex, csc.netGroup, csc.dkShare, false, outCh, csc.log); err != nil { return nil, err } csc.csInsts[sessionID] = newCS diff --git a/packages/chain/consensus/consensus.go b/packages/chain/consensus/consensus.go index fb122f61a0..ea579de2d8 100644 --- a/packages/chain/consensus/consensus.go +++ b/packages/chain/consensus/consensus.go @@ -15,18 +15,21 @@ import ( "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/assert" "github.com/iotaledger/wasp/packages/metrics" + "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/state" + "github.com/iotaledger/wasp/packages/util/pipe" "github.com/iotaledger/wasp/packages/vm" "github.com/iotaledger/wasp/packages/vm/runvm" "go.uber.org/atomic" ) -type Consensus struct { +type consensus struct { isReady atomic.Bool chain chain.ChainCore committee chain.Committee + committeePeerGroup peering.GroupProvider mempool chain.Mempool - nodeConn chain.NodeConnection + nodeConn chain.ChainNodeConnection vmRunner vm.VMRunner currentState state.VirtualStateAccess stateOutput *ledgerstate.AliasOutput @@ -43,7 +46,7 @@ type Consensus struct { delaySendingSignedResult time.Time resultTxEssence *ledgerstate.TransactionEssence resultState state.VirtualStateAccess - resultSignatures []*messages.SignedResultMsg + resultSignatures []*messages.SignedResultMsgIn resultSigAck []uint16 finalTx *ledgerstate.Transaction postTxDeadline time.Time @@ -52,18 +55,18 @@ type Consensus struct { consensusInfoSnapshot atomic.Value timers ConsensusTimers log *logger.Logger - eventStateTransitionMsgCh chan *messages.StateTransitionMsg - eventSignedResultMsgCh chan *messages.SignedResultMsg - eventSignedResultAckMsgCh chan *messages.SignedResultAckMsg - eventInclusionStateMsgCh chan *messages.InclusionStateMsg - eventACSMsgCh chan *messages.AsynchronousCommonSubsetMsg - eventVMResultMsgCh chan *messages.VMResultMsg - eventTimerMsgCh chan messages.TimerTick - closeCh chan struct{} + eventStateTransitionMsgPipe pipe.Pipe + eventSignedResultMsgPipe pipe.Pipe + eventSignedResultAckMsgPipe pipe.Pipe + eventInclusionStateMsgPipe pipe.Pipe + eventACSMsgPipe pipe.Pipe + eventVMResultMsgPipe pipe.Pipe + eventTimerMsgPipe pipe.Pipe assert assert.Assert missingRequestsFromBatch map[iscp.RequestID][32]byte missingRequestsMutex sync.Mutex pullMissingRequestsFromCommittee bool + receivePeerMessagesAttachID interface{} consensusMetrics metrics.ConsensusMetrics } @@ -79,9 +82,16 @@ type workflowFlags struct { inProgress bool } -var _ chain.Consensus = &Consensus{} +var _ chain.Consensus = &consensus{} -func New(chainCore chain.ChainCore, mempool chain.Mempool, committee chain.Committee, nodeConn chain.NodeConnection, pullMissingRequestsFromCommittee bool, consensusMetrics metrics.ConsensusMetrics, timersOpt ...ConsensusTimers) *Consensus { +const ( + peerMsgTypeSignedResult = iota + peerMsgTypeSignedResultAck + + 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 { var timers ConsensusTimers if len(timersOpt) > 0 { timers = timersOpt[0] @@ -89,47 +99,103 @@ func New(chainCore chain.ChainCore, mempool chain.Mempool, committee chain.Commi timers = NewConsensusTimers() } log := chainCore.Log().Named("c") - ret := &Consensus{ + ret := &consensus{ chain: chainCore, committee: committee, + committeePeerGroup: peerGroup, mempool: mempool, nodeConn: nodeConn, vmRunner: runvm.NewVMRunner(), - resultSignatures: make([]*messages.SignedResultMsg, committee.Size()), + resultSignatures: make([]*messages.SignedResultMsgIn, committee.Size()), resultSigAck: make([]uint16, 0, committee.Size()), timers: timers, log: log, - eventStateTransitionMsgCh: make(chan *messages.StateTransitionMsg), - eventSignedResultMsgCh: make(chan *messages.SignedResultMsg), - eventSignedResultAckMsgCh: make(chan *messages.SignedResultAckMsg), - eventInclusionStateMsgCh: make(chan *messages.InclusionStateMsg), - eventACSMsgCh: make(chan *messages.AsynchronousCommonSubsetMsg), - eventVMResultMsgCh: make(chan *messages.VMResultMsg), - eventTimerMsgCh: make(chan messages.TimerTick), - closeCh: make(chan struct{}), + eventStateTransitionMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + eventSignedResultMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + eventSignedResultAckMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + eventInclusionStateMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + eventACSMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + eventVMResultMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + eventTimerMsgPipe: pipe.NewLimitInfinitePipe(1), assert: assert.NewAssert(log), pullMissingRequestsFromCommittee: pullMissingRequestsFromCommittee, consensusMetrics: consensusMetrics, } + ret.receivePeerMessagesAttachID = ret.committeePeerGroup.Attach(peering.PeerMessageReceiverConsensus, ret.receiveCommitteePeerMessages) + ret.nodeConn.AttachToInclusionStateReceived(func(txID ledgerstate.TransactionID, inclusionState ledgerstate.InclusionState) { + ret.EnqueueInclusionsStateMsg(txID, inclusionState) + }) ret.refreshConsensusInfo() go ret.recvLoop() return ret } -func (c *Consensus) IsReady() bool { +func (c *consensus) receiveCommitteePeerMessages(peerMsg *peering.PeerMessageGroupIn) { + switch peerMsg.MsgType { + case peerMsgTypeSignedResult: + msg, err := messages.NewSignedResultMsg(peerMsg.MsgData) + if err != nil { + c.log.Error(err) + return + } + c.EnqueueSignedResultMsg(&messages.SignedResultMsgIn{ + SignedResultMsg: *msg, + SenderIndex: peerMsg.SenderIndex, + }) + case peerMsgTypeSignedResultAck: + msg, err := messages.NewSignedResultAckMsg(peerMsg.MsgData) + if err != nil { + c.log.Error(err) + return + } + c.EnqueueSignedResultAckMsg(&messages.SignedResultAckMsgIn{ + SignedResultAckMsg: *msg, + SenderIndex: peerMsg.SenderIndex, + }) + default: + c.log.Warnf("Wrong type of consensus message: %v, ignoring it", peerMsg.MsgType) + } +} + +func (c *consensus) IsReady() bool { return c.isReady.Load() } -func (c *Consensus) Close() { - close(c.closeCh) +func (c *consensus) Close() { + c.nodeConn.DetachFromInclusionStateReceived() + c.committeePeerGroup.Detach(c.receivePeerMessagesAttachID) + + c.eventStateTransitionMsgPipe.Close() + c.eventSignedResultMsgPipe.Close() + c.eventSignedResultAckMsgPipe.Close() + c.eventInclusionStateMsgPipe.Close() + c.eventACSMsgPipe.Close() + c.eventVMResultMsgPipe.Close() + c.eventTimerMsgPipe.Close() } -func (c *Consensus) recvLoop() { +func (c *consensus) recvLoop() { + eventStateTransitionMsgCh := c.eventStateTransitionMsgPipe.Out() + eventSignedResultMsgCh := c.eventSignedResultMsgPipe.Out() + eventSignedResultAckMsgCh := c.eventSignedResultAckMsgPipe.Out() + eventInclusionStateMsgCh := c.eventInclusionStateMsgPipe.Out() + eventACSMsgCh := c.eventACSMsgPipe.Out() + eventVMResultMsgCh := c.eventVMResultMsgPipe.Out() + eventTimerMsgCh := c.eventTimerMsgPipe.Out() + isClosedFun := func() bool { + return eventStateTransitionMsgCh == nil && + eventSignedResultMsgCh == nil && + eventSignedResultAckMsgCh == nil && + eventInclusionStateMsgCh == nil && + eventACSMsgCh == nil && + eventVMResultMsgCh == nil && + eventTimerMsgCh == nil + } + // wait at startup for !c.committee.IsReady() { - select { - case <-time.After(100 * time.Millisecond): - case <-c.closeCh: + time.Sleep(100 * time.Millisecond) + if isClosedFun() { return } } @@ -137,55 +203,70 @@ func (c *Consensus) recvLoop() { c.isReady.Store(true) for { select { - case msg, ok := <-c.eventStateTransitionMsgCh: + case msg, ok := <-eventStateTransitionMsgCh: if ok { c.log.Debugf("Consensus::recvLoop, eventStateTransitionMsg...") - c.eventStateTransitionMsg(msg) + c.handleStateTransitionMsg(msg.(*messages.StateTransitionMsg)) c.log.Debugf("Consensus::recvLoop, eventStateTransitionMsg... Done") + } else { + eventStateTransitionMsgCh = nil } - case msg, ok := <-c.eventSignedResultMsgCh: + case msg, ok := <-eventSignedResultMsgCh: if ok { - c.log.Debugf("Consensus::recvLoop, eventSignedResult...") - c.eventSignedResult(msg) - c.log.Debugf("Consensus::recvLoop, eventSignedResult... Done") + c.log.Debugf("Consensus::recvLoop, handleSignedResultMsg...") + c.handleSignedResultMsg(msg.(*messages.SignedResultMsgIn)) + c.log.Debugf("Consensus::recvLoop, handleSignedResultMsg... Done") + } else { + eventSignedResultMsgCh = nil } - case msg, ok := <-c.eventSignedResultAckMsgCh: + case msg, ok := <-eventSignedResultAckMsgCh: if ok { - c.log.Debugf("Consensus::recvLoop, eventSignedResultAck...") - c.eventSignedResultAck(msg) - c.log.Debugf("Consensus::recvLoop, eventSignedResultAck... Done") + c.log.Debugf("Consensus::recvLoop, handleSignedResultAckMsg...") + c.handleSignedResultAckMsg(msg.(*messages.SignedResultAckMsgIn)) + c.log.Debugf("Consensus::recvLoop, handleSignedResultAckMsg... Done") + } else { + eventSignedResultAckMsgCh = nil } - case msg, ok := <-c.eventInclusionStateMsgCh: + case msg, ok := <-eventInclusionStateMsgCh: if ok { c.log.Debugf("Consensus::recvLoop, eventInclusionState...") - c.eventInclusionState(msg) + c.handleInclusionState(msg.(*messages.InclusionStateMsg)) c.log.Debugf("Consensus::recvLoop, eventInclusionState... Done") + } else { + eventInclusionStateMsgCh = nil } - case msg, ok := <-c.eventACSMsgCh: + case msg, ok := <-eventACSMsgCh: if ok { c.log.Debugf("Consensus::recvLoop, eventAsynchronousCommonSubset...") - c.eventAsynchronousCommonSubset(msg) + c.handleAsynchronousCommonSubset(msg.(*messages.AsynchronousCommonSubsetMsg)) c.log.Debugf("Consensus::recvLoop, eventAsynchronousCommonSubset... Done") + } else { + eventACSMsgCh = nil } - case msg, ok := <-c.eventVMResultMsgCh: + case msg, ok := <-eventVMResultMsgCh: if ok { c.log.Debugf("Consensus::recvLoop, eventVMResultMsg...") - c.eventVMResultMsg(msg) + c.handleVMResultMsg(msg.(*messages.VMResultMsg)) c.log.Debugf("Consensus::recvLoop, eventVMResultMsg... Done") + } else { + eventVMResultMsgCh = nil } - case msg, ok := <-c.eventTimerMsgCh: + case msg, ok := <-eventTimerMsgCh: if ok { c.log.Debugf("Consensus::recvLoop, eventTimerMsg...") - c.eventTimerMsg(msg) + c.handleTimerMsg(msg.(messages.TimerTick)) c.log.Debugf("Consensus::recvLoop, eventTimerMsg... Done") + } else { + eventTimerMsgCh = nil } - case <-c.closeCh: + } + if isClosedFun() { return } } } -func (c *Consensus) refreshConsensusInfo() { +func (c *consensus) refreshConsensusInfo() { index := uint32(0) if c.currentState != nil { index = c.currentState.BlockIndex() @@ -206,7 +287,7 @@ func (c *Consensus) refreshConsensusInfo() { c.consensusInfoSnapshot.Store(consensusInfo) } -func (c *Consensus) GetStatusSnapshot() *chain.ConsensusInfo { +func (c *consensus) GetStatusSnapshot() *chain.ConsensusInfo { ret := c.consensusInfoSnapshot.Load() if ret == nil { return nil diff --git a/packages/chain/consensus/eventproc.go b/packages/chain/consensus/eventproc.go index 4b0b3e8d3c..8f5d3247d2 100644 --- a/packages/chain/consensus/eventproc.go +++ b/packages/chain/consensus/eventproc.go @@ -5,72 +5,83 @@ package consensus import ( "fmt" + "time" + "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/wasp/packages/chain/messages" "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/state" ) -func (c *Consensus) EventStateTransitionMsg(msg *messages.StateTransitionMsg) { - c.eventStateTransitionMsgCh <- msg +func (c *consensus) EnqueueStateTransitionMsg(virtualState state.VirtualStateAccess, stateOutput *ledgerstate.AliasOutput, stateTimestamp time.Time) { + c.eventStateTransitionMsgPipe.In() <- &messages.StateTransitionMsg{ + State: virtualState, + StateOutput: stateOutput, + StateTimestamp: stateTimestamp, + } } -func (c *Consensus) eventStateTransitionMsg(msg *messages.StateTransitionMsg) { +func (c *consensus) handleStateTransitionMsg(msg *messages.StateTransitionMsg) { c.log.Debugf("StateTransitionMsg received: state index: %d, state output: %s, timestamp: %v", msg.State.BlockIndex(), iscp.OID(msg.StateOutput.ID()), msg.StateTimestamp) - c.setNewState(msg) - c.takeAction() + if c.setNewState(msg) { + c.takeAction() + } } -func (c *Consensus) EventSignedResultMsg(msg *messages.SignedResultMsg) { - c.eventSignedResultMsgCh <- msg +func (c *consensus) EnqueueSignedResultMsg(msg *messages.SignedResultMsgIn) { + c.eventSignedResultMsgPipe.In() <- msg } -func (c *Consensus) eventSignedResult(msg *messages.SignedResultMsg) { - c.log.Debugf("SignedResultMsg received: from sender %d, hash=%s, chain input id=%v", +func (c *consensus) handleSignedResultMsg(msg *messages.SignedResultMsgIn) { + c.log.Debugf("handleSignedResultMsg message received: from sender %d, hash=%s, chain input id=%v", msg.SenderIndex, msg.EssenceHash, iscp.OID(msg.ChainInputID)) c.receiveSignedResult(msg) c.takeAction() } -func (c *Consensus) EventSignedResultAckMsg(msg *messages.SignedResultAckMsg) { - c.eventSignedResultAckMsgCh <- msg +func (c *consensus) EnqueueSignedResultAckMsg(msg *messages.SignedResultAckMsgIn) { + c.eventSignedResultAckMsgPipe.In() <- msg } -func (c *Consensus) eventSignedResultAck(msg *messages.SignedResultAckMsg) { +func (c *consensus) handleSignedResultAckMsg(msg *messages.SignedResultAckMsgIn) { c.log.Debugf("SignedResultAckMsg received: from sender %d, hash=%s, chain input id=%v", msg.SenderIndex, msg.EssenceHash, iscp.OID(msg.ChainInputID)) c.receiveSignedResultAck(msg) c.takeAction() } -func (c *Consensus) EventInclusionsStateMsg(msg *messages.InclusionStateMsg) { - c.eventInclusionStateMsgCh <- msg +func (c *consensus) EnqueueInclusionsStateMsg(txID ledgerstate.TransactionID, inclusionState ledgerstate.InclusionState) { + c.eventInclusionStateMsgPipe.In() <- &messages.InclusionStateMsg{ + TxID: txID, + State: inclusionState, + } } -func (c *Consensus) eventInclusionState(msg *messages.InclusionStateMsg) { +func (c *consensus) handleInclusionState(msg *messages.InclusionStateMsg) { c.log.Debugf("InclusionStateMsg received: %s: '%s'", msg.TxID.Base58(), msg.State.String()) c.processInclusionState(msg) c.takeAction() } -func (c *Consensus) EventAsynchronousCommonSubsetMsg(msg *messages.AsynchronousCommonSubsetMsg) { - c.eventACSMsgCh <- msg +func (c *consensus) EnqueueAsynchronousCommonSubsetMsg(msg *messages.AsynchronousCommonSubsetMsg) { + c.eventACSMsgPipe.In() <- msg } -func (c *Consensus) eventAsynchronousCommonSubset(msg *messages.AsynchronousCommonSubsetMsg) { +func (c *consensus) handleAsynchronousCommonSubset(msg *messages.AsynchronousCommonSubsetMsg) { c.log.Debugf("AsynchronousCommonSubsetMsg received for session %v: len = %d", msg.SessionID, len(msg.ProposedBatchesBin)) c.receiveACS(msg.ProposedBatchesBin, msg.SessionID) c.takeAction() } -func (c *Consensus) EventVMResultMsg(msg *messages.VMResultMsg) { - c.eventVMResultMsgCh <- msg +func (c *consensus) EnqueueVMResultMsg(msg *messages.VMResultMsg) { + c.eventVMResultMsgPipe.In() <- msg } -func (c *Consensus) eventVMResultMsg(msg *messages.VMResultMsg) { +func (c *consensus) handleVMResultMsg(msg *messages.VMResultMsg) { var essenceString string if msg.Task.ResultTransactionEssence == nil { essenceString = "essence is nil" @@ -83,11 +94,11 @@ func (c *Consensus) eventVMResultMsg(msg *messages.VMResultMsg) { c.takeAction() } -func (c *Consensus) EventTimerMsg(msg messages.TimerTick) { - c.eventTimerMsgCh <- msg +func (c *consensus) EnqueueTimerMsg(msg messages.TimerTick) { + c.eventTimerMsgPipe.In() <- msg } -func (c *Consensus) eventTimerMsg(msg messages.TimerTick) { +func (c *consensus) handleTimerMsg(msg messages.TimerTick) { c.lastTimerTick.Store(int64(msg)) c.refreshConsensusInfo() if msg%40 == 0 { diff --git a/packages/chain/consensus/setup_test.go b/packages/chain/consensus/setup_test.go index 58a6aa3f87..c78ead2e88 100644 --- a/packages/chain/consensus/setup_test.go +++ b/packages/chain/consensus/setup_test.go @@ -4,7 +4,6 @@ package consensus import ( - "bytes" "fmt" "io" "math/rand" @@ -12,9 +11,6 @@ import ( "testing" "time" - "github.com/iotaledger/wasp/packages/iscp/colored" - "github.com/iotaledger/wasp/packages/metrics" - "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/goshimmer/packages/ledgerstate/utxodb" "github.com/iotaledger/goshimmer/packages/ledgerstate/utxoutil" @@ -28,8 +24,11 @@ import ( "github.com/iotaledger/wasp/packages/chain/messages" "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/iscp/colored" "github.com/iotaledger/wasp/packages/iscp/coreutil" + "github.com/iotaledger/wasp/packages/iscp/request" "github.com/iotaledger/wasp/packages/kv" + "github.com/iotaledger/wasp/packages/metrics" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/registry" "github.com/iotaledger/wasp/packages/solo" @@ -186,8 +185,8 @@ func (env *MockedEnv) NewNode(nodeIndex uint16, timers ConsensusTimers) *mockedN ret.Log.Infof("stored transaction to the ledger: %s", tx.ID().Base58()) for _, node := range env.Nodes { go func(n *mockedNode) { - ret.mutex.Lock() - defer ret.mutex.Unlock() + n.mutex.Lock() + defer n.mutex.Unlock() n.StateOutput = stateOutput n.checkStateApproval() }(node) @@ -196,12 +195,9 @@ func (env *MockedEnv) NewNode(nodeIndex uint16, timers ConsensusTimers) *mockedN ret.Log.Infof("transaction already in the ledger: %s", tx.ID().Base58()) } }) - ret.NodeConn.OnPullTransactionInclusionState(func(addr ledgerstate.Address, txid ledgerstate.TransactionID) { + ret.NodeConn.OnPullTransactionInclusionState(func(txid ledgerstate.TransactionID) { if _, already := env.Ledger.GetTransaction(txid); already { - go ret.ChainCore.ReceiveMessage(&messages.InclusionStateMsg{ - TxID: txid, - State: ledgerstate.Confirmed, - }) + go ret.Consensus.EnqueueInclusionsStateMsg(txid, ledgerstate.Confirmed) } }) mempoolMetrics := metrics.DefaultChainMetrics() @@ -221,7 +217,7 @@ func (env *MockedEnv) NewNode(nodeIndex uint16, timers ConsensusTimers) *mockedN Address: env.StateAddress, Nodes: env.NodeIDs, } - cmt, err := committee.New( + cmt, cmtPeerGroup, err := committee.New( cmtRec, env.ChainID, env.NetworkProviders[nodeIndex], @@ -231,57 +227,60 @@ func (env *MockedEnv) NewNode(nodeIndex uint16, timers ConsensusTimers) *mockedN acs..., ) require.NoError(env.T, err) - cmt.Attach(ret.ChainCore) + cmtPeerGroup.Attach(peering.PeerMessageReceiverConsensus, func(peerMsg *peering.PeerMessageGroupIn) { + log.Debugf("Consensus received peer message from %v of type %v", peerMsg.SenderNetID, peerMsg.MsgType) + switch peerMsg.MsgType { + case peerMsgTypeSignedResult: + msg, err := messages.NewSignedResultMsg(peerMsg.MsgData) + if err != nil { + log.Error(err) + return + } + ret.Consensus.EnqueueSignedResultMsg(&messages.SignedResultMsgIn{ + SignedResultMsg: *msg, + SenderIndex: peerMsg.SenderIndex, + }) + case peerMsgTypeSignedResultAck: + msg, err := messages.NewSignedResultAckMsg(peerMsg.MsgData) + if err != nil { + log.Error(err) + return + } + ret.Consensus.EnqueueSignedResultAckMsg(&messages.SignedResultAckMsgIn{ + SignedResultAckMsg: *msg, + SenderIndex: peerMsg.SenderIndex, + }) + } + }) ret.StateOutput = env.InitStateOutput ret.SolidState, err = state.CreateOriginState(ret.store, env.ChainID) ret.stateSync.SetSolidIndex(0) require.NoError(env.T, err) - cons := New(ret.ChainCore, ret.Mempool, cmt, ret.NodeConn, true, metrics.DefaultChainMetrics(), timers) - cons.vmRunner = testchain.NewMockedVMRunner(env.T, log) + cons := New(ret.ChainCore, ret.Mempool, cmt, cmtPeerGroup, ret.NodeConn, true, metrics.DefaultChainMetrics(), timers) + cons.(*consensus).vmRunner = testchain.NewMockedVMRunner(env.T, log) ret.Consensus = cons - ret.ChainCore.OnReceiveAsynchronousCommonSubsetMsg(func(msg *messages.AsynchronousCommonSubsetMsg) { - ret.Consensus.EventAsynchronousCommonSubsetMsg(msg) - }) - ret.ChainCore.OnReceiveVMResultMsg(func(msg *messages.VMResultMsg) { - ret.Consensus.EventVMResultMsg(msg) - }) - ret.ChainCore.OnReceiveInclusionStateMsg(func(msg *messages.InclusionStateMsg) { - ret.Consensus.EventInclusionsStateMsg(msg) - }) - ret.ChainCore.OnReceiveStateCandidateMsg(func(msg *messages.StateCandidateMsg) { - ret.mutex.Lock() - defer ret.mutex.Unlock() - newState := msg.State - ret.Log.Infof("chainCore.StateCandidateMsg: state hash: %s, approving output: %s", - msg.State.StateCommitment(), iscp.OID(msg.ApprovingOutputID)) - - if ret.SolidState != nil && ret.SolidState.BlockIndex() == newState.BlockIndex() { - ret.Log.Debugf("new state already committed for index %d", newState.BlockIndex()) - return - } - err := newState.Commit() - require.NoError(env.T, err) - - ret.SolidState = newState - ret.Log.Debugf("committed new state for index %d", newState.BlockIndex()) + ret.ChainCore.OnStateCandidate(func(newState state.VirtualStateAccess, approvingOutputID ledgerstate.OutputID) { + go func() { + ret.mutex.Lock() + defer ret.mutex.Unlock() + ret.Log.Infof("chainCore.StateCandidateMsg: state hash: %s, approving output: %s", + newState.StateCommitment(), iscp.OID(approvingOutputID)) - ret.checkStateApproval() - }) - ret.ChainCore.OnReceivePeerMessage(func(msg *peering.PeerMessage) { - var err error - if msg.MsgType == messages.MsgSignedResult { - decoded := messages.SignedResultMsg{} - if err = decoded.Read(bytes.NewReader(msg.MsgData)); err == nil { - decoded.SenderIndex = msg.SenderIndex - ret.Consensus.EventSignedResultMsg(&decoded) + if ret.SolidState != nil && ret.SolidState.BlockIndex() == newState.BlockIndex() { + ret.Log.Debugf("new state already committed for index %d", newState.BlockIndex()) + return } - } - if err != nil { - ret.Log.Errorf("unexpected peer message type = %d", msg.MsgType) - } + err := newState.Commit() + require.NoError(env.T, err) + + ret.SolidState = newState + ret.Log.Debugf("committed new state for index %d", newState.BlockIndex()) + + ret.checkStateApproval() + }() }) return ret } @@ -336,11 +335,7 @@ func (n *mockedNode) EventStateTransition() { n.ChainCore.GlobalStateSync().SetSolidIndex(n.SolidState.BlockIndex()) - n.Consensus.EventStateTransitionMsg(&messages.StateTransitionMsg{ - State: n.SolidState.Copy(), - StateOutput: n.StateOutput, - StateTimestamp: time.Now(), - }) + n.Consensus.EnqueueStateTransitionMsg(n.SolidState.Copy(), n.StateOutput, time.Now()) } func (env *MockedEnv) StartTimers() { @@ -354,7 +349,7 @@ func (n *mockedNode) StartTimer() { go func() { counter := 0 for { - n.Consensus.EventTimerMsg(messages.TimerTick(counter)) + n.Consensus.EnqueueTimerMsg(messages.TimerTick(counter)) counter++ time.Sleep(50 * time.Millisecond) } @@ -432,22 +427,20 @@ func (env *MockedEnv) WaitForEventFromNodesQuorum(waitName string, quorum int, i } func (env *MockedEnv) PostDummyRequests(n int, randomize ...bool) { - reqs := make([]iscp.Request, n) + reqs := make([]*request.OffLedger, n) for i := 0; i < n; i++ { reqs[i] = solo.NewCallParams("dummy", "dummy", "c", i). - NewRequestOffLedger(env.OriginatorKeyPair) + NewRequestOffLedger(iscp.RandomChainID(), env.OriginatorKeyPair) } rnd := len(randomize) > 0 && randomize[0] for _, n := range env.Nodes { - if rnd { - for _, req := range reqs { - go func(node *mockedNode, r iscp.Request) { + for _, req := range reqs { + go func(node *mockedNode, r *request.OffLedger) { + if rnd { time.Sleep(time.Duration(rand.Intn(50)) * time.Millisecond) - node.Mempool.ReceiveRequests(r) - }(n, req) - } - } else { - n.Mempool.ReceiveRequests(reqs...) + } + node.Mempool.ReceiveRequest(r) + }(n, req) } } } diff --git a/packages/chain/mempool/mempool.go b/packages/chain/mempool/mempool.go index 7110585881..0150d8ebef 100644 --- a/packages/chain/mempool/mempool.go +++ b/packages/chain/mempool/mempool.go @@ -20,7 +20,7 @@ import ( "github.com/iotaledger/wasp/packages/vm/core/blocklog" ) -type Mempool struct { +type mempool struct { inBuffer map[iscp.RequestID]iscp.Request inMutex sync.RWMutex poolMutex sync.RWMutex @@ -47,10 +47,10 @@ const ( moveToPoolLoopDelay = 20 * time.Millisecond ) -var _ chain.Mempool = &Mempool{} +var _ chain.Mempool = &mempool{} -func New(stateReader state.OptimisticStateReader, blobCache registry.BlobCache, log *logger.Logger, mempoolMetrics metrics.MempoolMetrics, solidificationLoopDelay ...time.Duration) *Mempool { - ret := &Mempool{ +func New(stateReader state.OptimisticStateReader, blobCache registry.BlobCache, log *logger.Logger, mempoolMetrics metrics.MempoolMetrics, solidificationLoopDelay ...time.Duration) chain.Mempool { + ret := &mempool{ inBuffer: make(map[iscp.RequestID]iscp.Request), stateReader: stateReader, pool: make(map[iscp.RequestID]*requestRef), @@ -69,7 +69,7 @@ func New(stateReader state.OptimisticStateReader, blobCache registry.BlobCache, return ret } -func (m *Mempool) addToInBuffer(req iscp.Request) bool { +func (m *mempool) addToInBuffer(req iscp.Request) bool { // just check if it is already in the pool if m.HasRequest(req.ID()) { return false @@ -82,7 +82,7 @@ func (m *Mempool) addToInBuffer(req iscp.Request) bool { return true } -func (m *Mempool) removeFromInBuffer(req iscp.Request) { +func (m *mempool) removeFromInBuffer(req iscp.Request) { m.inMutex.Lock() defer m.inMutex.Unlock() if _, ok := m.inBuffer[req.ID()]; ok { @@ -92,7 +92,7 @@ func (m *Mempool) removeFromInBuffer(req iscp.Request) { } // fills up the buffer with requests from the in-buffer -func (m *Mempool) takeInBuffer(buf []iscp.Request) []iscp.Request { +func (m *mempool) takeInBuffer(buf []iscp.Request) []iscp.Request { buf = buf[:0] m.inMutex.RLock() defer m.inMutex.RUnlock() @@ -105,14 +105,7 @@ func (m *Mempool) takeInBuffer(buf []iscp.Request) []iscp.Request { // addToPool adds request to the pool. It may fail // returns true if it must be removed from the input buffer -func (m *Mempool) addToPool(req iscp.Request) bool { - if offLedgerReq, ok := req.(*request.OffLedger); ok { - if !offLedgerReq.VerifySignature() { - // wrong signature, must be removed from in buffer - m.log.Warnf("ReceiveRequest.VerifySignature: invalid signature") - return true - } - } +func (m *mempool) addToPool(req iscp.Request) bool { reqid := req.ID() // checking in the state if request is processed. Reading may fail @@ -152,39 +145,31 @@ func (m *Mempool) addToPool(req iscp.Request) bool { return true } +func (m *mempool) countRequestInMetrics(req iscp.Request) { + // TODO refactor, this should be part of metrics logic. + if req.IsOffLedger() { + m.mempoolMetrics.CountOffLedgerRequestIn() + } else { + m.mempoolMetrics.CountOnLedgerRequestIn() + } +} + // ReceiveRequests places requests into the inBuffer. InBuffer is unordered and non-deterministic -func (m *Mempool) ReceiveRequests(reqs ...iscp.Request) { +func (m *mempool) ReceiveRequests(reqs ...iscp.Request) { for _, req := range reqs { - if req.IsOffLedger() { - m.mempoolMetrics.CountOffLedgerRequestIn() - } else { - m.mempoolMetrics.CountOnLedgerRequestIn() - } + m.countRequestInMetrics(req) m.addToInBuffer(req) } } -// ReceiveRequest used to receive off-ledger request -func (m *Mempool) ReceiveRequest(req iscp.Request) bool { - // could be worth it to check if the request was already processed in the blocklog. - // Not adding this check now to avoid overhead, but should be looked into in case re-gossiping happens a lot - if m.checkInBuffer(req) { - return false - } - m.mempoolMetrics.CountOffLedgerRequestIn() +// ReceiveRequest receives a single request and returns whether that request has been added to the in-buffer +func (m *mempool) ReceiveRequest(req iscp.Request) bool { + m.countRequestInMetrics(req) return m.addToInBuffer(req) } -func (m *Mempool) checkInBuffer(req iscp.Request) bool { - m.inMutex.RLock() - defer m.inMutex.RUnlock() - - _, exists := m.inBuffer[req.ID()] - return exists -} - // RemoveRequests removes requests from the pool -func (m *Mempool) RemoveRequests(reqs ...iscp.RequestID) { +func (m *mempool) RemoveRequests(reqs ...iscp.RequestID) { m.poolMutex.Lock() defer m.poolMutex.Unlock() @@ -194,6 +179,7 @@ func (m *Mempool) RemoveRequests(reqs ...iscp.RequestID) { } m.outPoolCounter++ m.mempoolMetrics.CountRequestOut() + m.mempoolMetrics.CountBlocksPerChain() elapsed := time.Since(m.pool[rid].whenReceived) m.mempoolMetrics.RecordRequestProcessingTime(rid, elapsed) delete(m.pool, rid) @@ -203,7 +189,7 @@ func (m *Mempool) RemoveRequests(reqs ...iscp.RequestID) { const traceInOut = false -func (m *Mempool) traceIn(req iscp.Request) { +func (m *mempool) traceIn(req iscp.Request) { rotateStr := "" if rotate.IsRotateStateControllerRequest(req) { rotateStr = "(rotate) " @@ -224,7 +210,7 @@ func (m *Mempool) traceIn(req iscp.Request) { } } -func (m *Mempool) traceOut(reqid iscp.RequestID) { +func (m *mempool) traceOut(reqid iscp.RequestID) { if traceInOut { m.log.Infof("OUT MEMPOOL %s (+%d / -%d)", reqid, m.inPoolCounter, m.outPoolCounter) } else { @@ -258,7 +244,7 @@ func isRequestReady(ref *requestRef, nowis time.Time) (isReady, shouldBeRemoved // Note that later status of request may change due to the time change and time constraints // If there's at least one committee rotation request in the mempool, the ReadyNow returns // batch with only one request, the oldest committee rotation request -func (m *Mempool) ReadyNow(now ...time.Time) []iscp.Request { +func (m *mempool) ReadyNow(now ...time.Time) []iscp.Request { m.poolMutex.RLock() nowis := time.Now() @@ -316,7 +302,7 @@ func (m *Mempool) ReadyNow(now ...time.Time) []iscp.Request { // - (a list of processable requests), true if the list can be deterministically calculated // Note that (a list of processable requests) can be empty if none satisfies nowis time constraint (timelock, fallback) // For requests which are known and solidified, the result is deterministic -func (m *Mempool) ReadyFromIDs(nowis time.Time, reqIDs ...iscp.RequestID) ([]iscp.Request, []int, bool) { +func (m *mempool) ReadyFromIDs(nowis time.Time, reqIDs ...iscp.RequestID) ([]iscp.Request, []int, bool) { requests := make([]iscp.Request, 0, len(reqIDs)) missingRequestIndexes := []int{} toRemove := []iscp.RequestID{} @@ -344,7 +330,7 @@ func (m *Mempool) ReadyFromIDs(nowis time.Time, reqIDs ...iscp.RequestID) ([]isc } // HasRequest checks if the request is in the pool -func (m *Mempool) HasRequest(id iscp.RequestID) bool { +func (m *mempool) HasRequest(id iscp.RequestID) bool { m.poolMutex.RLock() defer m.poolMutex.RUnlock() @@ -352,7 +338,7 @@ func (m *Mempool) HasRequest(id iscp.RequestID) bool { return ok } -func (m *Mempool) GetRequest(id iscp.RequestID) iscp.Request { +func (m *mempool) GetRequest(id iscp.RequestID) iscp.Request { m.poolMutex.RLock() defer m.poolMutex.RUnlock() @@ -365,7 +351,7 @@ func (m *Mempool) GetRequest(id iscp.RequestID) iscp.Request { const waitRequestInPoolTimeoutDefault = 2 * time.Second // WaitRequestInPool waits until the request appears in the pool but no longer than timeout -func (m *Mempool) WaitRequestInPool(reqid iscp.RequestID, timeout ...time.Duration) bool { +func (m *mempool) WaitRequestInPool(reqid iscp.RequestID, timeout ...time.Duration) bool { nowis := time.Now() deadline := nowis.Add(waitRequestInPoolTimeoutDefault) if len(timeout) > 0 { @@ -382,7 +368,7 @@ func (m *Mempool) WaitRequestInPool(reqid iscp.RequestID, timeout ...time.Durati } } -func (m *Mempool) inBufferLen() int { +func (m *mempool) inBufferLen() int { m.inMutex.RLock() defer m.inMutex.RUnlock() return len(m.inBuffer) @@ -392,7 +378,7 @@ const waitInBufferEmptyTimeoutDefault = 5 * time.Second // WaitAllRequestsIn waits until in buffer becomes empty. Used in synchronous situations when the caller // want to be sure all requests were fed into the pool. May create nondeterminism when used from goroutines -func (m *Mempool) WaitInBufferEmpty(timeout ...time.Duration) bool { +func (m *mempool) WaitInBufferEmpty(timeout ...time.Duration) bool { nowis := time.Now() deadline := nowis.Add(waitInBufferEmptyTimeoutDefault) if len(timeout) > 0 { @@ -410,7 +396,7 @@ func (m *Mempool) WaitInBufferEmpty(timeout ...time.Duration) bool { } // Stats collects mempool stats -func (m *Mempool) Info() chain.MempoolInfo { +func (m *mempool) Info() chain.MempoolInfo { m.poolMutex.RLock() defer m.poolMutex.RUnlock() @@ -431,12 +417,12 @@ func (m *Mempool) Info() chain.MempoolInfo { return ret } -func (m *Mempool) Close() { +func (m *mempool) Close() { close(m.chStop) } // the loop validates and moves request from inBuffer to the pool -func (m *Mempool) moveToPoolLoop() { +func (m *mempool) moveToPoolLoop() { buf := make([]iscp.Request, 0, 100) for { select { @@ -458,7 +444,7 @@ func (m *Mempool) moveToPoolLoop() { } // the loop solidifies requests -func (m *Mempool) solidificationLoop() { +func (m *mempool) solidificationLoop() { for { select { case <-m.chStop: @@ -469,7 +455,7 @@ func (m *Mempool) solidificationLoop() { } } -func (m *Mempool) doSolidifyRequests() { +func (m *mempool) doSolidifyRequests() { m.poolMutex.Lock() defer m.poolMutex.Unlock() diff --git a/packages/chain/mempool/mempool_test.go b/packages/chain/mempool/mempool_test.go index e1d5672dea..3f0ea77312 100644 --- a/packages/chain/mempool/mempool_test.go +++ b/packages/chain/mempool/mempool_test.go @@ -5,6 +5,7 @@ import ( "time" "github.com/iotaledger/wasp/packages/iscp/colored" + "go.uber.org/zap/zapcore" "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/goshimmer/packages/ledgerstate/utxodb" @@ -25,7 +26,6 @@ import ( "github.com/iotaledger/wasp/packages/vm/core/blocklog" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" ) func createStateReader(t *testing.T, glb coreutil.ChainStateSync) (state.OptimisticStateReader, state.VirtualStateAccess) { @@ -87,6 +87,8 @@ func (m *MockMempoolMetrics) CountRequestOut() { func (m *MockMempoolMetrics) RecordRequestProcessingTime(reqID iscp.RequestID, elapse time.Duration) { } +func (m *MockMempoolMetrics) CountBlocksPerChain() {} + // Test if mempool is created func TestMempool(t *testing.T) { log := testlogger.NewLogger(t) @@ -183,8 +185,7 @@ func TestAddRequestTwice(t *testing.T) { require.EqualValues(t, 1, stats.ReadyCounter) } -// Test if adding off ledger requests works as expected: correctly signed ones -// are added, others are ignored +// Test if adding off ledger requests works as expected func TestAddOffLedgerRequest(t *testing.T) { log := testlogger.NewLogger(t) testlogger.WithLevel(log, zapcore.InfoLevel, false) @@ -196,32 +197,21 @@ func TestAddOffLedgerRequest(t *testing.T) { onLedgerRequests, keyPair := getRequestsOnLedger(t, 2) offFromOnLedgerFun := func(onLedger *request.OnLedger) *request.OffLedger { - contract, emptyPoint := onLedger.Target() - return request.NewOffLedger(contract, emptyPoint, onLedger.GetMetadata().Args()) + target := onLedger.Target() + return request.NewOffLedger(iscp.RandomChainID(), target.Contract, target.EntryPoint, onLedger.GetMetadata().Args()) } - offLedgerRequestUnsigned := offFromOnLedgerFun(onLedgerRequests[0]) offLedgerRequestSigned := offFromOnLedgerFun(onLedgerRequests[1]) offLedgerRequestSigned.Sign(keyPair) - require.NotEqual(t, offLedgerRequestUnsigned.ID(), offLedgerRequestSigned.ID()) require.EqualValues(t, 0, mempoolMetrics.offLedgerRequestCounter) - pool.ReceiveRequests(offLedgerRequestUnsigned) - require.False(t, pool.WaitRequestInPool(offLedgerRequestUnsigned.ID(), 200*time.Millisecond)) - stats := pool.Info() - require.EqualValues(t, 0, stats.InPoolCounter) - require.EqualValues(t, 0, stats.OutPoolCounter) - require.EqualValues(t, 0, stats.TotalPool) - require.EqualValues(t, 0, stats.ReadyCounter) - require.EqualValues(t, 1, mempoolMetrics.offLedgerRequestCounter) - pool.ReceiveRequests(offLedgerRequestSigned) require.True(t, pool.WaitRequestInPool(offLedgerRequestSigned.ID(), 200*time.Millisecond)) - stats = pool.Info() + stats := pool.Info() require.EqualValues(t, 1, stats.InPoolCounter) require.EqualValues(t, 0, stats.OutPoolCounter) require.EqualValues(t, 1, stats.TotalPool) require.EqualValues(t, 1, stats.ReadyCounter) - require.EqualValues(t, 2, mempoolMetrics.offLedgerRequestCounter) + require.EqualValues(t, 1, mempoolMetrics.offLedgerRequestCounter) } // Test if processed request cannot be added to mempool @@ -458,7 +448,7 @@ func TestFallbackOptions(t *testing.T) { // request with the invalid deadline should have been removed from the mempool time.Sleep(500 * time.Millisecond) // just to let the `RemoveRequests` go routine get the pool mutex before we look into it require.Nil(t, pool.GetRequest(requests[2].ID())) - require.Len(t, pool.pool, 2) + require.Len(t, pool.(*mempool).pool, 2) } // Test if ReadyFromIDs function correctly handle non-existing or removed IDs @@ -623,10 +613,10 @@ func TestRotateRequest(t *testing.T) { require.True(t, len(ready) == 5) kp, addr := testkey.GenKeyAddr() - rotateReq := rotate.NewRotateRequestOffLedger(addr, kp) + rotateReq := rotate.NewRotateRequestOffLedger(iscp.RandomChainID(), addr, kp) require.True(t, rotate.IsRotateStateControllerRequest(rotateReq)) - pool.ReceiveRequests(rotateReq) + pool.ReceiveRequest(rotateReq) require.True(t, pool.WaitRequestInPool(rotateReq.ID())) require.True(t, pool.HasRequest(rotateReq.ID())) diff --git a/packages/chain/messages/missing_req_msg.go b/packages/chain/messages/missing_req_msg.go deleted file mode 100644 index 1cc3285c05..0000000000 --- a/packages/chain/messages/missing_req_msg.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package messages - -import ( - "github.com/iotaledger/hive.go/marshalutil" - "github.com/iotaledger/wasp/packages/iscp" - "github.com/iotaledger/wasp/packages/iscp/request" -) - -// region MissingRequestIDsMsg /////////////////////////////////////////////////// - -type MissingRequestIDsMsg struct { - IDs []iscp.RequestID -} - -func NewMissingRequestIDsMsg(missingIDs []iscp.RequestID) *MissingRequestIDsMsg { - return &MissingRequestIDsMsg{ - IDs: missingIDs, - } -} - -func (msg *MissingRequestIDsMsg) Bytes() []byte { - mu := marshalutil.New() - mu.WriteUint16(uint16(len(msg.IDs))) - for i := range msg.IDs { - mu.WriteBytes(msg.IDs[i].Bytes()) - } - return mu.Bytes() -} - -func MissingRequestIDsMsgFromBytes(data []byte) (*MissingRequestIDsMsg, error) { - mu := marshalutil.New(data) - num, err := mu.ReadUint16() - if err != nil { - return nil, err - } - ret := &MissingRequestIDsMsg{ - IDs: make([]iscp.RequestID, num), - } - for i := range ret.IDs { - if ret.IDs[i], err = iscp.RequestIDFromMarshalUtil(mu); err != nil { - return nil, err - } - } - return ret, nil -} - -// endregion /////////////////////////////////////////////////////////////////// - -// region MissingRequestMsg /////////////////////////////////////////////////// - -type MissingRequestMsg struct { - Request iscp.Request -} - -func NewMissingRequestMsg(req iscp.Request) *MissingRequestMsg { - return &MissingRequestMsg{ - Request: req, - } -} - -func (msg *MissingRequestMsg) Bytes() []byte { - return msg.Request.Bytes() -} - -func MissingRequestMsgFromBytes(data []byte) (*MissingRequestMsg, error) { - msg := &MissingRequestMsg{} - var err error - msg.Request, err = request.FromMarshalUtil(marshalutil.New(data)) - if err != nil { - return nil, err - } - return msg, nil -} - -// endregion /////////////////////////////////////////////////////////////////// diff --git a/packages/chain/messages/peer_block_msg.go b/packages/chain/messages/peer_block_msg.go new file mode 100644 index 0000000000..452b0bdc34 --- /dev/null +++ b/packages/chain/messages/peer_block_msg.go @@ -0,0 +1,36 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package messages + +import ( + "bytes" + "io" + + "github.com/iotaledger/wasp/packages/util" +) + +// BlockMsg StateManager in response to GetBlockMsg sends block data to the querying node's StateManager +// StateManager -> StateManager +type BlockMsg struct { + BlockBytes []byte +} + +type BlockMsgIn struct { + BlockMsg + SenderNetID string +} + +func NewBlockMsg(data []byte) (*BlockMsg, error) { + msg := &BlockMsg{} + r := bytes.NewReader(data) + var err error + if msg.BlockBytes, err = util.ReadBytes32(r); err != nil { + return nil, err + } + return msg, nil +} + +func (msg *BlockMsg) Write(w io.Writer) error { + return util.WriteBytes32(w, msg.BlockBytes) +} diff --git a/packages/chain/messages/peer_get_block_msg.go b/packages/chain/messages/peer_get_block_msg.go new file mode 100644 index 0000000000..48d4a500c6 --- /dev/null +++ b/packages/chain/messages/peer_get_block_msg.go @@ -0,0 +1,35 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package messages + +import ( + "bytes" + "io" + + "github.com/iotaledger/wasp/packages/util" +) + +// GetBlockMsg StateManager queries specific block data from another peer (access node) +// StateManager -> StateManager +type GetBlockMsg struct { + BlockIndex uint32 +} + +type GetBlockMsgIn struct { + GetBlockMsg + SenderNetID string +} + +func NewGetBlockMsg(data []byte) (*GetBlockMsg, error) { + msg := &GetBlockMsg{} + r := bytes.NewReader(data) + if err := util.ReadUint32(r, &msg.BlockIndex); err != nil { + return nil, err + } + return msg, nil +} + +func (msg *GetBlockMsg) Write(w io.Writer) error { + return util.WriteUint32(w, msg.BlockIndex) +} diff --git a/packages/chain/messages/peer_missing_request_ids_msg.go b/packages/chain/messages/peer_missing_request_ids_msg.go new file mode 100644 index 0000000000..ed32285b4e --- /dev/null +++ b/packages/chain/messages/peer_missing_request_ids_msg.go @@ -0,0 +1,44 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package messages + +import ( + "github.com/iotaledger/hive.go/marshalutil" + "github.com/iotaledger/wasp/packages/iscp" +) + +type MissingRequestIDsMsg struct { + IDs []iscp.RequestID +} + +type MissingRequestIDsMsgIn struct { + MissingRequestIDsMsg + SenderNetID string +} + +func (msg *MissingRequestIDsMsg) Bytes() []byte { + mu := marshalutil.New() + mu.WriteUint16(uint16(len(msg.IDs))) + for i := range msg.IDs { + mu.WriteBytes(msg.IDs[i].Bytes()) + } + return mu.Bytes() +} + +func NewMissingRequestIDsMsg(data []byte) (*MissingRequestIDsMsg, error) { + mu := marshalutil.New(data) + num, err := mu.ReadUint16() + if err != nil { + return nil, err + } + ret := &MissingRequestIDsMsg{ + IDs: make([]iscp.RequestID, num), + } + for i := range ret.IDs { + if ret.IDs[i], err = iscp.RequestIDFromMarshalUtil(mu); err != nil { + return nil, err + } + } + return ret, nil +} diff --git a/packages/chain/messages/peer_missing_request_msg.go b/packages/chain/messages/peer_missing_request_msg.go new file mode 100644 index 0000000000..8bdf1fdbb2 --- /dev/null +++ b/packages/chain/messages/peer_missing_request_msg.go @@ -0,0 +1,28 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package messages + +import ( + "github.com/iotaledger/hive.go/marshalutil" + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/iscp/request" +) + +type MissingRequestMsg struct { + Request iscp.Request +} + +func (msg *MissingRequestMsg) Bytes() []byte { + return msg.Request.Bytes() +} + +func NewMissingRequestMsg(data []byte) (*MissingRequestMsg, error) { + msg := &MissingRequestMsg{} + var err error + msg.Request, err = request.FromMarshalUtil(marshalutil.New(data)) + if err != nil { + return nil, err + } + return msg, nil +} diff --git a/packages/chain/messages/offledger_req_msg.go b/packages/chain/messages/peer_offledger_request_msg.go similarity index 78% rename from packages/chain/messages/offledger_req_msg.go rename to packages/chain/messages/peer_offledger_request_msg.go index 95fac6208a..672a7e3414 100644 --- a/packages/chain/messages/offledger_req_msg.go +++ b/packages/chain/messages/peer_offledger_request_msg.go @@ -15,21 +15,12 @@ type OffLedgerRequestMsg struct { Req *request.OffLedger } -func NewOffLedgerRequestMsg(chainID *iscp.ChainID, req *request.OffLedger) *OffLedgerRequestMsg { - return &OffLedgerRequestMsg{ - ChainID: chainID, - Req: req, - } +type OffLedgerRequestMsgIn struct { + OffLedgerRequestMsg + SenderNetID string } -func (msg *OffLedgerRequestMsg) Bytes() []byte { - return marshalutil.New(). - Write(msg.ChainID). - Write(msg.Req). - Bytes() -} - -func OffLedgerRequestMsgFromBytes(data []byte) (*OffLedgerRequestMsg, error) { +func NewOffLedgerRequestMsg(data []byte) (*OffLedgerRequestMsg, error) { mu := marshalutil.New(data) chainID, err := iscp.ChainIDFromMarshalUtil(mu) if err != nil { @@ -48,3 +39,10 @@ func OffLedgerRequestMsgFromBytes(data []byte) (*OffLedgerRequestMsg, error) { Req: reqCasted, }, nil } + +func (msg *OffLedgerRequestMsg) Bytes() []byte { + return marshalutil.New(). + Write(msg.ChainID). + Write(msg.Req). + Bytes() +} diff --git a/packages/chain/messages/offledger_req_msg_test.go b/packages/chain/messages/peer_offledger_request_msg_test.go similarity index 81% rename from packages/chain/messages/offledger_req_msg_test.go rename to packages/chain/messages/peer_offledger_request_msg_test.go index 03dd3e4c87..85954f3671 100644 --- a/packages/chain/messages/offledger_req_msg_test.go +++ b/packages/chain/messages/peer_offledger_request_msg_test.go @@ -24,16 +24,16 @@ func TestMarshalling(t *testing.T) { dict.Dict{foo: []byte("bar")}, ) - msg := NewOffLedgerRequestMsg( - iscp.RandomChainID(), - request.NewOffLedger(contract, entrypoint, args), - ) + msg := &OffLedgerRequestMsg{ + ChainID: iscp.RandomChainID(), + Req: request.NewOffLedger(iscp.RandomChainID(), contract, entrypoint, args), + } // marshall the msg msgBytes := msg.Bytes() // unmashal the message from bytes and ensure everything checks out - unmarshalledMsg, err := OffLedgerRequestMsgFromBytes(msgBytes) + unmarshalledMsg, err := NewOffLedgerRequestMsg(msgBytes) require.NoError(t, err) require.True(t, unmarshalledMsg.ChainID.AliasAddress.Equals(msg.ChainID.AliasAddress)) diff --git a/packages/chain/messages/req_ack_msg.go b/packages/chain/messages/peer_request_ack_msg.go similarity index 66% rename from packages/chain/messages/req_ack_msg.go rename to packages/chain/messages/peer_request_ack_msg.go index 59b5054c56..35bbbba2a2 100644 --- a/packages/chain/messages/req_ack_msg.go +++ b/packages/chain/messages/peer_request_ack_msg.go @@ -11,30 +11,36 @@ import ( "golang.org/x/xerrors" ) -type RequestAcKMsg struct { +type RequestAckMsg struct { ReqID *iscp.RequestID } -func NewRequestAckMsg(reqID iscp.RequestID) *RequestAcKMsg { - return &RequestAcKMsg{ - ReqID: &reqID, - } +type RequestAckMsgIn struct { + RequestAckMsg + SenderNetID string +} + +func NewRequestAckMsg(buf []byte) (*RequestAckMsg, error) { + r := bytes.NewReader(buf) + msg := &RequestAckMsg{} + err := msg.read(r) + return msg, err } -func (msg *RequestAcKMsg) write(w io.Writer) error { +func (msg *RequestAckMsg) write(w io.Writer) error { if _, err := w.Write(msg.ReqID.Bytes()); err != nil { return xerrors.Errorf("failed to write requestIDs: %w", err) } return nil } -func (msg *RequestAcKMsg) Bytes() []byte { +func (msg *RequestAckMsg) Bytes() []byte { var buf bytes.Buffer _ = msg.write(&buf) return buf.Bytes() } -func (msg *RequestAcKMsg) read(r io.Reader) error { +func (msg *RequestAckMsg) read(r io.Reader) error { b, err := io.ReadAll(r) if err != nil { return xerrors.Errorf("failed to read requestIDs: %w", err) @@ -46,10 +52,3 @@ func (msg *RequestAcKMsg) read(r io.Reader) error { msg.ReqID = &reqID return nil } - -func RequestAckMsgFromBytes(buf []byte) (RequestAcKMsg, error) { - r := bytes.NewReader(buf) - msg := RequestAcKMsg{} - err := msg.read(r) - return msg, err -} diff --git a/packages/chain/messages/peer_signed_result_msg.go b/packages/chain/messages/peer_signed_result_msg.go new file mode 100644 index 0000000000..ed06e74498 --- /dev/null +++ b/packages/chain/messages/peer_signed_result_msg.go @@ -0,0 +1,55 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package messages + +import ( + "bytes" + "io" + + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/wasp/packages/hashing" + "github.com/iotaledger/wasp/packages/util" + "go.dedis.ch/kyber/v3/sign/tbls" +) + +// Consensus -> Consensus +type SignedResultMsg struct { + ChainInputID ledgerstate.OutputID + EssenceHash hashing.HashValue + SigShare tbls.SigShare +} + +type SignedResultMsgIn struct { + SignedResultMsg + SenderIndex uint16 +} + +func NewSignedResultMsg(data []byte) (*SignedResultMsg, error) { + msg := &SignedResultMsg{} + r := bytes.NewReader(data) + var err error + if err = util.ReadHashValue(r, &msg.EssenceHash); err != nil { // nolint:gocritic // - ignore sloppyReassign + return nil, err + } + if msg.SigShare, err = util.ReadBytes16(r); err != nil { + return nil, err + } + if err = util.ReadOutputID(r, &msg.ChainInputID); err != nil { // nolint:gocritic // - ignore sloppyReassign + return nil, err + } + return msg, nil +} + +func (msg *SignedResultMsg) Write(w io.Writer) error { + if _, err := w.Write(msg.EssenceHash[:]); err != nil { + return err + } + if err := util.WriteBytes16(w, msg.SigShare); err != nil { + return err + } + if _, err := w.Write(msg.ChainInputID[:]); err != nil { + return err + } + return nil +} diff --git a/packages/chain/messages/peer_signed_result_msg_ack.go b/packages/chain/messages/peer_signed_result_msg_ack.go new file mode 100644 index 0000000000..f069d410f5 --- /dev/null +++ b/packages/chain/messages/peer_signed_result_msg_ack.go @@ -0,0 +1,47 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package messages + +import ( + "bytes" + "io" + + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/wasp/packages/hashing" + "github.com/iotaledger/wasp/packages/util" +) + +// Consensus -> Consensus +type SignedResultAckMsg struct { + ChainInputID ledgerstate.OutputID + EssenceHash hashing.HashValue +} + +type SignedResultAckMsgIn struct { + SignedResultAckMsg + SenderIndex uint16 +} + +func NewSignedResultAckMsg(data []byte) (*SignedResultAckMsg, error) { + msg := &SignedResultAckMsg{} + r := bytes.NewReader(data) + var err error + if err = util.ReadHashValue(r, &msg.EssenceHash); err != nil { // nolint:gocritic // - ignore sloppyReassign + return nil, err + } + if err = util.ReadOutputID(r, &msg.ChainInputID); err != nil { // nolint:gocritic // - ignore sloppyReassign + return nil, err + } + return msg, nil +} + +func (msg *SignedResultAckMsg) Write(w io.Writer) error { + if _, err := w.Write(msg.EssenceHash[:]); err != nil { + return err + } + if _, err := w.Write(msg.ChainInputID[:]); err != nil { + return err + } + return nil +} diff --git a/packages/chain/messages/peermsg.go b/packages/chain/messages/peermsg.go index fcf816517d..118a3709c2 100644 --- a/packages/chain/messages/peermsg.go +++ b/packages/chain/messages/peermsg.go @@ -4,16 +4,12 @@ package messages import ( - "io" "time" "github.com/iotaledger/goshimmer/packages/ledgerstate" - "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/state" - "github.com/iotaledger/wasp/packages/util" "github.com/iotaledger/wasp/packages/vm" - "go.dedis.ch/kyber/v3/sign/tbls" ) // Message types for the committee communications. @@ -30,36 +26,6 @@ const ( type TimerTick int -type SignedResultMsg struct { - SenderIndex uint16 - ChainInputID ledgerstate.OutputID - EssenceHash hashing.HashValue - SigShare tbls.SigShare -} - -type SignedResultAckMsg struct { - SenderIndex uint16 - ChainInputID ledgerstate.OutputID - EssenceHash hashing.HashValue -} - -// GetBlockMsg StateManager queries specific block data from another peer (access node) -type GetBlockMsg struct { - SenderNetID string - BlockIndex uint32 -} - -// BlockMsg StateManager in response to GetBlockMsg sends block data to the querying node's StateManager -type BlockMsg struct { - SenderNetID string - BlockBytes []byte -} - -// DismissChainMsg sent by component to the chain core in case of major setback -type DismissChainMsg struct { - Reason string -} - // StateTransitionMsg Notifies chain about changed state type StateTransitionMsg struct { // new variable state @@ -98,67 +64,3 @@ type StateMsg struct { ChainOutput *ledgerstate.AliasOutput Timestamp time.Time } - -func (msg *GetBlockMsg) Write(w io.Writer) error { - return util.WriteUint32(w, msg.BlockIndex) -} - -func (msg *GetBlockMsg) Read(r io.Reader) error { - return util.ReadUint32(r, &msg.BlockIndex) -} - -func (msg *BlockMsg) Write(w io.Writer) error { - return util.WriteBytes32(w, msg.BlockBytes) -} - -func (msg *BlockMsg) Read(r io.Reader) error { - var err error - if msg.BlockBytes, err = util.ReadBytes32(r); err != nil { - return err - } - return nil -} - -func (msg *SignedResultMsg) Write(w io.Writer) error { - if _, err := w.Write(msg.EssenceHash[:]); err != nil { - return err - } - if err := util.WriteBytes16(w, msg.SigShare); err != nil { - return err - } - if _, err := w.Write(msg.ChainInputID[:]); err != nil { - return err - } - return nil -} - -func (msg *SignedResultMsg) Read(r io.Reader) error { - if err := util.ReadHashValue(r, &msg.EssenceHash); err != nil { - return err - } - var err error - if msg.SigShare, err = util.ReadBytes16(r); err != nil { - return err - } - if err := util.ReadOutputID(r, &msg.ChainInputID); /* nolint:revive */ err != nil { - return err - } - return nil -} - -func (msg *SignedResultAckMsg) Write(w io.Writer) error { - if _, err := w.Write(msg.EssenceHash[:]); err != nil { - return err - } - if _, err := w.Write(msg.ChainInputID[:]); err != nil { - return err - } - return nil -} - -func (msg *SignedResultAckMsg) Read(r io.Reader) error { - if err := util.ReadHashValue(r, &msg.EssenceHash); err != nil { - return err - } - return util.ReadOutputID(r, &msg.ChainInputID) -} diff --git a/packages/chain/nodeconnimpl/nodeconnimpl.go b/packages/chain/nodeconnimpl/nodeconnimpl.go index a919268528..cd8c471401 100644 --- a/packages/chain/nodeconnimpl/nodeconnimpl.go +++ b/packages/chain/nodeconnimpl/nodeconnimpl.go @@ -1,56 +1,239 @@ package nodeconnimpl import ( - "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/goshimmer/packages/ledgerstate" - txstream "github.com/iotaledger/goshimmer/packages/txstream/client" + "github.com/iotaledger/goshimmer/packages/txstream" + txstream_client "github.com/iotaledger/goshimmer/packages/txstream/client" + "github.com/iotaledger/hive.go/events" + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/wasp/packages/chain" + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" ) -type NodeConnImplementation struct { - client *txstream.Client - log *logger.Logger +type nodeConnImplementation struct { + client *txstream_client.Client + transactionHandlers map[ledgerstate.AliasAddress]chain.NodeConnectionHandleTransactionFun + iStateHandlers map[ledgerstate.AliasAddress]chain.NodeConnectionHandleInclusionStateFun + outputHandlers map[ledgerstate.AliasAddress]chain.NodeConnectionHandleOutputFun + unspentAOutputHandlers map[ledgerstate.AliasAddress]chain.NodeConnectionHandleUnspentAliasOutputFun + transactionClosure *events.Closure + iStateClosure *events.Closure + outputClosure *events.Closure + unspentAOutputClosure *events.Closure + metrics nodeconnmetrics.NodeConnectionMetrics + log *logger.Logger // general chains logger } -func New(nodeConnClient *txstream.Client, log *logger.Logger) *NodeConnImplementation { - return &NodeConnImplementation{ - client: nodeConnClient, - log: log, +var _ chain.NodeConnection = &nodeConnImplementation{} + +func NewNodeConnection(nodeConnClient *txstream_client.Client, metrics nodeconnmetrics.NodeConnectionMetrics, log *logger.Logger) chain.NodeConnection { + ret := &nodeConnImplementation{ + client: nodeConnClient, + transactionHandlers: make(map[ledgerstate.AliasAddress]chain.NodeConnectionHandleTransactionFun), + iStateHandlers: make(map[ledgerstate.AliasAddress]chain.NodeConnectionHandleInclusionStateFun), + outputHandlers: make(map[ledgerstate.AliasAddress]chain.NodeConnectionHandleOutputFun), + unspentAOutputHandlers: make(map[ledgerstate.AliasAddress]chain.NodeConnectionHandleUnspentAliasOutputFun), + metrics: metrics, + log: log, } + + ret.transactionClosure = events.NewClosure(ret.handleTransactionReceived) + ret.client.Events.TransactionReceived.Attach(ret.transactionClosure) + + ret.iStateClosure = events.NewClosure(ret.handleInclusionStateReceived) + ret.client.Events.InclusionStateReceived.Attach(ret.iStateClosure) + + ret.outputClosure = events.NewClosure(ret.handleOutputReceived) + ret.client.Events.OutputReceived.Attach(ret.outputClosure) + + ret.unspentAOutputClosure = events.NewClosure(ret.handleUnspentAliasOutputReceived) + ret.client.Events.UnspentAliasOutputReceived.Attach(ret.unspentAOutputClosure) + + return ret } -func (n *NodeConnImplementation) PullBacklog(addr *ledgerstate.AliasAddress) { - n.log.Debugf("NodeConnImplementation::PullBacklog(addr=%s)...", addr.Base58()) - n.client.RequestBacklog(addr) - n.log.Debugf("NodeConnImplementation::PullBacklog(addr=%s)... Done", addr.Base58()) +func (n *nodeConnImplementation) handleTransactionReceived(msg *txstream.MsgTransaction) { + n.log.Debugf("NodeConnnection::TransactionReceived...") + defer n.log.Debugf("NodeConnnection::TransactionReceived... Done") + n.metrics.GetInTransaction().CountLastMessage(msg) + aliasAddr, ok := msg.Address.(*ledgerstate.AliasAddress) + if !ok { + n.log.Warnf("NodeConnnection::TransactionReceived: cannot dispatch transaction message to non-alias address %v", msg.Address.String()) + return + } + handler, ok := n.transactionHandlers[*aliasAddr] + if !ok { + n.log.Warnf("NodeConnnection::TransactionReceived: no handler for address %v", aliasAddr.String()) + return + } + handler(msg.Tx) } -func (n *NodeConnImplementation) PullState(addr *ledgerstate.AliasAddress) { - n.log.Debugf("NodeConnImplementation::PullState(addr=%s)...", addr.Base58()) - n.client.RequestUnspentAliasOutput(addr) - n.log.Debugf("NodeConnImplementation::PullState(addr=%s)... Done", addr.Base58()) +func (n *nodeConnImplementation) handleInclusionStateReceived(msg *txstream.MsgTxInclusionState) { + n.log.Debugf("NodeConnnection::InclusionStateReceived...") + defer n.log.Debugf("NodeConnnection::InclusionStateReceived... Done") + n.metrics.GetInInclusionState().CountLastMessage(msg) + aliasAddr, ok := msg.Address.(*ledgerstate.AliasAddress) + if !ok { + n.log.Warnf("NodeConnnection::InclusionStateReceived: cannot dispatch transaction message to non-alias address %v", msg.Address.String()) + return + } + handler, ok := n.iStateHandlers[*aliasAddr] + if !ok { + n.log.Warnf("NodeConnnection::InclusionStateReceived: no handler for address %v", aliasAddr.String()) + return + } + handler(msg.TxID, msg.State) } -func (n *NodeConnImplementation) PullConfirmedTransaction(addr ledgerstate.Address, txid ledgerstate.TransactionID) { - n.log.Debugf("NodeConnImplementation::PullConfirmedTransaction(addr=%s)...", addr.Base58()) - n.client.RequestConfirmedTransaction(addr, txid) - n.log.Debugf("NodeConnImplementation::PullConfirmedTransaction(addr=%s)... Done", addr.Base58()) +func (n *nodeConnImplementation) handleOutputReceived(msg *txstream.MsgOutput) { + n.log.Debugf("NodeConnnection::OutputReceived...") + defer n.log.Debugf("NodeConnnection::OutputReceived... Done") + n.metrics.GetInOutput().CountLastMessage(msg) + aliasAddr, ok := msg.Address.(*ledgerstate.AliasAddress) + if !ok { + n.log.Warnf("NodeConnnection::OutputReceived: cannot dispatch transaction message to non-alias address %v", msg.Address.String()) + return + } + handler, ok := n.outputHandlers[*aliasAddr] + if !ok { + n.log.Warnf("NodeConnnection::OutputReceived: no handler for address %v", aliasAddr.String()) + return + } + handler(msg.Output) } -func (n *NodeConnImplementation) PullTransactionInclusionState(addr ledgerstate.Address, txid ledgerstate.TransactionID) { - n.log.Debugf("NodeConnImplementation::PullTransactionInclusionState(addr=%s)...", addr.Base58()) +func (n *nodeConnImplementation) handleUnspentAliasOutputReceived(msg *txstream.MsgUnspentAliasOutput) { + n.log.Debugf("NodeConnnection::UnspentAliasOutputReceived...") + defer n.log.Debugf("NodeConnnection::UnspentAliasOutputReceived... Done") + n.metrics.GetInUnspentAliasOutput().CountLastMessage(msg) + handler, ok := n.unspentAOutputHandlers[*msg.AliasAddress] + if !ok { + n.log.Warnf("NodeConnnection::UnspentAliasOutputReceived: no handler for address %v", msg.AliasAddress.String()) + return + } + handler(msg.AliasOutput, msg.Timestamp) +} + +// NOTE: request to client methods are logged through each chain logger in chainNodeConnImplementation + +func (n *nodeConnImplementation) PullState(addr *ledgerstate.AliasAddress) { + n.metrics.GetOutPullState().CountLastMessage(addr) + n.client.RequestUnspentAliasOutput(addr) +} + +func (n *nodeConnImplementation) PullTransactionInclusionState(addr ledgerstate.Address, txid ledgerstate.TransactionID) { + n.metrics.GetOutPullTransactionInclusionState().CountLastMessage(struct { + Address ledgerstate.Address + TransactionID ledgerstate.TransactionID + }{ + Address: addr, + TransactionID: txid, + }) n.client.RequestTxInclusionState(addr, txid) - n.log.Debugf("NodeConnImplementation::PullTransactionInclusionState(addr=%s)... Done", addr.Base58()) } -func (n *NodeConnImplementation) PullConfirmedOutput(addr ledgerstate.Address, outputID ledgerstate.OutputID) { - n.log.Debugf("NodeConnImplementation::PullConfirmedOutput(addr=%s)...", addr.Base58()) +func (n *nodeConnImplementation) PullConfirmedOutput(addr ledgerstate.Address, outputID ledgerstate.OutputID) { + n.metrics.GetOutPullConfirmedOutput().CountLastMessage(struct { + Address ledgerstate.Address + OutputID ledgerstate.OutputID + }{ + Address: addr, + OutputID: outputID, + }) n.client.RequestConfirmedOutput(addr, outputID) - n.log.Debugf("NodeConnImplementation::PullConfirmedOutput(addr=%s)... Done", addr.Base58()) } -func (n *NodeConnImplementation) PostTransaction(tx *ledgerstate.Transaction) { - n.log.Debugf("NodeConnImplementation::PostTransaction(tx, id=%s)...", tx.ID()) +func (n *nodeConnImplementation) PostTransaction(tx *ledgerstate.Transaction) { + n.metrics.GetOutPostTransaction().CountLastMessage(tx) n.client.PostTransaction(tx) - n.log.Debugf("NodeConnImplementation::PostTransaction(tx, id=%s)... Done", tx.ID()) +} + +func (n *nodeConnImplementation) AttachToTransactionReceived(addr *ledgerstate.AliasAddress, handler chain.NodeConnectionHandleTransactionFun) { + n.log.Debugf("NodeConnnection::AttachToTransactionReceived to %v", addr.String()) + _, ok := n.transactionHandlers[*addr] + if ok { + n.log.Panicf("NodeConnnection::AttachToTransactionReceived to %v failed: handler already registered") + } + n.transactionHandlers[*addr] = handler +} + +func (n *nodeConnImplementation) AttachToInclusionStateReceived(addr *ledgerstate.AliasAddress, handler chain.NodeConnectionHandleInclusionStateFun) { + n.log.Debugf("NodeConnnection::AttachToInclusionStateReceived to %v", addr.String()) + _, ok := n.iStateHandlers[*addr] + if ok { + n.log.Panicf("NodeConnnection::AttachToInclusionStateReceived to %v failed: handler already registered") + } + n.iStateHandlers[*addr] = handler +} + +func (n *nodeConnImplementation) AttachToOutputReceived(addr *ledgerstate.AliasAddress, handler chain.NodeConnectionHandleOutputFun) { + n.log.Debugf("NodeConnnection::AttachToOutputReceived to %v", addr.String()) + _, ok := n.outputHandlers[*addr] + if ok { + n.log.Panicf("NodeConnnection::AttachToOutputReceived to %v failed: handler already registered") + } + n.outputHandlers[*addr] = handler +} + +func (n *nodeConnImplementation) AttachToUnspentAliasOutputReceived(addr *ledgerstate.AliasAddress, handler chain.NodeConnectionHandleUnspentAliasOutputFun) { + n.log.Debugf("NodeConnnection::AttachToUnspentAliasOutputReceived to %v", addr.String()) + _, ok := n.unspentAOutputHandlers[*addr] + if ok { + n.log.Panicf("NodeConnnection::AttachToUnspentAliasOutputReceived to %v failed: handler already registered") + } + n.unspentAOutputHandlers[*addr] = handler +} + +func (n *nodeConnImplementation) DetachFromTransactionReceived(addr *ledgerstate.AliasAddress) { + n.log.Debugf("NodeConnnection::DetachFromTransactionReceived to %v", addr.String()) + delete(n.transactionHandlers, *addr) +} + +func (n *nodeConnImplementation) DetachFromInclusionStateReceived(addr *ledgerstate.AliasAddress) { + n.log.Debugf("NodeConnnection::DetachFromInclusionStateReceived to %v", addr.String()) + delete(n.iStateHandlers, *addr) +} + +func (n *nodeConnImplementation) DetachFromOutputReceived(addr *ledgerstate.AliasAddress) { + n.log.Debugf("NodeConnnection::DetachFromOutputReceived to %v", addr.String()) + delete(n.outputHandlers, *addr) +} + +func (n *nodeConnImplementation) DetachFromUnspentAliasOutputReceived(addr *ledgerstate.AliasAddress) { + n.log.Debugf("NodeConnnection::DetachFromUnspentAliasOutputReceived to %v", addr.String()) + delete(n.unspentAOutputHandlers, *addr) +} + +func (n *nodeConnImplementation) Subscribe(addr ledgerstate.Address) { + n.log.Debugf("NodeConnnection::Subscribing to %v...", addr.String()) + defer n.log.Debugf("NodeConnnection::Subscribing done") + n.client.Subscribe(addr) + n.metrics.SetSubscribed(addr) +} + +func (n *nodeConnImplementation) Unsubscribe(addr ledgerstate.Address) { + n.log.Debugf("NodeConnnection::Unsubscribing from %v...", addr.String()) + defer n.log.Debugf("NodeConnnection::Unsubscribing done") + n.metrics.SetUnsubscribed(addr) + n.client.Unsubscribe(addr) +} + +func (n *nodeConnImplementation) GetMetrics() nodeconnmetrics.NodeConnectionMetrics { + return n.metrics +} + +func (n *nodeConnImplementation) Close() { + n.log.Debugf("NodeConnnection::Close") + n.client.Events.TransactionReceived.Detach(n.transactionClosure) + n.transactionHandlers = make(map[ledgerstate.AliasAddress]chain.NodeConnectionHandleTransactionFun) + + n.client.Events.InclusionStateReceived.Detach(n.iStateClosure) + n.iStateHandlers = make(map[ledgerstate.AliasAddress]chain.NodeConnectionHandleInclusionStateFun) + + n.client.Events.OutputReceived.Detach(n.outputClosure) + n.outputHandlers = make(map[ledgerstate.AliasAddress]chain.NodeConnectionHandleOutputFun) + + n.client.Events.UnspentAliasOutputReceived.Detach(n.unspentAOutputClosure) + n.unspentAOutputHandlers = make(map[ledgerstate.AliasAddress]chain.NodeConnectionHandleUnspentAliasOutputFun) } diff --git a/packages/chain/nodeconnimpl/nodeconnimpl_chain.go b/packages/chain/nodeconnimpl/nodeconnimpl_chain.go new file mode 100644 index 0000000000..365a7e7a67 --- /dev/null +++ b/packages/chain/nodeconnimpl/nodeconnimpl_chain.go @@ -0,0 +1,137 @@ +// Provides implementations for chain.ChainNodeConnection methods +package nodeconnimpl + +import ( + "time" + + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/wasp/packages/chain" + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" +) + +type chainNodeConnImplementation struct { + chainID *iscp.ChainID + nodeConn chain.NodeConnection + metrics nodeconnmetrics.NodeConnectionMessagesMetrics + log *logger.Logger // logger for one chain +} + +var _ chain.ChainNodeConnection = &chainNodeConnImplementation{} + +func NewChainNodeConnection(chainID *iscp.ChainID, nodeConn chain.NodeConnection, log *logger.Logger) chain.ChainNodeConnection { + return &chainNodeConnImplementation{ + chainID: chainID, + nodeConn: nodeConn, + metrics: nodeConn.GetMetrics().NewMessagesMetrics(chainID), + log: log, + } +} + +func (c *chainNodeConnImplementation) AttachToTransactionReceived(fun chain.NodeConnectionHandleTransactionFun) { + c.log.Debugf("ChainNodeConnImplementation::AttachToTransactionReceived") + c.nodeConn.AttachToTransactionReceived(c.chainID.AsAliasAddress(), func(tx *ledgerstate.Transaction) { + c.metrics.GetInTransaction().CountLastMessage(tx) + fun(tx) + }) +} + +func (c *chainNodeConnImplementation) AttachToInclusionStateReceived(fun chain.NodeConnectionHandleInclusionStateFun) { + c.log.Debugf("ChainNodeConnImplementation::AttachToInclusionStateReceived") + c.nodeConn.AttachToInclusionStateReceived(c.chainID.AsAliasAddress(), func(txID ledgerstate.TransactionID, iState ledgerstate.InclusionState) { + c.metrics.GetInInclusionState().CountLastMessage(struct { + TransactionID ledgerstate.TransactionID + InclusionState ledgerstate.InclusionState + }{ + TransactionID: txID, + InclusionState: iState, + }) + fun(txID, iState) + }) +} + +func (c *chainNodeConnImplementation) AttachToOutputReceived(fun chain.NodeConnectionHandleOutputFun) { + c.log.Debugf("ChainNodeConnImplementation::AttachToOutputReceived") + c.nodeConn.AttachToOutputReceived(c.chainID.AsAliasAddress(), func(output ledgerstate.Output) { + c.metrics.GetInOutput().CountLastMessage(output) + fun(output) + }) +} + +func (c *chainNodeConnImplementation) AttachToUnspentAliasOutputReceived(fun chain.NodeConnectionHandleUnspentAliasOutputFun) { + c.log.Debugf("ChainNodeConnImplementation::AttachToUnspentAliasOutputReceived") + c.nodeConn.AttachToUnspentAliasOutputReceived(c.chainID.AsAliasAddress(), func(output *ledgerstate.AliasOutput, timestamp time.Time) { + c.metrics.GetInUnspentAliasOutput().CountLastMessage(struct { + AliasOutput *ledgerstate.AliasOutput + Timestamp time.Time + }{ + AliasOutput: output, + Timestamp: timestamp, + }) + fun(output, timestamp) + }) +} + +func (c *chainNodeConnImplementation) DetachFromTransactionReceived() { + c.log.Debugf("ChainNodeConnImplementation::DetachFromTransactionReceived") + c.nodeConn.DetachFromTransactionReceived(c.chainID.AsAliasAddress()) +} + +func (c *chainNodeConnImplementation) DetachFromInclusionStateReceived() { + c.log.Debugf("ChainNodeConnImplementation::DetachFromInclusionStateReceived") + c.nodeConn.DetachFromInclusionStateReceived(c.chainID.AsAliasAddress()) +} + +func (c *chainNodeConnImplementation) DetachFromOutputReceived() { + c.log.Debugf("ChainNodeConnImplementation::DetachFromOutputReceived") + c.nodeConn.DetachFromOutputReceived(c.chainID.AsAliasAddress()) +} + +func (c *chainNodeConnImplementation) DetachFromUnspentAliasOutputReceived() { + c.log.Debugf("ChainNodeConnImplementation::DetachFromUnspentAliasOutputReceived") + c.nodeConn.DetachFromUnspentAliasOutputReceived(c.chainID.AsAliasAddress()) +} + +func (c *chainNodeConnImplementation) PullState() { + c.log.Debugf("ChainNodeConnection::PullState...") + c.metrics.GetOutPullState().CountLastMessage(nil) + c.nodeConn.PullState(c.chainID.AsAliasAddress()) + c.log.Debugf("ChainNodeConnection::PullState... Done") +} + +func (c *chainNodeConnImplementation) PullTransactionInclusionState(txID ledgerstate.TransactionID) { + txIDStr := txID.Base58() + c.log.Debugf("ChainNodeConnImplementation::PullTransactionInclusionState(txID=%v)...", txIDStr) + c.metrics.GetOutPullTransactionInclusionState().CountLastMessage(txID) + c.nodeConn.PullTransactionInclusionState(c.chainID.AsAddress(), txID) + c.log.Debugf("ChainNodeConnImplementation::PullTransactionInclusionState(txID=%v)... Done", txIDStr) +} + +func (c *chainNodeConnImplementation) PullConfirmedOutput(outputID ledgerstate.OutputID) { + outputIDStr := iscp.OID(outputID) + c.log.Debugf("ChainNodeConnImplementation::PullConfirmedOutput(outputID=%v)...", outputIDStr) + c.metrics.GetOutPullConfirmedOutput().CountLastMessage(outputID) + c.nodeConn.PullConfirmedOutput(c.chainID.AsAddress(), outputID) + c.log.Debugf("ChainNodeConnImplementation::PullConfirmedOutput(outputID=%v)... Done", outputIDStr) +} + +func (c *chainNodeConnImplementation) PostTransaction(tx *ledgerstate.Transaction) { + txIDStr := tx.ID().Base58() + c.log.Debugf("ChainNodeConnImplementation::PostTransaction(txID=%s)...", txIDStr) + c.metrics.GetOutPostTransaction().CountLastMessage(tx) + c.nodeConn.PostTransaction(tx) + c.log.Debugf("ChainNodeConnImplementation::PostTransaction(txID=%s)... Done", txIDStr) +} + +func (c *chainNodeConnImplementation) GetMetrics() nodeconnmetrics.NodeConnectionMessagesMetrics { + return c.metrics +} + +func (c *chainNodeConnImplementation) Close() { + c.log.Debugf("ChainNodeConnImplementation::Close") + c.DetachFromTransactionReceived() + c.DetachFromInclusionStateReceived() + c.DetachFromOutputReceived() + c.DetachFromUnspentAliasOutputReceived() +} diff --git a/packages/chain/nodeconnimpl/nodeconnimpl_test.go b/packages/chain/nodeconnimpl/nodeconnimpl_test.go new file mode 100644 index 0000000000..c20585cca1 --- /dev/null +++ b/packages/chain/nodeconnimpl/nodeconnimpl_test.go @@ -0,0 +1,27 @@ +package nodeconnimpl + +import ( + "net" + "testing" + "time" + + "github.com/iotaledger/goshimmer/packages/ledgerstate" + txstream "github.com/iotaledger/goshimmer/packages/txstream/client" + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" + "github.com/iotaledger/wasp/packages/testutil/testlogger" + "golang.org/x/xerrors" +) + +func TestBasic(t *testing.T) { + logger := testlogger.NewLogger(t) + + var addr ledgerstate.AliasAddress + nconn := txstream.New("dummyID", logger, func() (addr string, conn net.Conn, err error) { + return "", nil, xerrors.New("dummy dial error") + }) + nconnimpl := NewNodeConnection(nconn, nodeconnmetrics.NewEmptyNodeConnectionMetrics(), logger) + nconnimpl.AttachToTransactionReceived(&addr, func(*ledgerstate.Transaction) {}) + nconnimpl.AttachToInclusionStateReceived(&addr, func(ledgerstate.TransactionID, ledgerstate.InclusionState) {}) + nconnimpl.AttachToOutputReceived(&addr, func(ledgerstate.Output) {}) + nconnimpl.AttachToUnspentAliasOutputReceived(&addr, func(*ledgerstate.AliasOutput, time.Time) {}) +} diff --git a/packages/chain/statemgr/action.go b/packages/chain/statemgr/action.go index 9975b844f1..81aaeb9253 100644 --- a/packages/chain/statemgr/action.go +++ b/packages/chain/statemgr/action.go @@ -48,7 +48,7 @@ func (sm *stateManager) notifyChainTransitionIfNeeded() { } sm.log.Debugf("notifyStateTransition: %sstate IS SYNCED to index %d and is approved by output %v", gu, stateOutputIndex, iscp.OID(stateOutputID)) - sm.chain.Events().ChainTransition().Trigger(&chain.ChainTransitionEventData{ + sm.chain.TriggerChainTransition(&chain.ChainTransitionEventData{ VirtualState: sm.solidState.Copy(), ChainOutput: sm.stateOutput, OutputTimestamp: sm.stateOutputTimestamp, @@ -66,7 +66,7 @@ func (sm *stateManager) pullStateIfNeeded() { nowis := time.Now() if nowis.After(sm.pullStateRetryTime) { chainAliasAddress := sm.chain.ID().AsAliasAddress() - sm.nodeConn.PullState(chainAliasAddress) + sm.nodeConn.PullState() sm.pullStateRetryTime = nowis.Add(sm.timers.PullStateRetry) sm.log.Debugf("pullState: pulling state for address %v. Next pull in: %v", chainAliasAddress.Base58(), sm.pullStateRetryTime.Sub(nowis)) @@ -127,9 +127,8 @@ func (sm *stateManager) addBlockFromPeer(block state.Block) bool { } if sm.addBlockAndCheckStateOutput(block, nil) { // ask for approving output - chainAddress := sm.chain.ID().AsAddress() - sm.log.Debugf("addBlockFromPeer: requesting approving output ID %v for chain %v", iscp.OID(block.ApprovingOutputID()), chainAddress.Base58()) - sm.nodeConn.PullConfirmedOutput(chainAddress, block.ApprovingOutputID()) + sm.log.Debugf("addBlockFromPeer: requesting approving output ID %v", iscp.OID(block.ApprovingOutputID())) + sm.nodeConn.PullConfirmedOutput(block.ApprovingOutputID()) } return true } diff --git a/packages/chain/statemgr/eventproc.go b/packages/chain/statemgr/eventproc.go index 75e6d6f619..c3a5a4c2cf 100644 --- a/packages/chain/statemgr/eventproc.go +++ b/packages/chain/statemgr/eventproc.go @@ -8,64 +8,66 @@ import ( "github.com/iotaledger/wasp/packages/chain/messages" "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/state" "github.com/iotaledger/wasp/packages/util" ) // EventGetBlockMsg is a request for a block while syncing -func (sm *stateManager) EventGetBlockMsg(msg *messages.GetBlockMsg) { - sm.eventGetBlockMsgCh <- msg +func (sm *stateManager) EnqueueGetBlockMsg(msg *messages.GetBlockMsgIn) { + sm.eventGetBlockMsgPipe.In() <- msg } -func (sm *stateManager) eventGetBlockMsg(msg *messages.GetBlockMsg) { - sm.log.Debugw("EventGetBlockMsg received: ", +func (sm *stateManager) handleGetBlockMsg(msg *messages.GetBlockMsgIn) { + sm.log.Debugw("handleGetBlockMsg: ", "sender", msg.SenderNetID, "block index", msg.BlockIndex, ) if sm.stateOutput == nil { // Not a necessary check, only for optimization. - sm.log.Debugf("EventGetBlockMsg ignored: stateOutput is nil") + sm.log.Debugf("handleGetBlockMsg: message ignored: stateOutput is nil") return } if msg.BlockIndex > sm.stateOutput.GetStateIndex() { // Not a necessary check, only for optimization. - sm.log.Debugf("EventGetBlockMsg ignored 1: block #%d not found. Current state index: #%d", + sm.log.Debugf("handleGetBlockMsg: message ignored 1: block #%d not found. Current state index: #%d", msg.BlockIndex, sm.stateOutput.GetStateIndex()) return } blockBytes, err := state.LoadBlockBytes(sm.store, msg.BlockIndex) if err != nil { - sm.log.Errorf("EventGetBlockMsg: LoadBlockBytes: %v", err) + sm.log.Errorf("handleGetBlockMsg: LoadBlockBytes error: %v", err) return } if blockBytes == nil { - sm.log.Debugf("EventGetBlockMsg ignored 2: block #%d not found. Current state index: #%d", + sm.log.Debugf("handleGetBlockMsg message ignored 2: block #%d not found. Current state index: #%d", msg.BlockIndex, sm.stateOutput.GetStateIndex()) return } - sm.log.Debugf("EventGetBlockMsg for state index #%d --> responding to peer %s", msg.BlockIndex, msg.SenderNetID) + sm.log.Debugf("handleGetBlockMsg: responding to peer %s by block %v", msg.SenderNetID, msg.BlockIndex) - sm.peers.SendSimple(msg.SenderNetID, messages.MsgBlock, util.MustBytes(&messages.BlockMsg{ - BlockBytes: blockBytes, - })) + blockMsg := &messages.BlockMsg{BlockBytes: blockBytes} + sm.chainPeers.SendMsgByNetID(msg.SenderNetID, peering.PeerMessageReceiverStateManager, peerMsgTypeBlock, util.MustBytes(blockMsg)) } // EventBlockMsg -func (sm *stateManager) EventBlockMsg(msg *messages.BlockMsg) { - sm.eventBlockMsgCh <- msg +func (sm *stateManager) EnqueueBlockMsg(msg *messages.BlockMsgIn) { + sm.eventBlockMsgPipe.In() <- msg } -func (sm *stateManager) eventBlockMsg(msg *messages.BlockMsg) { - sm.log.Debugf("EventBlockMsg received from %v", msg.SenderNetID) +func (sm *stateManager) handleBlockMsg(msg *messages.BlockMsgIn) { + sm.log.Debugw("handleBlockMsg: ", + "sender", msg.SenderNetID, + ) if sm.stateOutput == nil { - sm.log.Debugf("EventBlockMsg ignored: stateOutput is nil") + sm.log.Debugf("handleBlockMsg: message ignored: stateOutput is nil") return } block, err := state.BlockFromBytes(msg.BlockBytes) if err != nil { - sm.log.Warnf("EventBlockMsg 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.SenderNetID, err) return } - sm.log.Debugw("EventBlockMsg from ", + sm.log.Debugw("handleBlockMsg: adding block from peer ", "sender", msg.SenderNetID, "block index", block.BlockIndex(), "approving output", iscp.OID(block.ApprovingOutputID()), @@ -75,11 +77,11 @@ func (sm *stateManager) eventBlockMsg(msg *messages.BlockMsg) { } } -func (sm *stateManager) EventOutputMsg(msg ledgerstate.Output) { - sm.eventOutputMsgCh <- msg +func (sm *stateManager) EnqueueOutputMsg(msg ledgerstate.Output) { + sm.eventOutputMsgPipe.In() <- msg } -func (sm *stateManager) eventOutputMsg(msg ledgerstate.Output) { +func (sm *stateManager) handleOutputMsg(msg ledgerstate.Output) { sm.log.Debugf("EventOutputMsg received: %s", iscp.OID(msg.ID())) chainOutput, ok := msg.(*ledgerstate.AliasOutput) if !ok { @@ -93,11 +95,11 @@ func (sm *stateManager) eventOutputMsg(msg ledgerstate.Output) { // EventStateTransactionMsg triggered whenever new state transaction arrives // the state transaction may be confirmed or not -func (sm *stateManager) EventStateMsg(msg *messages.StateMsg) { - sm.eventStateOutputMsgCh <- msg +func (sm *stateManager) EnqueueStateMsg(msg *messages.StateMsg) { + sm.eventStateOutputMsgPipe.In() <- msg } -func (sm *stateManager) eventStateMsg(msg *messages.StateMsg) { +func (sm *stateManager) handleStateMsg(msg *messages.StateMsg) { sm.log.Debugw("EventStateMsg received: ", "state index", msg.ChainOutput.GetStateIndex(), "chainOutput", iscp.OID(msg.ChainOutput.ID()), @@ -113,11 +115,14 @@ func (sm *stateManager) eventStateMsg(msg *messages.StateMsg) { } } -func (sm *stateManager) EventStateCandidateMsg(msg *messages.StateCandidateMsg) { - sm.eventStateCandidateMsgCh <- msg +func (sm *stateManager) EnqueueStateCandidateMsg(virtualState state.VirtualStateAccess, outputID ledgerstate.OutputID) { + sm.eventStateCandidateMsgPipe.In() <- &messages.StateCandidateMsg{ + State: virtualState, + ApprovingOutputID: outputID, + } } -func (sm *stateManager) eventStateCandidateMsg(msg *messages.StateCandidateMsg) { +func (sm *stateManager) handleStateCandidateMsg(msg *messages.StateCandidateMsg) { sm.log.Debugf("EventStateCandidateMsg received: state index: %d, timestamp: %v", msg.State.BlockIndex(), msg.State.Timestamp(), ) @@ -130,13 +135,13 @@ func (sm *stateManager) eventStateCandidateMsg(msg *messages.StateCandidateMsg) } } -func (sm *stateManager) EventTimerMsg(msg messages.TimerTick) { +func (sm *stateManager) EnqueueTimerMsg(msg messages.TimerTick) { if msg%2 == 0 { - sm.eventTimerMsgCh <- msg + sm.eventTimerMsgPipe.In() <- msg } } -func (sm *stateManager) eventTimerMsg() { +func (sm *stateManager) handleTimerMsg() { sm.log.Debugf("EventTimerMsg received") sm.takeAction() } diff --git a/packages/chain/statemgr/setup_test.go b/packages/chain/statemgr/setup_test.go index 3b054405fb..66c0fc142c 100644 --- a/packages/chain/statemgr/setup_test.go +++ b/packages/chain/statemgr/setup_test.go @@ -4,7 +4,6 @@ package statemgr import ( - "bytes" "io" "sync" "testing" @@ -56,6 +55,7 @@ type MockedNode struct { store kvstore.KVStore NodeConn *testchain.MockedNodeConn ChainCore *testchain.MockedChainCore + ChainPeers peering.PeerDomainProvider stateSync coreutil.ChainStateSync Peers peering.PeerDomainProvider StateManager chain.StateManager @@ -63,6 +63,10 @@ type MockedNode struct { Log *logger.Logger } +type MockedStateManagerMetrics struct{} + +func (c *MockedStateManagerMetrics) RecordBlockSize(_ uint32, _ float64) {} + func NewMockedEnv(nodeCount int, t *testing.T, debug bool) (*MockedEnv, *ledgerstate.Transaction) { level := zapcore.InfoLevel if debug { @@ -127,7 +131,7 @@ func (env *MockedEnv) pushStateToNodesIfSet(tx *ledgerstate.Transaction) { require.NoError(env.T, err) for _, node := range env.Nodes { - go node.StateManager.EventStateMsg(&messages.StateMsg{ + go node.StateManager.EnqueueStateMsg(&messages.StateMsg{ ChainOutput: stateOutput, Timestamp: tx.Essence().Timestamp(), }) @@ -151,9 +155,9 @@ func (env *MockedEnv) PostTransactionToLedger(tx *ledgerstate.Transaction) { env.Log.Infof("MockedEnv.PostTransactionToLedger: posted transaction to ledger: %s", tx.ID().Base58()) } -func (env *MockedEnv) PullStateFromLedger(addr *ledgerstate.AliasAddress) *messages.StateMsg { - env.Log.Debugf("MockedEnv.PullStateFromLedger request received for address %v", addr.Base58) - outputs := env.Ledger.GetAddressOutputs(addr) +func (env *MockedEnv) PullStateFromLedger() *messages.StateMsg { + env.Log.Debugf("MockedEnv.PullStateFromLedger request received") + outputs := env.Ledger.GetAddressOutputs(env.ChainID.AsAliasAddress()) require.EqualValues(env.T, 1, len(outputs)) outTx, ok := env.Ledger.GetTransaction(outputs[0].ID().TransactionID()) require.True(env.T, ok) @@ -167,8 +171,8 @@ func (env *MockedEnv) PullStateFromLedger(addr *ledgerstate.AliasAddress) *messa } } -func (env *MockedEnv) PullConfirmedOutputFromLedger(addr ledgerstate.Address, outputID ledgerstate.OutputID) ledgerstate.Output { - env.Log.Debugf("MockedEnv.PullConfirmedOutputFromLedger for address %v output %v", addr.Base58, iscp.OID(outputID)) +func (env *MockedEnv) PullConfirmedOutputFromLedger(outputID ledgerstate.OutputID) ledgerstate.Output { + env.Log.Debugf("MockedEnv.PullConfirmedOutputFromLedger for output %v", iscp.OID(outputID)) tx, foundTx := env.Ledger.GetTransaction(outputID.TransactionID()) require.True(env.T, foundTx) outputIndex := outputID.OutputIndex() @@ -183,76 +187,76 @@ func (env *MockedEnv) PullConfirmedOutputFromLedger(addr ledgerstate.Address, ou 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.NodeIDs) + peers, err := env.NetworkProviders[nodeIndex].PeerDomain(env.ChainID.Array(), env.NodeIDs) require.NoError(env.T, err) ret := &MockedNode{ - NetID: nodeID, - Env: env, - NodeConn: testchain.NewMockedNodeConnection("Node_" + nodeID), - store: mapdb.NewMapDB(), - stateSync: coreutil.NewChainStateSync(), - ChainCore: testchain.NewMockedChainCore(env.T, env.ChainID, log), - Peers: peers, - Log: log, + NetID: nodeID, + Env: env, + NodeConn: testchain.NewMockedNodeConnection("Node_" + nodeID), + store: mapdb.NewMapDB(), + stateSync: coreutil.NewChainStateSync(), + ChainCore: testchain.NewMockedChainCore(env.T, env.ChainID, log), + ChainPeers: peers, + Peers: peers, + Log: log, } + + stateMgrMetrics := new(MockedStateManagerMetrics) ret.ChainCore.OnGlobalStateSync(func() coreutil.ChainStateSync { return ret.stateSync }) ret.ChainCore.OnGetStateReader(func() state.OptimisticStateReader { return state.NewOptimisticStateReader(ret.store, ret.stateSync) }) - ret.StateManager = New(ret.store, ret.ChainCore, ret.Peers, ret.NodeConn, timers) + ret.ChainPeers.Attach(peering.PeerMessageReceiverStateManager, func(peerMsg *peering.PeerMessageIn) { + log.Debugf("State manager recvEvent from %v of type %v", peerMsg.SenderNetID, peerMsg.MsgType) + switch peerMsg.MsgType { + case peerMsgTypeGetBlock: + msg, err := messages.NewGetBlockMsg(peerMsg.MsgData) + if err != nil { + log.Error(err) + return + } + ret.StateManager.EnqueueGetBlockMsg(&messages.GetBlockMsgIn{ + GetBlockMsg: *msg, + SenderNetID: peerMsg.SenderNetID, + }) + case peerMsgTypeBlock: + msg, err := messages.NewBlockMsg(peerMsg.MsgData) + if err != nil { + log.Error(err) + return + } + ret.StateManager.EnqueueBlockMsg(&messages.BlockMsgIn{ + BlockMsg: *msg, + SenderNetID: peerMsg.SenderNetID, + }) + } + }) + ret.StateManager = New(ret.store, ret.ChainCore, ret.ChainPeers, ret.NodeConn, stateMgrMetrics, 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()) - go ret.StateManager.EventStateCandidateMsg(&messages.StateCandidateMsg{State: vstate}) + stateOutput, err := utxoutil.GetSingleChainedAliasOutput(tx) + require.NoError(env.T, err) + go ret.StateManager.EnqueueStateCandidateMsg(vstate, stateOutput.ID()) go ret.NodeConn.PostTransaction(tx) }) ret.NodeConn.OnPostTransaction(func(tx *ledgerstate.Transaction) { log.Debugf("MockedNode.OnPostTransaction: transaction %v posted", tx.ID().Base58()) env.PostTransactionToLedger(tx) }) - ret.NodeConn.OnPullState(func(addr *ledgerstate.AliasAddress) { - log.Debugf("MockedNode.OnPullState request received for address %v", addr.Base58) - response := env.PullStateFromLedger(addr) + ret.NodeConn.OnPullState(func() { + log.Debugf("MockedNode.OnPullState request received") + response := env.PullStateFromLedger() log.Debugf("MockedNode.OnPullState call EventStateMsg: chain output %s", iscp.OID(response.ChainOutput.ID())) - go ret.StateManager.EventStateMsg(response) + go ret.StateManager.EnqueueStateMsg(response) }) - ret.NodeConn.OnPullConfirmedOutput(func(addr ledgerstate.Address, outputID ledgerstate.OutputID) { + ret.NodeConn.OnPullConfirmedOutput(func(outputID ledgerstate.OutputID) { log.Debugf("MockedNode.OnPullConfirmedOutput %v", iscp.OID(outputID)) - response := env.PullConfirmedOutputFromLedger(addr, outputID) + response := env.PullConfirmedOutputFromLedger(outputID) log.Debugf("MockedNode.OnPullConfirmedOutput call EventOutputMsg") - go ret.StateManager.EventOutputMsg(response) - }) - var peeringID peering.PeeringID = env.ChainID.Array() - peers.Attach(&peeringID, func(recvEvent *peering.RecvEvent) { - log.Debugf("MockedChain recvEvent from %v of type %v", recvEvent.From.NetID(), recvEvent.Msg.MsgType) - rdr := bytes.NewReader(recvEvent.Msg.MsgData) - - switch recvEvent.Msg.MsgType { - case messages.MsgGetBlock: - msgt := &messages.GetBlockMsg{} - if err := msgt.Read(rdr); err != nil { - log.Error(err) - return - } - - msgt.SenderNetID = recvEvent.Msg.SenderNetID - ret.StateManager.EventGetBlockMsg(msgt) - - case messages.MsgBlock: - msgt := &messages.BlockMsg{} - if err := msgt.Read(rdr); err != nil { - log.Error(err) - return - } - - msgt.SenderNetID = recvEvent.Msg.SenderNetID - ret.StateManager.EventBlockMsg(msgt) - - default: - log.Errorf("MockedChain recvEvent: wrong msg type") - } + go ret.StateManager.EnqueueOutputMsg(response) }) return ret @@ -263,7 +267,7 @@ func (node *MockedNode) StartTimer() { node.StateManager.Ready().MustWait() counter := 0 for { - node.StateManager.EventTimerMsg(messages.TimerTick(counter)) + node.StateManager.EnqueueTimerMsg(messages.TimerTick(counter)) counter++ time.Sleep(50 * time.Millisecond) } diff --git a/packages/chain/statemgr/statemgr.go b/packages/chain/statemgr/statemgr.go index dbd0b63783..af97409e56 100644 --- a/packages/chain/statemgr/statemgr.go +++ b/packages/chain/statemgr/statemgr.go @@ -14,44 +14,53 @@ import ( "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/chain/messages" + "github.com/iotaledger/wasp/packages/metrics" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/state" + "github.com/iotaledger/wasp/packages/util/pipe" "github.com/iotaledger/wasp/packages/util/ready" "go.uber.org/atomic" ) type stateManager struct { - ready *ready.Ready - store kvstore.KVStore - chain chain.ChainCore - peers peering.PeerDomainProvider - nodeConn chain.NodeConnection - pullStateRetryTime time.Time - solidState state.VirtualStateAccess - stateOutput *ledgerstate.AliasOutput - stateOutputTimestamp time.Time - currentSyncData atomic.Value - notifiedAnchorOutputID ledgerstate.OutputID - syncingBlocks *syncingBlocks - timers StateManagerTimers - log *logger.Logger + ready *ready.Ready + store kvstore.KVStore + chain chain.ChainCore + chainPeers peering.PeerDomainProvider + nodeConn chain.ChainNodeConnection + pullStateRetryTime time.Time + solidState state.VirtualStateAccess + stateOutput *ledgerstate.AliasOutput + stateOutputTimestamp time.Time + currentSyncData atomic.Value + notifiedAnchorOutputID ledgerstate.OutputID + syncingBlocks *syncingBlocks + receivePeerMessagesAttachID interface{} + timers StateManagerTimers + log *logger.Logger // Channels for accepting external events. - eventGetBlockMsgCh chan *messages.GetBlockMsg - eventBlockMsgCh chan *messages.BlockMsg - eventStateOutputMsgCh chan *messages.StateMsg - eventOutputMsgCh chan ledgerstate.Output - eventStateCandidateMsgCh chan *messages.StateCandidateMsg - eventTimerMsgCh chan messages.TimerTick - closeCh chan bool + eventGetBlockMsgPipe pipe.Pipe + eventBlockMsgPipe pipe.Pipe + eventStateOutputMsgPipe pipe.Pipe + eventOutputMsgPipe pipe.Pipe + eventStateCandidateMsgPipe pipe.Pipe + eventTimerMsgPipe pipe.Pipe + stateManagerMetrics metrics.StateManagerMetrics } +var _ chain.StateManager = &stateManager{} + const ( numberOfNodesToRequestBlockFromConst = 5 maxBlocksToCommitConst = 10000 // 10k + maxMsgBuffer = 1000 + + peerMsgTypeGetBlock = iota + peerMsgTypeBlock ) -func New(store kvstore.KVStore, c chain.ChainCore, peers peering.PeerDomainProvider, nodeconn chain.NodeConnection, timersOpt ...StateManagerTimers) chain.StateManager { +func New(store kvstore.KVStore, c chain.ChainCore, peers peering.PeerDomainProvider, nodeconn chain.ChainNodeConnection, stateManagerMetrics metrics.StateManagerMetrics, timersOpt ...StateManagerTimers) chain.StateManager { var timers StateManagerTimers if len(timersOpt) > 0 { timers = timersOpt[0] @@ -59,39 +68,74 @@ func New(store kvstore.KVStore, c chain.ChainCore, peers peering.PeerDomainProvi timers = NewStateManagerTimers() } ret := &stateManager{ - ready: ready.New(fmt.Sprintf("state manager %s", c.ID().Base58()[:6]+"..")), - store: store, - chain: c, - nodeConn: nodeconn, - peers: peers, - syncingBlocks: newSyncingBlocks(c.Log(), timers.GetBlockRetry), - timers: timers, - log: c.Log().Named("s"), - pullStateRetryTime: time.Now(), - eventGetBlockMsgCh: make(chan *messages.GetBlockMsg), - eventBlockMsgCh: make(chan *messages.BlockMsg), - eventStateOutputMsgCh: make(chan *messages.StateMsg), - eventOutputMsgCh: make(chan ledgerstate.Output), - eventStateCandidateMsgCh: make(chan *messages.StateCandidateMsg), - eventTimerMsgCh: make(chan messages.TimerTick), - closeCh: make(chan bool), + ready: ready.New(fmt.Sprintf("state manager %s", c.ID().Base58()[:6]+"..")), + store: store, + chain: c, + nodeConn: nodeconn, + chainPeers: peers, + syncingBlocks: newSyncingBlocks(c.Log(), timers.GetBlockRetry), + timers: timers, + log: c.Log().Named("s"), + pullStateRetryTime: time.Now(), + eventGetBlockMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + eventBlockMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + eventStateOutputMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + eventOutputMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + eventStateCandidateMsgPipe: pipe.NewLimitInfinitePipe(maxMsgBuffer), + eventTimerMsgPipe: pipe.NewLimitInfinitePipe(1), + stateManagerMetrics: stateManagerMetrics, } + ret.receivePeerMessagesAttachID = ret.chainPeers.Attach(peering.PeerMessageReceiverStateManager, ret.receiveChainPeerMessages) + ret.nodeConn.AttachToOutputReceived(ret.EnqueueOutputMsg) go ret.initLoadState() return ret } +func (sm *stateManager) receiveChainPeerMessages(peerMsg *peering.PeerMessageIn) { + switch peerMsg.MsgType { + case peerMsgTypeGetBlock: + msg, err := messages.NewGetBlockMsg(peerMsg.MsgData) + if err != nil { + sm.log.Error(err) + return + } + sm.EnqueueGetBlockMsg(&messages.GetBlockMsgIn{ + GetBlockMsg: *msg, + SenderNetID: peerMsg.SenderNetID, + }) + case peerMsgTypeBlock: + msg, err := messages.NewBlockMsg(peerMsg.MsgData) + if err != nil { + sm.log.Error(err) + return + } + sm.EnqueueBlockMsg(&messages.BlockMsgIn{ + BlockMsg: *msg, + SenderNetID: peerMsg.SenderNetID, + }) + default: + sm.log.Warnf("Wrong type of state manager message: %v, ignoring it", peerMsg.MsgType) + } +} + func (sm *stateManager) Close() { - close(sm.closeCh) + sm.nodeConn.DetachFromOutputReceived() + sm.chainPeers.Detach(sm.receivePeerMessagesAttachID) + + sm.eventGetBlockMsgPipe.Close() + sm.eventBlockMsgPipe.Close() + sm.eventStateOutputMsgPipe.Close() + sm.eventOutputMsgPipe.Close() + sm.eventStateCandidateMsgPipe.Close() + sm.eventTimerMsgPipe.Close() } // initial loading of the solid state func (sm *stateManager) initLoadState() { solidState, stateExists, err := state.LoadSolidState(sm.store, sm.chain.ID()) if err != nil { - go sm.chain.ReceiveMessage(messages.DismissChainMsg{ - Reason: fmt.Sprintf("StateManager.initLoadState: %v", err), - }) + sm.chain.EnqueueDismissChain(fmt.Sprintf("StateManager.initLoadState: %v", err)) return } if stateExists { @@ -101,9 +145,7 @@ func (sm *stateManager) initLoadState() { solidState.BlockIndex(), solidState.StateCommitment().String()) } else if err := sm.createOriginState(); err != nil { // create origin state in DB - go sm.chain.ReceiveMessage(messages.DismissChainMsg{ - Reason: fmt.Sprintf("StateManager.initLoadState. Failed to create origin state: %v", err), - }) + sm.chain.EnqueueDismissChain(fmt.Sprintf("StateManager.initLoadState. Failed to create origin state: %v", err)) return } sm.recvLoop() // Check to process external events. @@ -117,10 +159,7 @@ func (sm *stateManager) createOriginState() error { sm.chain.GlobalStateSync().SetSolidIndex(0) if err != nil { - go sm.chain.ReceiveMessage(messages.DismissChainMsg{ - Reason: fmt.Sprintf("StateManager.initLoadState. Failed to create origin state: %v", err), - }, - ) + sm.chain.EnqueueDismissChain(fmt.Sprintf("StateManager.initLoadState. Failed to create origin state: %v", err)) return err } sm.log.Infof("ORIGIN STATE has been created") @@ -141,33 +180,57 @@ func (sm *stateManager) GetStatusSnapshot() *chain.SyncInfo { func (sm *stateManager) recvLoop() { sm.ready.SetReady() + eventGetBlockMsgCh := sm.eventGetBlockMsgPipe.Out() + eventBlockMsgCh := sm.eventBlockMsgPipe.Out() + eventStateOutputMsgCh := sm.eventStateOutputMsgPipe.Out() + eventOutputMsgCh := sm.eventOutputMsgPipe.Out() + eventStateCandidateMsgCh := sm.eventStateCandidateMsgPipe.Out() + eventTimerMsgCh := sm.eventTimerMsgPipe.Out() for { select { - case msg, ok := <-sm.eventGetBlockMsgCh: + case msg, ok := <-eventGetBlockMsgCh: if ok { - sm.eventGetBlockMsg(msg) + sm.handleGetBlockMsg(msg.(*messages.GetBlockMsgIn)) + } else { + eventGetBlockMsgCh = nil } - case msg, ok := <-sm.eventBlockMsgCh: + case msg, ok := <-eventBlockMsgCh: if ok { - sm.eventBlockMsg(msg) + sm.handleBlockMsg(msg.(*messages.BlockMsgIn)) + } else { + eventBlockMsgCh = nil } - case msg, ok := <-sm.eventStateOutputMsgCh: + case msg, ok := <-eventStateOutputMsgCh: if ok { - sm.eventStateMsg(msg) + sm.handleStateMsg(msg.(*messages.StateMsg)) + } else { + eventStateOutputMsgCh = nil } - case msg, ok := <-sm.eventOutputMsgCh: + case msg, ok := <-eventOutputMsgCh: if ok { - sm.eventOutputMsg(msg) + sm.handleOutputMsg(msg.(ledgerstate.Output)) + } else { + eventOutputMsgCh = nil } - case msg, ok := <-sm.eventStateCandidateMsgCh: + case msg, ok := <-eventStateCandidateMsgCh: if ok { - sm.eventStateCandidateMsg(msg) + sm.handleStateCandidateMsg(msg.(*messages.StateCandidateMsg)) + } else { + eventStateCandidateMsgCh = nil } - case _, ok := <-sm.eventTimerMsgCh: + case _, ok := <-eventTimerMsgCh: if ok { - sm.eventTimerMsg() + sm.handleTimerMsg() + } else { + eventTimerMsgCh = nil } - case <-sm.closeCh: + } + if eventGetBlockMsgCh == nil && + eventBlockMsgCh == nil && + eventStateOutputMsgCh == nil && + eventOutputMsgCh == nil && + eventStateCandidateMsgCh == nil && + eventTimerMsgCh == nil { return } } diff --git a/packages/chain/statemgr/statemgr_test.go b/packages/chain/statemgr/statemgr_test.go index fc19db3900..9447c27ec4 100644 --- a/packages/chain/statemgr/statemgr_test.go +++ b/packages/chain/statemgr/statemgr_test.go @@ -220,8 +220,7 @@ func TestCatchUpNoConfirmedOutput(t *testing.T) { const targetBlockIndex = 10 node.OnStateTransitionMakeNewStateTransition(targetBlockIndex) - node.NodeConn.OnPullConfirmedOutput(func(addr ledgerstate.Address, outputID ledgerstate.OutputID) { - }) + node.NodeConn.OnPullConfirmedOutput(func(outputID ledgerstate.OutputID) {}) waitSyncBlockIndexAndCheck(10*time.Second, t, node, targetBlockIndex) node1 := env.NewMockedNode(1, NewStateManagerTimers()) diff --git a/packages/chain/statemgr/syncmgr.go b/packages/chain/statemgr/syncmgr.go index cdb31e75c6..aa0d023c94 100644 --- a/packages/chain/statemgr/syncmgr.go +++ b/packages/chain/statemgr/syncmgr.go @@ -9,6 +9,7 @@ import ( "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/wasp/packages/chain/messages" "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/state" "github.com/iotaledger/wasp/packages/util" ) @@ -79,20 +80,15 @@ func (sm *stateManager) doSyncActionIfNeeded() { i, requestBlockRetryTime, blockCandidatesCount, approvedBlockCandidatesCount) // TODO: temporary if. We need to find a solution to synchronize over large gaps. Making state snapshots may help. if i > startSyncFromIndex+maxBlocksToCommitConst { - go sm.chain.ReceiveMessage(messages.DismissChainMsg{ - Reason: fmt.Sprintf("StateManager.doSyncActionIfNeeded: too many blocks to catch up: %v", sm.stateOutput.GetStateIndex()-startSyncFromIndex+1), - }, - ) + sm.chain.EnqueueDismissChain(fmt.Sprintf("StateManager.doSyncActionIfNeeded: too many blocks to catch up: %v", sm.stateOutput.GetStateIndex()-startSyncFromIndex+1)) return } nowis := time.Now() if nowis.After(requestBlockRetryTime) { // have to pull sm.log.Debugf("doSyncAction: requesting block index %v from %v random peers", i, numberOfNodesToRequestBlockFromConst) - data := util.MustBytes(&messages.GetBlockMsg{ - BlockIndex: i, - }) - sm.peers.SendMsgToRandomPeersSimple(numberOfNodesToRequestBlockFromConst, messages.MsgGetBlock, data) + getBlockMsg := &messages.GetBlockMsg{BlockIndex: i} + sm.chainPeers.SendPeerMsgToRandomPeers(numberOfNodesToRequestBlockFromConst, peering.PeerMessageReceiverStateManager, peerMsgTypeGetBlock, util.MustBytes(getBlockMsg)) sm.syncingBlocks.startSyncingIfNeeded(i) sm.syncingBlocks.setRequestBlockRetryTime(i, nowis.Add(sm.timers.GetBlockRetry)) if blockCandidatesCount == 0 { @@ -180,6 +176,9 @@ func (sm *stateManager) commitCandidates(candidates []*candidateBlock, tentative // - any view call will return 'state invalidated message' sm.chain.GlobalStateSync().InvalidateSolidIndex() err := tentativeState.Commit(blocks...) + for _, block := range blocks { + sm.stateManagerMetrics.RecordBlockSize(block.BlockIndex(), float64(len(block.Bytes()))) + } sm.chain.GlobalStateSync().SetSolidIndex(tentativeState.BlockIndex()) if err != nil { diff --git a/packages/chains/chains.go b/packages/chains/chains.go index d0f2233548..ca40a77ab7 100644 --- a/packages/chains/chains.go +++ b/packages/chains/chains.go @@ -5,14 +5,13 @@ import ( "time" "github.com/iotaledger/goshimmer/packages/ledgerstate" - txstream "github.com/iotaledger/goshimmer/packages/txstream/client" - "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/chain/chainimpl" "github.com/iotaledger/wasp/packages/database/dbmanager" "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" @@ -34,7 +33,7 @@ type Chains struct { mutex sync.RWMutex log *logger.Logger allChains map[[ledgerstate.AddressLength]byte]chain.Chain - nodeConn *txstream.Client + nodeConn chain.NodeConnection processorConfig *processors.Config offledgerBroadcastUpToNPeers int offledgerBroadcastInterval time.Duration @@ -75,15 +74,11 @@ func (c *Chains) Dismiss() { c.allChains = make(map[[ledgerstate.AddressLength]byte]chain.Chain) } -func (c *Chains) Attach(nodeConn *txstream.Client) { +func (c *Chains) SetNodeConn(nodeConn chain.NodeConnection) { if c.nodeConn != nil { - c.log.Panicf("Chains: already attached") + c.log.Panicf("Chains: node conn already set") } c.nodeConn = nodeConn - c.nodeConn.Events.TransactionReceived.Attach(events.NewClosure(c.dispatchTransactionMsg)) - c.nodeConn.Events.InclusionStateReceived.Attach(events.NewClosure(c.dispatchInclusionStateMsg)) - c.nodeConn.Events.OutputReceived.Attach(events.NewClosure(c.dispatchOutputMsg)) - c.nodeConn.Events.UnspentAliasOutputReceived.Attach(events.NewClosure(c.dispatchUnspentAliasOutputMsg)) } func (c *Chains) ActivateAllFromRegistry(registryProvider registry.Provider, allMetrics *metrics.Metrics) error { @@ -120,8 +115,8 @@ func (c *Chains) Activate(chr *registry.ChainRecord, registryProvider registry.P return xerrors.Errorf("cannot activate chain for deactivated chain record") } chainArr := chr.ChainID.Array() - _, ok := c.allChains[chainArr] - if ok { + ret, ok := c.allChains[chainArr] + if ok && !ret.IsDismissed() { c.log.Debugf("chain is already active: %s", chr.ChainID.String()) return nil } @@ -181,16 +176,22 @@ func (c *Chains) Deactivate(chr *registry.ChainRecord) error { // Get returns active chain object or nil if it doesn't exist // lazy unsubscribing -func (c *Chains) Get(chainID *iscp.ChainID) chain.Chain { +func (c *Chains) Get(chainID *iscp.ChainID, includeDeactivated ...bool) chain.Chain { c.mutex.RLock() defer c.mutex.RUnlock() addrArr := chainID.Array() ret, ok := c.allChains[addrArr] + + if len(includeDeactivated) > 0 && includeDeactivated[0] { + return ret + } if ok && ret.IsDismissed() { - delete(c.allChains, addrArr) - c.nodeConn.Unsubscribe(chainID.AliasAddress) return nil } return ret } + +func (c *Chains) GetNodeConnectionMetrics() nodeconnmetrics.NodeConnectionMetrics { + return c.nodeConn.GetMetrics() +} diff --git a/packages/chains/chains_test.go b/packages/chains/chains_test.go index afc22a205e..c89076a039 100644 --- a/packages/chains/chains_test.go +++ b/packages/chains/chains_test.go @@ -1,18 +1,15 @@ package chains import ( - "net" "testing" "time" "github.com/iotaledger/goshimmer/packages/database" - txstream "github.com/iotaledger/goshimmer/packages/txstream/client" "github.com/iotaledger/hive.go/kvstore" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/testutil/testlogger" "github.com/iotaledger/wasp/packages/vm/processors" "github.com/stretchr/testify/require" - "golang.org/x/xerrors" ) func TestBasic(t *testing.T) { @@ -23,10 +20,5 @@ func TestBasic(t *testing.T) { return db.NewStore() } - ch := New(logger, processors.NewConfig(), 10, time.Second, false, nil, getOrCreateKVStore) - - nconn := txstream.New("dummyID", logger, func() (addr string, conn net.Conn, err error) { - return "", nil, xerrors.New("dummy dial error") - }) - ch.Attach(nconn) + _ = New(logger, processors.NewConfig(), 10, time.Second, false, nil, getOrCreateKVStore) } diff --git a/packages/chains/dispatch.go b/packages/chains/dispatch.go deleted file mode 100644 index 3688bd5a5a..0000000000 --- a/packages/chains/dispatch.go +++ /dev/null @@ -1,87 +0,0 @@ -package chains - -import ( - "github.com/iotaledger/goshimmer/packages/ledgerstate" - "github.com/iotaledger/goshimmer/packages/txstream" - "github.com/iotaledger/wasp/packages/iscp" -) - -func (c *Chains) dispatchTransactionMsg(msg *txstream.MsgTransaction) { - c.log.Debugf("NodeConnImplementation::dispatchTransactionMsg...") - defer c.log.Debugf("NodeConnImplementation::dispatchTransactionMsg... Done") - aliasAddr, ok := msg.Address.(*ledgerstate.AliasAddress) - if !ok { - c.log.Warnf("chains: cannot dispatch transaction message to non-alias address") - return - } - chainID := iscp.NewChainID(aliasAddr) - chain := c.Get(chainID) - if chain == nil { - // not interested in this chainID - return - } - c.log.Debugw("dispatch transaction", - "txid", msg.Tx.ID().Base58(), - "chainid", chainID.String(), - ) - chain.ReceiveTransaction(msg.Tx) -} - -func (c *Chains) dispatchInclusionStateMsg(msg *txstream.MsgTxInclusionState) { - c.log.Debugf("NodeConnImplementation::dispatchInclusionStateMsg...") - defer c.log.Debugf("NodeConnImplementation::dispatchInclusionStateMsg... Done") - aliasAddr, ok := msg.Address.(*ledgerstate.AliasAddress) - if !ok { - c.log.Warnf("chains: cannot dispatch inclusion state message to non-alias address") - return - } - chainID := iscp.NewChainID(aliasAddr) - chain := c.Get(chainID) - if chain == nil { - // not interested in this chainID - return - } - c.log.Debugw("dispatch transaction", - "txid", msg.TxID.Base58(), - "chainid", chainID.String(), - "inclusion", msg.State.String(), - ) - chain.ReceiveInclusionState(msg.TxID, msg.State) -} - -func (c *Chains) dispatchOutputMsg(msg *txstream.MsgOutput) { - c.log.Debugf("NodeConnImplementation::dispatchOutputMsg...") - defer c.log.Debugf("NodeConnImplementation::dispatchOutputMsg... Done") - aliasAddr, ok := msg.Address.(*ledgerstate.AliasAddress) - if !ok { - c.log.Warnf("chains: cannot dispatch output message to non-alias address") - return - } - chainID := iscp.NewChainID(aliasAddr) - chain := c.Get(chainID) - if chain == nil { - // not interested in this message - return - } - c.log.Debugw("dispatch output", - "outputID", iscp.OID(msg.Output.ID()), - "chainid", chainID.String(), - ) - chain.ReceiveOutput(msg.Output) -} - -func (c *Chains) dispatchUnspentAliasOutputMsg(msg *txstream.MsgUnspentAliasOutput) { - c.log.Debugf("NodeConnImplementation::dispatchUnspentAliasOutputMsg...") - defer c.log.Debugf("NodeConnImplementation::dispatchUnspentAliasOutputMsg... Done") - chainID := iscp.NewChainID(msg.AliasAddress) - chain := c.Get(chainID) - if chain == nil { - // not interested in this message - return - } - c.log.Debugw("dispatch state", - "outputID", iscp.OID(msg.AliasOutput.ID()), - "chainid", chainID.String(), - ) - chain.ReceiveState(msg.AliasOutput, msg.Timestamp) -} diff --git a/packages/dashboard/base.go b/packages/dashboard/base.go index df85bf0e9c..7e2b41737d 100644 --- a/packages/dashboard/base.go +++ b/packages/dashboard/base.go @@ -12,6 +12,7 @@ import ( "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/kv/dict" + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" "github.com/iotaledger/wasp/packages/registry" "github.com/iotaledger/wasp/packages/wasp" "github.com/labstack/echo/v4" @@ -45,6 +46,8 @@ type WaspServices interface { GetChainRecord(chainID *iscp.ChainID) (*registry.ChainRecord, error) GetChainCommitteeInfo(chainID *iscp.ChainID) (*chain.CommitteeInfo, error) CallView(chainID *iscp.ChainID, scName, fname string, params dict.Dict) (dict.Dict, error) + GetChainNodeConnectionMetrics(*iscp.ChainID) (nodeconnmetrics.NodeConnectionMessagesMetrics, error) + GetNodeConnectionMetrics() (nodeconnmetrics.NodeConnectionMetrics, error) } type Dashboard struct { @@ -70,6 +73,7 @@ func Init(server *echo.Echo, waspServices WaspServices, log *logger.Logger) *Das d.configInit(server, r), d.peeringInit(server, r), d.chainsInit(server, r), + d.metricsInit(server, r), } d.webSocketInit(server) @@ -93,18 +97,20 @@ func (d *Dashboard) BaseParams(c echo.Context, breadcrumbs ...Tab) BaseTemplateP func (d *Dashboard) makeTemplate(e *echo.Echo, parts ...string) *template.Template { t := template.New("").Funcs(template.FuncMap{ - "formatTimestamp": formatTimestamp, - "exploreAddressUrl": exploreAddressURL(d.wasp.ExploreAddressBaseURL()), - "args": args, - "hashref": hashref, - "colorref": colorref, - "trim": trim, - "incUint32": incUint32, - "decUint32": decUint32, - "bytesToString": bytesToString, - "base58": base58.Encode, - "replace": strings.Replace, - "uri": func(s string, p ...interface{}) string { return e.Reverse(s, p...) }, + "formatTimestamp": formatTimestamp, + "formatTimestampOrNever": formatTimestampOrNever, + "exploreAddressUrl": exploreAddressURL(d.wasp.ExploreAddressBaseURL()), + "args": args, + "hashref": hashref, + "colorref": colorref, + "trim": trim, + "incUint32": incUint32, + "decUint32": decUint32, + "bytesToString": bytesToString, + "keyToString": keyToString, + "base58": base58.Encode, + "replace": strings.Replace, + "uri": func(s string, p ...interface{}) string { return e.Reverse(s, p...) }, }) t = template.Must(t.Parse(tplBase)) for _, part := range parts { diff --git a/packages/dashboard/metrics.go b/packages/dashboard/metrics.go new file mode 100644 index 0000000000..c160cde263 --- /dev/null +++ b/packages/dashboard/metrics.go @@ -0,0 +1,41 @@ +package dashboard + +import ( + _ "embed" + "net/http" + + "github.com/labstack/echo/v4" +) + +//go:embed templates/metrics.tmpl +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) + return ret +} + +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) + + return Tab{ + Path: route.Path, + Title: "Metrics", + Href: route.Path, + } +} + +func (d *Dashboard) handleMetrics(c echo.Context) error { + return c.Render(http.StatusOK, c.Path(), &MetricsTemplateParams{ + BaseTemplateParams: d.BaseParams(c), + }) +} + +type MetricsTemplateParams struct { + BaseTemplateParams +} diff --git a/packages/dashboard/metrics_nodeconn.go b/packages/dashboard/metrics_nodeconn.go new file mode 100644 index 0000000000..8c1b0b5ace --- /dev/null +++ b/packages/dashboard/metrics_nodeconn.go @@ -0,0 +1,49 @@ +package dashboard + +import ( + _ "embed" + "net/http" + + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" + "github.com/labstack/echo/v4" +) + +//go:embed templates/metrics_nodeconn.tmpl +var tplMetricsNodeconn string + +func metricsNodeconnBreadcrumb(e *echo.Echo) Tab { + return Tab{ + Path: e.Reverse("metricsNodeconn"), + Title: "Metrics: Connection to L1", + Href: e.Reverse("metricsNodeconn"), + } +} + +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) +} + +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) + } + 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 new file mode 100644 index 0000000000..b4691b26b2 --- /dev/null +++ b/packages/dashboard/metrics_nodeconn_messages.go @@ -0,0 +1,49 @@ +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 52b674ac64..6a67a13cc4 100644 --- a/packages/dashboard/mock_test.go +++ b/packages/dashboard/mock_test.go @@ -12,6 +12,7 @@ import ( "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/kv/dict" + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" "github.com/iotaledger/wasp/packages/registry" "github.com/iotaledger/wasp/packages/solo" "github.com/iotaledger/wasp/packages/testutil/testlogger" @@ -125,6 +126,14 @@ func (w *waspServicesMock) GetChainCommitteeInfo(chainID *iscp.ChainID) (*chain. }, nil } +func (w *waspServicesMock) GetChainNodeConnectionMetrics(*iscp.ChainID) (nodeconnmetrics.NodeConnectionMessagesMetrics, error) { + panic("Not implemented") +} + +func (w *waspServicesMock) GetNodeConnectionMetrics() (nodeconnmetrics.NodeConnectionMetrics, error) { + panic("Not implemented") +} + type dashboardTestEnv struct { wasp *waspServicesMock echo *echo.Echo diff --git a/packages/dashboard/templates/chainblock.tmpl b/packages/dashboard/templates/chainblock.tmpl index b46879b07f..7432ef9605 100644 --- a/packages/dashboard/templates/chainblock.tmpl +++ b/packages/dashboard/templates/chainblock.tmpl @@ -12,31 +12,37 @@

Requests

-
-
#Total
{{ .Block.TotalRequests }}
-
#Successful
{{ .Block.NumSuccessfulRequests }}
-
#Off-ledger
{{ .Block.NumOffLedgerRequests }}
-
- - - - - - - - - - {{range $i, $r := .Receipts}} - - - - - - + {{ $req := $r.Request }} +
+

Request #{{$i}}

+
+
ID
{{ $req.ID.Base58 }}
+
Type
{{ if $req.IsOffLedger -}} off-ledger {{- else -}} on-ledger {{- end }}
+
Fee prepaid
{{ if $req.IsFeePrepaid -}} yes {{- else -}} no {{- end }}
+ {{ if $r.Error }} +
Error
{{ $r.Error }}
+ {{ end }} +
Sender
{{template "agentid" (args $chainid $req.SenderAccount)}}
+
Contract Hname
{{$req.Target.Contract}}
+
Entry point
{{$req.Target.EntryPoint}}
+ {{ if not $req.IsOffLedger }} +
Transaction timestamp
{{ formatTimestamp $req.Timestamp }}
+ {{ end }} +
+
Arguments
+ {{if gt (len $req.Args) 0}} +
+ {{range $k, $v := $req.Args}} +
{{ $k | keyToString | trim 30 }}
+
{{ $v | bytesToString | trim 100 }}
+ {{end}} +
+ {{else}} +

(empty)

+ {{end}} +
{{end}} - -
IndexIDOff-ledger?Error
{{$i}}{{$r.Request.ID.Base58}}{{ if $r.Request.IsOffLedger -}} yes {{- else -}} no {{- end }}{{ $r.Error }}
diff --git a/packages/dashboard/templates/metrics.tmpl b/packages/dashboard/templates/metrics.tmpl new file mode 100644 index 0000000000..ccf0dca056 --- /dev/null +++ b/packages/dashboard/templates/metrics.tmpl @@ -0,0 +1,11 @@ +{{define "title"}}Metrics{{end}} + +{{define "body"}} +
+

Metrics

+ + +
+{{end}} diff --git a/packages/dashboard/templates/metrics_nodeconn.tmpl b/packages/dashboard/templates/metrics_nodeconn.tmpl new file mode 100644 index 0000000000..6c74a95966 --- /dev/null +++ b/packages/dashboard/templates/metrics_nodeconn.tmpl @@ -0,0 +1,24 @@ +{{define "title"}}Connection to L1 metrics{{end}} + +{{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 }}
  • + {{end}} +
+ +

Total L1 messages

+ {{template "metricsNodeconnMessages" (args .Metrics.NodeConnectionMessagesMetrics)}} +
+{{end}} diff --git a/packages/dashboard/templates/metrics_nodeconn_messages.tmpl b/packages/dashboard/templates/metrics_nodeconn_messages.tmpl new file mode 100644 index 0000000000..b3115cdae5 --- /dev/null +++ b/packages/dashboard/templates/metrics_nodeconn_messages.tmpl @@ -0,0 +1,81 @@ +{{define "metricsNodeconnMessages"}} + {{ $metrics := (index . 0) }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Message nameTotalLast timeLast message
Pull stateOUT{{ (($metrics.GetOutPullState).GetMessageTotal) }}{{ (formatTimestampOrNever (($metrics.GetOutPullState).GetLastEvent)) }}{{ (($metrics.GetOutPullState).GetLastMessage) }}
Pull tx inclusion stateOUT{{ (($metrics.GetOutPullTransactionInclusionState).GetMessageTotal) }}{{ (formatTimestampOrNever (($metrics.GetOutPullTransactionInclusionState).GetLastEvent)) }}{{ (($metrics.GetOutPullTransactionInclusionState).GetLastMessage) }}
Pull confirmed outputOUT{{ (($metrics.GetOutPullConfirmedOutput).GetMessageTotal) }}{{ (formatTimestampOrNever (($metrics.GetOutPullConfirmedOutput).GetLastEvent)) }}{{ (($metrics.GetOutPullConfirmedOutput).GetLastMessage) }}
Post transactionOUT{{ (($metrics.GetOutPostTransaction).GetMessageTotal) }}{{ (formatTimestampOrNever (($metrics.GetOutPostTransaction).GetLastEvent)) }}{{ (($metrics.GetOutPostTransaction).GetLastMessage) }}
TransactionIN{{ (($metrics.GetInTransaction).GetMessageTotal) }}{{ (formatTimestampOrNever (($metrics.GetInTransaction).GetLastEvent)) }}{{ (($metrics.GetInTransaction).GetLastMessage) }}
Inclusion stateIN{{ (($metrics.GetInInclusionState).GetMessageTotal) }}{{ (formatTimestampOrNever (($metrics.GetInInclusionState).GetLastEvent)) }}{{ (($metrics.GetInInclusionState).GetLastMessage) }}
OutputIN{{ (($metrics.GetInOutput).GetMessageTotal) }}{{ (formatTimestampOrNever (($metrics.GetInOutput).GetLastEvent)) }}{{ (($metrics.GetInOutput).GetLastMessage) }}
Unspent alias outputIN{{ (($metrics.GetInUnspentAliasOutput).GetMessageTotal) }}{{ (formatTimestampOrNever (($metrics.GetInUnspentAliasOutput).GetLastEvent)) }}{{ (($metrics.GetInUnspentAliasOutput).GetLastMessage) }}
+{{end}} + +{{define "title"}}Kažkas{{end}} + +{{define "body"}} +
+

Messages

+ {{template "metricsNodeconnMessages" (args .Metrics)}} +
+{{end}} diff --git a/packages/dashboard/util.go b/packages/dashboard/util.go index 5a9eb86900..a646869c80 100644 --- a/packages/dashboard/util.go +++ b/packages/dashboard/util.go @@ -7,6 +7,7 @@ import ( "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/iscp/colored" + "github.com/iotaledger/wasp/packages/kv" ) func args(args ...interface{}) []interface{} { @@ -39,6 +40,10 @@ func decUint32(n uint32) uint32 { return n - 1 } +func keyToString(k kv.Key) string { + return string(k) +} + func bytesToString(b []byte) string { return string(b) } @@ -51,6 +56,14 @@ func formatTimestamp(ts interface{}) string { return t.UTC().Format(time.RFC3339) } +func formatTimestampOrNever(t time.Time) string { + bla := time.Time{} + if t == bla { + return "NEVER" + } + return formatTimestamp(t) +} + func exploreAddressURL(baseURL string) func(address ledgerstate.Address) string { return func(address ledgerstate.Address) string { return baseURL + "/" + address.Base58() diff --git a/packages/dkg/messages.go b/packages/dkg/messages.go index 3499059d09..a5372b1c46 100644 --- a/packages/dkg/messages.go +++ b/packages/dkg/messages.go @@ -11,6 +11,7 @@ package dkg import ( "bytes" "errors" + "fmt" "io" "time" @@ -57,6 +58,8 @@ const ( rabinEcho byte = peering.FirstUserMsgCode + 44 ) +var initPeeringID peering.PeeringID + // Checks if that's a Initiator -> PeerNode message. func isDkgInitNodeMsg(msgType byte) bool { //nolint:unused,deadcode return msgType == initiatorInitMsgType @@ -111,12 +114,11 @@ type msgByteCoder interface { Read(io.Reader) error } -func makePeerMessage(peeringID peering.PeeringID, step byte, msg msgByteCoder) *peering.PeerMessage { +func makePeerMessage(peeringID peering.PeeringID, receiver, step byte, msg msgByteCoder) *peering.PeerMessageData { msg.SetStep(step) - return &peering.PeerMessage{ + return &peering.PeerMessageData{ PeeringID: peeringID, - SenderIndex: 0, // This is resolved on the receiving side. - Timestamp: 0, // We do not use it in the DKG. + MsgReceiver: receiver, MsgType: msg.MsgType(), MsgData: util.MustBytes(msg), } @@ -134,7 +136,7 @@ type initiatorMsg interface { IsResponse() bool } -func readInitiatorMsg(peerMessage *peering.PeerMessage, blsSuite kyber.Group) (bool, initiatorMsg, error) { +func readInitiatorMsg(peerMessage *peering.PeerMessageData, blsSuite kyber.Group) (bool, initiatorMsg, error) { switch peerMessage.MsgType { case initiatorInitMsgType: msg := initiatorInitMsg{} @@ -180,6 +182,7 @@ func readInitiatorMsg(peerMessage *peering.PeerMessage, blsSuite kyber.Group) (b 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 @@ -188,6 +191,11 @@ type initiatorInitMsg struct { roundRetry time.Duration } +type initiatorInitMsgIn struct { + initiatorInitMsg + SenderNetID string +} + func (m *initiatorInitMsg) MsgType() byte { return initiatorInitMsgType } @@ -209,6 +217,9 @@ func (m *initiatorInitMsg) Write(w io.Writer) error { if err = util.WriteString16(w, m.dkgRef); err != nil { return err } + if _, err = w.Write(m.peeringID[:]); err != nil { + return err + } if err = util.WriteStrings16(w, m.peerNetIDs); err != nil { return err } @@ -235,12 +246,20 @@ func (m *initiatorInitMsg) Write(w io.Writer) error { //nolint:gocritic func (m *initiatorInitMsg) Read(r io.Reader) error { var err error + var n int if m.step, err = util.ReadByte(r); err != nil { return err } if m.dkgRef, err = util.ReadString16(r); err != nil { return err } + if n, err = r.Read(m.peeringID[:]); err != nil { + return err + } + if n != ledgerstate.AddressLength { + 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 } diff --git a/packages/dkg/node.go b/packages/dkg/node.go index 73e6746623..75fd0dfbed 100644 --- a/packages/dkg/node.go +++ b/packages/dkg/node.go @@ -27,19 +27,18 @@ type NodeProvider func() *Node // It receives commands from the initiator as a dkg.NodeProvider, // and communicates with other DKG nodes via the peering network. type Node struct { - identity *ed25519.KeyPair // Keys of the current node. - secKey kyber.Scalar // Derived from the identity. - pubKey kyber.Point // Derived from the identity. - blsSuite Suite // Cryptography to use for the Pairing based operations. - edSuite rabin_dkg.Suite // Cryptography to use for the Ed25519 based operations. - netProvider peering.NetworkProvider // Network to communicate through. - registry registry.DKShareRegistryProvider // Where to store the generated keys. - processes map[string]*proc // Only for introspection. - procLock *sync.RWMutex // To guard access to the process pool. - recvQueue chan *peering.RecvEvent // Incoming events processed async. - recvStopCh chan bool // To coordinate shutdown. - attachID interface{} // Peering attach ID - log *logger.Logger + identity *ed25519.KeyPair // Keys of the current node. + secKey kyber.Scalar // Derived from the identity. + pubKey kyber.Point // Derived from the identity. + blsSuite Suite // Cryptography to use for the Pairing based operations. + edSuite rabin_dkg.Suite // Cryptography to use for the Ed25519 based operations. + netProvider peering.NetworkProvider // Network to communicate through. + registry registry.DKShareRegistryProvider // Where to store the generated keys. + processes map[string]*proc // Only for introspection. + procLock *sync.RWMutex // To guard access to the process pool. + initMsgQueue chan *initiatorInitMsgIn // Incoming events processed async. + attachID interface{} // Peering attach ID + log *logger.Logger } // Init creates new node, that can participate in the DKG procedure. @@ -55,29 +54,44 @@ func NewNode( return nil, err } n := Node{ - identity: identity, - secKey: kyberEdDSSA.Secret, - pubKey: kyberEdDSSA.Public, - blsSuite: tcrypto.DefaultSuite(), - edSuite: edwards25519.NewBlakeSHA256Ed25519(), - netProvider: netProvider, - registry: reg, - processes: make(map[string]*proc), - procLock: &sync.RWMutex{}, - recvQueue: make(chan *peering.RecvEvent), - recvStopCh: make(chan bool), - log: log, + identity: identity, + secKey: kyberEdDSSA.Secret, + pubKey: kyberEdDSSA.Public, + blsSuite: tcrypto.DefaultSuite(), + edSuite: edwards25519.NewBlakeSHA256Ed25519(), + netProvider: netProvider, + registry: reg, + processes: make(map[string]*proc), + procLock: &sync.RWMutex{}, + initMsgQueue: make(chan *initiatorInitMsgIn), + log: log, } - n.attachID = netProvider.Attach(nil, func(recv *peering.RecvEvent) { - n.recvQueue <- recv - }) + n.attachID = netProvider.Attach(&initPeeringID, peering.PeerMessageReceiverDkgInit, n.receiveInitMessage) go n.recvLoop() return &n, nil } +func (n *Node) receiveInitMessage(peerMsg *peering.PeerMessageIn) { + if peerMsg.MsgReceiver != peering.PeerMessageReceiverDkgInit { + panic(fmt.Errorf("DKG init handler does not accept peer messages of other receiver type %v, message type=%v", + peerMsg.MsgReceiver, peerMsg.MsgType)) + } + if peerMsg.MsgType != initiatorInitMsgType { + panic(fmt.Errorf("Wrong type of DKG init message: %v", peerMsg.MsgType)) + } + msg := &initiatorInitMsg{} + if err := msg.fromBytes(peerMsg.MsgData); err != nil { + n.log.Warnf("Dropping unknown message: %v", peerMsg) + return + } + n.initMsgQueue <- &initiatorInitMsgIn{ + initiatorInitMsg: *msg, + SenderNetID: peerMsg.SenderNetID, + } +} + func (n *Node) Close() { - close(n.recvStopCh) - close(n.recvQueue) + close(n.initMsgQueue) n.netProvider.Detach(n.attachID) } @@ -107,14 +121,14 @@ func (n *Node) GenerateDistributedKey( } // // Setup network connections. + dkgID := peering.RandomPeeringID() var netGroup peering.GroupProvider - if netGroup, err = n.netProvider.PeerGroup(peerNetIDs); err != nil { + if netGroup, err = n.netProvider.PeerGroup(dkgID, peerNetIDs); err != nil { return nil, err } defer netGroup.Close() - dkgID := peering.RandomPeeringID() - recvCh := make(chan *peering.RecvEvent, peerCount*2) - attachID := n.netProvider.Attach(&dkgID, func(recv *peering.RecvEvent) { + recvCh := make(chan *peering.PeerMessageIn, peerCount*2) + attachID := n.netProvider.Attach(&dkgID, peering.PeerMessageReceiverDkg, func(recv *peering.PeerMessageIn) { recvCh <- recv }) defer n.netProvider.Detach(attachID) @@ -139,8 +153,9 @@ func (n *Node) GenerateDistributedKey( if err = n.exchangeInitiatorAcks(netGroup, netGroup.AllNodes(), recvCh, rTimeout, gTimeout, rabinStep0Initialize, func(peerIdx uint16, peer peering.PeerSender) { n.log.Debugf("Initiator sends step=%v command to %v", rabinStep0Initialize, peer.NetID()) - peer.SendMsg(makePeerMessage(dkgID, rabinStep0Initialize, &initiatorInitMsg{ + 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, @@ -179,12 +194,12 @@ func (n *Node) GenerateDistributedKey( if err = n.exchangeInitiatorMsgs(netGroup, netGroup.AllNodes(), recvCh, rTimeout, gTimeout, rabinStep6R6SendReconstructCommits, func(peerIdx uint16, peer peering.PeerSender) { n.log.Debugf("Initiator sends step=%v command to %v", rabinStep6R6SendReconstructCommits, peer.NetID()) - peer.SendMsg(makePeerMessage(dkgID, rabinStep6R6SendReconstructCommits, &initiatorStepMsg{})) + peer.SendMsg(makePeerMessage(dkgID, peering.PeerMessageReceiverDkg, rabinStep6R6SendReconstructCommits, &initiatorStepMsg{})) }, - func(recv *peering.RecvEvent, initMsg initiatorMsg) (bool, error) { + func(recv *peering.PeerMessageGroupIn, initMsg initiatorMsg) (bool, error) { switch msg := initMsg.(type) { case *initiatorPubShareMsg: - pubShareResponses[int(recv.Msg.SenderIndex)] = msg + pubShareResponses[int(recv.SenderIndex)] = msg return true, nil default: n.log.Errorf("unexpected message type instead of initiatorPubShareMsg: %V", msg) @@ -227,7 +242,7 @@ func (n *Node) GenerateDistributedKey( if err = n.exchangeInitiatorAcks(netGroup, netGroup.AllNodes(), recvCh, rTimeout, gTimeout, rabinStep7CommitAndTerminate, func(peerIdx uint16, peer peering.PeerSender) { n.log.Debugf("Initiator sends step=%v command to %v", rabinStep7CommitAndTerminate, peer.NetID()) - peer.SendMsg(makePeerMessage(dkgID, rabinStep7CommitAndTerminate, &initiatorDoneMsg{ + peer.SendMsg(makePeerMessage(dkgID, peering.PeerMessageReceiverDkg, rabinStep7CommitAndTerminate, &initiatorDoneMsg{ pubShares: publicShares, })) }, @@ -249,35 +264,21 @@ func (n *Node) GenerateDistributedKey( // Async recv is needed to avoid locking on the even publisher (Recv vs Attach in proc). func (n *Node) recvLoop() { - for { - select { - case <-n.recvStopCh: - return - case recv, ok := <-n.recvQueue: - if ok { - n.onInitMsg(recv) - } - } + for recv := range n.initMsgQueue { + n.onInitMsg(recv) } } // onInitMsg is a callback to handle the DKG initialization messages. -func (n *Node) onInitMsg(recv *peering.RecvEvent) { - if recv.Msg.MsgType != initiatorInitMsgType { - return - } +func (n *Node) onInitMsg(msg *initiatorInitMsgIn) { var err error var p *proc - req := initiatorInitMsg{} - if err = req.fromBytes(recv.Msg.MsgData); err != nil { - n.log.Warnf("Dropping unknown message: %v", recv) - } n.procLock.RLock() - if _, ok := n.processes[req.dkgRef]; ok { + if _, ok := n.processes[msg.dkgRef]; ok { // To have idempotence for retries, we need to consider duplicate // messages as success, if process is already created. n.procLock.RUnlock() - recv.From.SendMsg(makePeerMessage(recv.Msg.PeeringID, req.step, &initiatorStatusMsg{ + n.netProvider.SendMsgByNetID(msg.SenderNetID, makePeerMessage(msg.peeringID, peering.PeerMessageReceiverDkg, msg.step, &initiatorStatusMsg{ error: nil, })) return @@ -287,11 +288,11 @@ func (n *Node) onInitMsg(recv *peering.RecvEvent) { // This part should be executed async, because it accesses the network again, and can // be locked because of the naive implementation of `events.Event`. It locks on all the callbacks. n.procLock.Lock() - if p, err = onInitiatorInit(recv.Msg.PeeringID, &req, n); err == nil { + if p, err = onInitiatorInit(msg.peeringID, &msg.initiatorInitMsg, n); err == nil { n.processes[p.dkgRef] = p } n.procLock.Unlock() - recv.From.SendMsg(makePeerMessage(recv.Msg.PeeringID, req.step, &initiatorStatusMsg{ + n.netProvider.SendMsgByNetID(msg.SenderNetID, makePeerMessage(msg.peeringID, peering.PeerMessageReceiverDkg, msg.step, &initiatorStatusMsg{ error: err, })) }() @@ -311,7 +312,7 @@ func (n *Node) dropProcess(p *proc) bool { func (n *Node) exchangeInitiatorStep( netGroup peering.GroupProvider, peers map[uint16]peering.PeerSender, - recvCh chan *peering.RecvEvent, + recvCh chan *peering.PeerMessageIn, retryTimeout time.Duration, giveUpTimeout time.Duration, dkgID peering.PeeringID, @@ -319,7 +320,7 @@ func (n *Node) exchangeInitiatorStep( ) error { sendCB := func(peerIdx uint16, peer peering.PeerSender) { n.log.Debugf("Initiator sends step=%v command to %v", step, peer.NetID()) - peer.SendMsg(makePeerMessage(dkgID, step, &initiatorStepMsg{})) + peer.SendMsg(makePeerMessage(dkgID, peering.PeerMessageReceiverDkg, step, &initiatorStepMsg{})) } return n.exchangeInitiatorAcks(netGroup, peers, recvCh, retryTimeout, giveUpTimeout, step, sendCB) } @@ -327,14 +328,14 @@ func (n *Node) exchangeInitiatorStep( func (n *Node) exchangeInitiatorAcks( netGroup peering.GroupProvider, peers map[uint16]peering.PeerSender, - recvCh chan *peering.RecvEvent, + recvCh chan *peering.PeerMessageIn, retryTimeout time.Duration, giveUpTimeout time.Duration, step byte, sendCB func(peerIdx uint16, peer peering.PeerSender), ) error { - recvCB := func(recv *peering.RecvEvent, msg initiatorMsg) (bool, error) { - n.log.Debugf("Initiator recv. step=%v response %v from %v", step, msg, recv.From.NetID()) + recvCB := func(recv *peering.PeerMessageGroupIn, msg initiatorMsg) (bool, error) { + n.log.Debugf("Initiator recv. step=%v response %v from %v", step, msg, recv.SenderNetID) return true, nil } return n.exchangeInitiatorMsgs(netGroup, peers, recvCh, retryTimeout, giveUpTimeout, step, sendCB, recvCB) @@ -343,23 +344,23 @@ func (n *Node) exchangeInitiatorAcks( func (n *Node) exchangeInitiatorMsgs( netGroup peering.GroupProvider, peers map[uint16]peering.PeerSender, - recvCh chan *peering.RecvEvent, + recvCh chan *peering.PeerMessageIn, retryTimeout time.Duration, giveUpTimeout time.Duration, step byte, sendCB func(peerIdx uint16, peer peering.PeerSender), - recvCB func(recv *peering.RecvEvent, initMsg initiatorMsg) (bool, error), + recvCB func(recv *peering.PeerMessageGroupIn, initMsg initiatorMsg) (bool, error), ) error { - recvInitCB := func(recv *peering.RecvEvent) (bool, error) { + recvInitCB := func(recv *peering.PeerMessageGroupIn) (bool, error) { var err error var initMsg initiatorMsg var isInitMsg bool - isInitMsg, initMsg, err = readInitiatorMsg(recv.Msg, n.blsSuite) + isInitMsg, initMsg, err = readInitiatorMsg(&recv.PeerMessageData, n.blsSuite) if !isInitMsg { return false, nil } if err != nil { - n.log.Warnf("Failed to read message from %v: %v", recv.From.NetID(), recv.Msg) + n.log.Warnf("Failed to read message from %v: %v", recv.SenderNetID, recv.PeerMessageData) return false, err } if !initMsg.IsResponse() { diff --git a/packages/dkg/proc.go b/packages/dkg/proc.go index 3f969c0319..cfd19fb98d 100644 --- a/packages/dkg/proc.go +++ b/packages/dkg/proc.go @@ -46,15 +46,15 @@ type proc struct { nodeIndex uint16 // Index of this node. 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. - dkgImpl *rabin_dkg.DistKeyGenerator // The cryptographic implementation to use. - dkgLock *sync.RWMutex // Guard access to dkgImpl - attachID interface{} // We keep it here to be able to detach from the network. - peerMsgCh chan *peering.RecvEvent // A buffer for the received peer messages. - log *logger.Logger // A logger to use. - myNetID string // Just to make logging easier. - steps map[byte]*procStep // All the steps for the procedure. + roundRetry time.Duration // Retry period for the Peer <-> Peer communication. + netGroup peering.GroupProvider // A group for which the distributed key is generated. + dkgImpl *rabin_dkg.DistKeyGenerator // The cryptographic implementation to use. + dkgLock *sync.RWMutex // Guard access to dkgImpl + 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. + steps map[byte]*procStep // All the steps for the procedure. } func onInitiatorInit(dkgID peering.PeeringID, msg *initiatorInitMsg, node *Node) (*proc, error) { @@ -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(msg.peerNetIDs); err != nil { + if netGroup, err = node.netProvider.PeerGroup(dkgID, msg.peerNetIDs); err != nil { return nil, err } var dkgImpl *rabin_dkg.DistKeyGenerator @@ -90,12 +90,12 @@ func onInitiatorInit(dkgID peering.PeeringID, msg *initiatorInitMsg, node *Node) netGroup: netGroup, dkgImpl: dkgImpl, dkgLock: &sync.RWMutex{}, - peerMsgCh: make(chan *peering.RecvEvent, len(msg.peerPubs)), + peerMsgCh: make(chan *peering.PeerMessageGroupIn, len(msg.peerPubs)), log: log, myNetID: node.netProvider.Self().NetID(), } p.log.Infof("Starting DKG Peer process at %v for DkgID=%v", p.myNetID, p.dkgID.String()) - stepsStart := make(chan map[uint16]*peering.PeerMessage) + stepsStart := make(chan map[uint16]*peering.PeerMessageData) p.steps = make(map[byte]*procStep) if p.dkgImpl == nil { p.steps[rabinStep6R6SendReconstructCommits] = newProcStep(rabinStep6R6SendReconstructCommits, &p, @@ -146,26 +146,26 @@ func onInitiatorInit(dkgID peering.PeeringID, msg *initiatorInitMsg, node *Node) ) } go p.processLoop(msg.timeout, p.steps[rabinStep7CommitAndTerminate].doneCh) - p.attachID = p.netGroup.Attach(&dkgID, p.onPeerMessage) - stepsStart <- make(map[uint16]*peering.PeerMessage) + p.attachID = p.netGroup.Attach(peering.PeerMessageReceiverDkg, p.onPeerMessage) + stepsStart <- make(map[uint16]*peering.PeerMessageData) return &p, nil } // Handles a message from a peer and pass it to the main thread. -func (p *proc) onPeerMessage(recv *peering.RecvEvent) { - p.peerMsgCh <- recv +func (p *proc) onPeerMessage(peerMsg *peering.PeerMessageGroupIn) { + p.peerMsgCh <- peerMsg } // That's the main thread executing all the procedure steps. // We use a single process to make all the actions sequential. -func (p *proc) processLoop(timeout time.Duration, doneCh chan map[uint16]*peering.PeerMessage) { +func (p *proc) processLoop(timeout time.Duration, doneCh chan map[uint16]*peering.PeerMessageData) { done := false timeoutCh := time.After(timeout) for { select { case recv := <-p.peerMsgCh: - if isDkgInitProcRecvMsg(recv.Msg.MsgType) || isDkgRabinRoundMsg(recv.Msg.MsgType) || isDkgRabinEchoMsg(recv.Msg.MsgType) { - step := readDkgMessageStep(recv.Msg.MsgData) + if isDkgInitProcRecvMsg(recv.MsgType) || isDkgRabinRoundMsg(recv.MsgType) || isDkgRabinEchoMsg(recv.MsgType) { + step := readDkgMessageStep(recv.MsgData) if s := p.steps[step]; s != nil { s.recv(recv) } else { @@ -197,7 +197,7 @@ func (p *proc) processLoop(timeout time.Duration, doneCh chan map[uint16]*peerin // // rabinStep1R21SendDeals // -func (p *proc) rabinStep1R21SendDealsMakeSent(step byte, initRecv *peering.RecvEvent, prevMsgs map[uint16]*peering.PeerMessage) (map[uint16]*peering.PeerMessage, error) { +func (p *proc) rabinStep1R21SendDealsMakeSent(step byte, initRecv *peering.PeerMessageGroupIn, prevMsgs map[uint16]*peering.PeerMessageData) (map[uint16]*peering.PeerMessageData, error) { var err error if p.dkgImpl == nil { return nil, errors.New("unexpected step for n=1") @@ -210,23 +210,23 @@ func (p *proc) rabinStep1R21SendDealsMakeSent(step byte, initRecv *peering.RecvE return nil, err } p.dkgLock.Unlock() - sentMsgs := make(map[uint16]*peering.PeerMessage) + sentMsgs := make(map[uint16]*peering.PeerMessageData) for i := range deals { - sentMsgs[uint16(i)] = makePeerMessage(p.dkgID, step, &rabinDealMsg{ + sentMsgs[uint16(i)] = makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &rabinDealMsg{ deal: deals[i], }) } return sentMsgs, nil } -func (p *proc) rabinStep1R21SendDealsMakeResp(step byte, initRecv *peering.RecvEvent, recvMsgs map[uint16]*peering.PeerMessage) (*peering.PeerMessage, error) { - return makePeerMessage(p.dkgID, step, &initiatorStatusMsg{error: nil}), nil +func (p *proc) rabinStep1R21SendDealsMakeResp(step byte, initRecv *peering.PeerMessageGroupIn, recvMsgs map[uint16]*peering.PeerMessageData) (*peering.PeerMessageData, error) { + return makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &initiatorStatusMsg{error: nil}), nil } // // rabinStep2R22SendResponses // -func (p *proc) rabinStep2R22SendResponsesMakeSent(step byte, initRecv *peering.RecvEvent, prevMsgs map[uint16]*peering.PeerMessage) (map[uint16]*peering.PeerMessage, error) { +func (p *proc) rabinStep2R22SendResponsesMakeSent(step byte, initRecv *peering.PeerMessageGroupIn, prevMsgs map[uint16]*peering.PeerMessageData) (map[uint16]*peering.PeerMessageData, error) { var err error if p.dkgImpl == nil { return nil, errors.New("unexpected step for n=1") @@ -258,23 +258,23 @@ func (p *proc) rabinStep2R22SendResponsesMakeSent(step byte, initRecv *peering.R } // // Produce the sent messages. - sentMsgs := make(map[uint16]*peering.PeerMessage) + sentMsgs := make(map[uint16]*peering.PeerMessageData) for i := range prevMsgs { // Use peerIdx from the previous round. - sentMsgs[i] = makePeerMessage(p.dkgID, step, &rabinResponseMsg{ + sentMsgs[i] = makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &rabinResponseMsg{ responses: ourResponses, }) } return sentMsgs, nil } -func (p *proc) rabinStep2R22SendResponsesMakeResp(step byte, initRecv *peering.RecvEvent, recvMsgs map[uint16]*peering.PeerMessage) (*peering.PeerMessage, error) { - return makePeerMessage(p.dkgID, step, &initiatorStatusMsg{error: nil}), nil +func (p *proc) rabinStep2R22SendResponsesMakeResp(step byte, initRecv *peering.PeerMessageGroupIn, recvMsgs map[uint16]*peering.PeerMessageData) (*peering.PeerMessageData, error) { + return makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &initiatorStatusMsg{error: nil}), nil } // // rabinStep3R23SendJustifications // -func (p *proc) rabinStep3R23SendJustificationsMakeSent(step byte, initRecv *peering.RecvEvent, prevMsgs map[uint16]*peering.PeerMessage) (map[uint16]*peering.PeerMessage, error) { +func (p *proc) rabinStep3R23SendJustificationsMakeSent(step byte, initRecv *peering.PeerMessageGroupIn, prevMsgs map[uint16]*peering.PeerMessageData) (map[uint16]*peering.PeerMessageData, error) { var err error if p.dkgImpl == nil { return nil, errors.New("unexpected step for n=1") @@ -311,23 +311,23 @@ func (p *proc) rabinStep3R23SendJustificationsMakeSent(step byte, initRecv *peer } // // Produce the sent messages. - sentMsgs := make(map[uint16]*peering.PeerMessage) + sentMsgs := make(map[uint16]*peering.PeerMessageData) for i := range prevMsgs { // Use peerIdx from the previous round. - sentMsgs[i] = makePeerMessage(p.dkgID, step, &rabinJustificationMsg{ + sentMsgs[i] = makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &rabinJustificationMsg{ justifications: ourJustifications, }) } return sentMsgs, nil } -func (p *proc) rabinStep3R23SendJustificationsMakeResp(step byte, initRecv *peering.RecvEvent, recvMsgs map[uint16]*peering.PeerMessage) (*peering.PeerMessage, error) { - return makePeerMessage(p.dkgID, step, &initiatorStatusMsg{error: nil}), nil +func (p *proc) rabinStep3R23SendJustificationsMakeResp(step byte, initRecv *peering.PeerMessageGroupIn, recvMsgs map[uint16]*peering.PeerMessageData) (*peering.PeerMessageData, error) { + return makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &initiatorStatusMsg{error: nil}), nil } // // rabinStep4R4SendSecretCommits // -func (p *proc) rabinStep4R4SendSecretCommitsMakeSent(step byte, initRecv *peering.RecvEvent, prevMsgs map[uint16]*peering.PeerMessage) (map[uint16]*peering.PeerMessage, error) { +func (p *proc) rabinStep4R4SendSecretCommitsMakeSent(step byte, initRecv *peering.PeerMessageGroupIn, prevMsgs map[uint16]*peering.PeerMessageData) (map[uint16]*peering.PeerMessageData, error) { var err error if p.dkgImpl == nil { return nil, errors.New("unexpected step for n=1") @@ -376,14 +376,14 @@ func (p *proc) rabinStep4R4SendSecretCommitsMakeSent(step byte, initRecv *peerin } // // Produce the sent messages. - sentMsgs := make(map[uint16]*peering.PeerMessage) + sentMsgs := make(map[uint16]*peering.PeerMessageData) for i := range prevMsgs { // Use peerIdx from the previous round. if thisInQual && p.nodeInQUAL(i) { - sentMsgs[i] = makePeerMessage(p.dkgID, step, &rabinSecretCommitsMsg{ + sentMsgs[i] = makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &rabinSecretCommitsMsg{ secretCommits: ourSecretCommits, }) } else { - sentMsgs[i] = makePeerMessage(p.dkgID, step, &rabinSecretCommitsMsg{ + sentMsgs[i] = makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &rabinSecretCommitsMsg{ secretCommits: nil, }) } @@ -391,14 +391,14 @@ func (p *proc) rabinStep4R4SendSecretCommitsMakeSent(step byte, initRecv *peerin return sentMsgs, nil } -func (p *proc) rabinStep4R4SendSecretCommitsMakeResp(step byte, initRecv *peering.RecvEvent, recvMsgs map[uint16]*peering.PeerMessage) (*peering.PeerMessage, error) { - return makePeerMessage(p.dkgID, step, &initiatorStatusMsg{error: nil}), nil +func (p *proc) rabinStep4R4SendSecretCommitsMakeResp(step byte, initRecv *peering.PeerMessageGroupIn, recvMsgs map[uint16]*peering.PeerMessageData) (*peering.PeerMessageData, error) { + return makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &initiatorStatusMsg{error: nil}), nil } // // rabinStep5R5SendComplaintCommits // -func (p *proc) rabinStep5R5SendComplaintCommitsMakeSent(step byte, initRecv *peering.RecvEvent, prevMsgs map[uint16]*peering.PeerMessage) (map[uint16]*peering.PeerMessage, error) { +func (p *proc) rabinStep5R5SendComplaintCommitsMakeSent(step byte, initRecv *peering.PeerMessageGroupIn, prevMsgs map[uint16]*peering.PeerMessageData) (map[uint16]*peering.PeerMessageData, error) { var err error if p.dkgImpl == nil { return nil, errors.New("unexpected step for n=1") @@ -435,14 +435,14 @@ func (p *proc) rabinStep5R5SendComplaintCommitsMakeSent(step byte, initRecv *pee } // // Produce the sent messages. - sentMsgs := make(map[uint16]*peering.PeerMessage) + sentMsgs := make(map[uint16]*peering.PeerMessageData) for i := range prevMsgs { // Use peerIdx from the previous round. if p.nodeInQUAL(i) { - sentMsgs[i] = makePeerMessage(p.dkgID, step, &rabinComplaintCommitsMsg{ + sentMsgs[i] = makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &rabinComplaintCommitsMsg{ complaintCommits: ourComplaintCommits, }) } else { - sentMsgs[i] = makePeerMessage(p.dkgID, step, &rabinComplaintCommitsMsg{ + sentMsgs[i] = makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &rabinComplaintCommitsMsg{ complaintCommits: []*rabin_dkg.ComplaintCommits{}, }) } @@ -450,18 +450,18 @@ func (p *proc) rabinStep5R5SendComplaintCommitsMakeSent(step byte, initRecv *pee return sentMsgs, nil } -func (p *proc) rabinStep5R5SendComplaintCommitsMakeResp(step byte, initRecv *peering.RecvEvent, recvMsgs map[uint16]*peering.PeerMessage) (*peering.PeerMessage, error) { - return makePeerMessage(p.dkgID, step, &initiatorStatusMsg{error: nil}), nil +func (p *proc) rabinStep5R5SendComplaintCommitsMakeResp(step byte, initRecv *peering.PeerMessageGroupIn, recvMsgs map[uint16]*peering.PeerMessageData) (*peering.PeerMessageData, error) { + return makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &initiatorStatusMsg{error: nil}), nil } // // rabinStep6R6SendReconstructCommits // -func (p *proc) rabinStep6R6SendReconstructCommitsMakeSent(step byte, initRecv *peering.RecvEvent, prevMsgs map[uint16]*peering.PeerMessage) (map[uint16]*peering.PeerMessage, error) { +func (p *proc) rabinStep6R6SendReconstructCommitsMakeSent(step byte, initRecv *peering.PeerMessageGroupIn, prevMsgs map[uint16]*peering.PeerMessageData) (map[uint16]*peering.PeerMessageData, error) { var err error if p.dkgImpl == nil { // Nothing to exchange in the round, if N=1 - return make(map[uint16]*peering.PeerMessage), nil + return make(map[uint16]*peering.PeerMessageData), nil } // // Decode and process the received secret commits. @@ -494,14 +494,14 @@ func (p *proc) rabinStep6R6SendReconstructCommitsMakeSent(step byte, initRecv *p } // // Produce the sent messages. - sentMsgs := make(map[uint16]*peering.PeerMessage) + sentMsgs := make(map[uint16]*peering.PeerMessageData) for i := range prevMsgs { // Use peerIdx from the previous round. if p.nodeInQUAL(i) { - sentMsgs[i] = makePeerMessage(p.dkgID, step, &rabinReconstructCommitsMsg{ + sentMsgs[i] = makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &rabinReconstructCommitsMsg{ reconstructCommits: ourReconstructCommits, }) } else { - sentMsgs[i] = makePeerMessage(p.dkgID, step, &rabinReconstructCommitsMsg{ + sentMsgs[i] = makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &rabinReconstructCommitsMsg{ reconstructCommits: []*rabin_dkg.ReconstructCommits{}, }) } @@ -509,7 +509,7 @@ func (p *proc) rabinStep6R6SendReconstructCommitsMakeSent(step byte, initRecv *p return sentMsgs, nil } -func (p *proc) rabinStep6R6SendReconstructCommitsMakeResp(step byte, initRecv *peering.RecvEvent, recvMsgs map[uint16]*peering.PeerMessage) (*peering.PeerMessage, error) { +func (p *proc) rabinStep6R6SendReconstructCommitsMakeResp(step byte, initRecv *peering.PeerMessageGroupIn, recvMsgs map[uint16]*peering.PeerMessageData) (*peering.PeerMessageData, error) { var err error if p.dkgImpl == nil { // This is the case for N=1, just use simple BLS key pair. @@ -583,16 +583,16 @@ func (p *proc) rabinStep6R6SendReconstructCommitsMakeResp(step byte, initRecv *p if pubShareMsg, err = p.makeInitiatorPubShareMsg(step); err != nil { return nil, err } - return makePeerMessage(p.dkgID, step, pubShareMsg), nil + return makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, pubShareMsg), nil } // // rabinStep7CommitAndTerminate // -func (p *proc) rabinStep7CommitAndTerminateMakeSent(step byte, initRecv *peering.RecvEvent, prevMsgs map[uint16]*peering.PeerMessage) (map[uint16]*peering.PeerMessage, error) { +func (p *proc) rabinStep7CommitAndTerminateMakeSent(step byte, initRecv *peering.PeerMessageGroupIn, prevMsgs map[uint16]*peering.PeerMessageData) (map[uint16]*peering.PeerMessageData, error) { var err error doneMsg := initiatorDoneMsg{} - if err = doneMsg.fromBytes(initRecv.Msg.MsgData, p.node.blsSuite); err != nil { + if err = doneMsg.fromBytes(initRecv.MsgData, p.node.blsSuite); err != nil { p.log.Warnf("Dropping message, failed to decode: %v", initRecv) return nil, err } @@ -603,11 +603,11 @@ func (p *proc) rabinStep7CommitAndTerminateMakeSent(step byte, initRecv *peering if err := p.node.registry.SaveDKShare(p.dkShare); err != nil { return nil, err } - return make(map[uint16]*peering.PeerMessage), nil + return make(map[uint16]*peering.PeerMessageData), nil } -func (p *proc) rabinStep7CommitAndTerminateMakeResp(step byte, initRecv *peering.RecvEvent, recvMsgs map[uint16]*peering.PeerMessage) (*peering.PeerMessage, error) { - return makePeerMessage(p.dkgID, step, &initiatorStatusMsg{error: nil}), nil +func (p *proc) rabinStep7CommitAndTerminateMakeResp(step byte, initRecv *peering.PeerMessageGroupIn, recvMsgs map[uint16]*peering.PeerMessageData) (*peering.PeerMessageData, error) { + return makePeerMessage(p.dkgID, peering.PeerMessageReceiverDkg, step, &initiatorStatusMsg{error: nil}), nil } func (p *proc) nodeInQUAL(nodeIdx uint16) bool { @@ -646,18 +646,18 @@ func (p *proc) makeInitiatorPubShareMsg(step byte) (*initiatorPubShareMsg, error type procStep struct { step byte - startCh <-chan map[uint16]*peering.PeerMessage // Gives a signal to start the current step. - prevMsgs map[uint16]*peering.PeerMessage // Messages received from other peers in the previous step. - sentMsgs map[uint16]*peering.PeerMessage // Messages produced by this peer in this step and sent to others. - recvMsgs map[uint16]*peering.PeerMessage // Messages received from other peers in this step. - initRecv *peering.RecvEvent // Initiator that activated this step. - initResp *peering.PeerMessage // Step response to the initiator. - recvCh chan *peering.RecvEvent // Channel to receive messages for this step (from initiator and peers). - doneCh chan map[uint16]*peering.PeerMessage // Indicates, that this step is done. - closeCh chan bool // For terminating this process. - makeSent func(step byte, initRecv *peering.RecvEvent, prevMsgs map[uint16]*peering.PeerMessage) (map[uint16]*peering.PeerMessage, error) + startCh <-chan map[uint16]*peering.PeerMessageData // Gives a signal to start the current step. + prevMsgs map[uint16]*peering.PeerMessageData // Messages received from other peers in the previous step. + sentMsgs map[uint16]*peering.PeerMessageData // Messages produced by this peer in this step and sent to others. + recvMsgs map[uint16]*peering.PeerMessageData // Messages received from other peers in this step. + initRecv *peering.PeerMessageGroupIn // Initiator that activated this step. + initResp *peering.PeerMessageData // Step response to the initiator. + recvCh chan *peering.PeerMessageGroupIn // Channel to receive messages for this step (from initiator and peers). + doneCh chan map[uint16]*peering.PeerMessageData // Indicates, that this step is done. + closeCh chan bool // For terminating this process. + makeSent func(step byte, initRecv *peering.PeerMessageGroupIn, prevMsgs map[uint16]*peering.PeerMessageData) (map[uint16]*peering.PeerMessageData, error) onceSent *sync.Once - makeResp func(step byte, initRecv *peering.RecvEvent, recvMsgs map[uint16]*peering.PeerMessage) (*peering.PeerMessage, error) + makeResp func(step byte, initRecv *peering.PeerMessageGroupIn, recvMsgs map[uint16]*peering.PeerMessageData) (*peering.PeerMessageData, error) onceResp *sync.Once retryCh <-chan time.Time proc *proc @@ -667,19 +667,19 @@ type procStep struct { func newProcStep( step byte, proc *proc, - startCh <-chan map[uint16]*peering.PeerMessage, - makeSent func(step byte, initRecv *peering.RecvEvent, prevMsgs map[uint16]*peering.PeerMessage) (map[uint16]*peering.PeerMessage, error), - makeResp func(step byte, initRecv *peering.RecvEvent, recvMsgs map[uint16]*peering.PeerMessage) (*peering.PeerMessage, error), + startCh <-chan map[uint16]*peering.PeerMessageData, + makeSent func(step byte, initRecv *peering.PeerMessageGroupIn, prevMsgs map[uint16]*peering.PeerMessageData) (map[uint16]*peering.PeerMessageData, error), + makeResp func(step byte, initRecv *peering.PeerMessageGroupIn, recvMsgs map[uint16]*peering.PeerMessageData) (*peering.PeerMessageData, error), ) *procStep { s := procStep{ step: step, startCh: startCh, prevMsgs: nil, sentMsgs: nil, - recvMsgs: make(map[uint16]*peering.PeerMessage), + recvMsgs: make(map[uint16]*peering.PeerMessageData), initResp: nil, - recvCh: make(chan *peering.RecvEvent, 1000), // NOTE: The channel depth is nor necessary, just for performance. - doneCh: make(chan map[uint16]*peering.PeerMessage), + recvCh: make(chan *peering.PeerMessageGroupIn, 1000), // NOTE: The channel depth is not necessary, just for performance. + doneCh: make(chan map[uint16]*peering.PeerMessageData), closeCh: make(chan bool), makeSent: makeSent, onceSent: &sync.Once{}, @@ -697,7 +697,7 @@ func (s *procStep) close() { close(s.closeCh) } -func (s *procStep) recv(msg *peering.RecvEvent) { +func (s *procStep) recv(msg *peering.PeerMessageGroupIn) { s.recvCh <- msg } @@ -724,38 +724,38 @@ func (s *procStep) run() { // The following is for the case, when we already completed our step, but receiving // messages from others. Maybe our messages were lost, so we just resend the same messages. if s.initResp != nil { - if isDkgInitProcRecvMsg(recv.Msg.MsgType) { - s.log.Debugf("[%v -%v-> %v] Resending initiator response.", s.proc.myNetID, s.initResp.MsgType, recv.From.NetID()) - recv.From.SendMsg(s.initResp) + if isDkgInitProcRecvMsg(recv.MsgType) { + s.log.Debugf("[%v -%v-> %v] Resending initiator response.", s.proc.myNetID, s.initResp.MsgType, recv.SenderNetID) + s.proc.netGroup.SendMsgByIndex(recv.SenderIndex, s.initResp.MsgReceiver, s.initResp.MsgType, s.initResp.MsgData) continue } - if isDkgRabinEchoMsg(recv.Msg.MsgType) { + if isDkgRabinEchoMsg(recv.MsgType) { // Do not respond to echo messages, a resend loop will be initiated otherwise. continue } - if isDkgRabinRoundMsg(recv.Msg.MsgType) { + if isDkgRabinRoundMsg(recv.MsgType) { // Resend the peer messages as echo messages, because we don't need the responses anymore. s.sendEcho(recv) continue } - s.log.Warnf("[%v -%v-> %v] Dropping unknown message.", recv.From.NetID(), recv.Msg.MsgType, s.proc.myNetID) + s.log.Warnf("[%v -%v-> %v] Dropping unknown message.", recv.SenderNetID, recv.MsgType, s.proc.myNetID) continue } // // The following processes te messages while this step is active. - if isDkgInitProcRecvMsg(recv.Msg.MsgType) { + if isDkgInitProcRecvMsg(recv.MsgType) { s.onceSent.Do(func() { s.initRecv = recv s.retryCh = time.After(s.proc.roundRetry) // Check the retries. if s.sentMsgs, err = s.makeSent(s.step, s.initRecv, s.prevMsgs); err != nil { s.log.Errorf("Step %v failed to make round messages, reason=%v", s.step, err) - s.sentMsgs = make(map[uint16]*peering.PeerMessage) // No messages will be sent on error. - s.markDone(makePeerMessage(s.proc.dkgID, s.step, &initiatorStatusMsg{error: err})) + s.sentMsgs = make(map[uint16]*peering.PeerMessageData) // No messages will be sent on error. + s.markDone(makePeerMessage(s.proc.dkgID, peering.PeerMessageReceiverDkg, s.step, &initiatorStatusMsg{error: err})) } for i := range s.sentMsgs { - sendPeer := s.proc.netGroup.AllNodes()[i] - s.log.Debugf("[%v -%v-> %v] Sending peer message (first).", s.proc.myNetID, s.sentMsgs[i].MsgType, sendPeer.NetID()) - sendPeer.SendMsg(s.sentMsgs[i]) + netID, _ := s.proc.netGroup.NetIDByIndex(i) + s.log.Debugf("[%v -%v-> %v] Sending peer message (first).", s.proc.myNetID, s.sentMsgs[i].MsgType, netID) + s.proc.netGroup.SendMsgByIndex(i, s.sentMsgs[i].MsgReceiver, s.sentMsgs[i].MsgType, s.sentMsgs[i].MsgData) } if s.haveAll() { s.makeDone() @@ -763,12 +763,12 @@ func (s *procStep) run() { }) continue } - if isDkgRabinRoundMsg(recv.Msg.MsgType) || isDkgRabinEchoMsg(recv.Msg.MsgType) { + if isDkgRabinRoundMsg(recv.MsgType) || isDkgRabinEchoMsg(recv.MsgType) { // in the current step we consider echo messages as ordinary round messages, // because it is possible that we have requested for them. - if s.recvMsgs[recv.Msg.SenderIndex] == nil { - s.recvMsgs[recv.Msg.SenderIndex] = recv.Msg - } else if s.sentMsgs != nil && isDkgRabinRoundMsg(recv.Msg.MsgType) { + if s.recvMsgs[recv.SenderIndex] == nil { + s.recvMsgs[recv.SenderIndex] = &recv.PeerMessageData + } else if s.sentMsgs != nil && isDkgRabinRoundMsg(recv.MsgType) { // If that's a repeated message from the peer, maybe our message has been // lost, so we repeat it as an echo, to avoid resend loops. s.sendEcho(recv) @@ -778,16 +778,16 @@ func (s *procStep) run() { } continue } - s.log.Warnf("[%v -%v-> %v] Dropping unknown message.", recv.From.NetID(), recv.Msg.MsgType, s.proc.myNetID) + s.log.Warnf("[%v -%v-> %v] Dropping unknown message.", recv.SenderNetID, recv.MsgType, s.proc.myNetID) 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 { - sendPeer := s.proc.netGroup.AllNodes()[i] - s.log.Debugf("[%v -%v-> %v] Resending peer message (retry).", s.proc.myNetID, s.sentMsgs[i].MsgType, sendPeer.NetID()) - sendPeer.SendMsg(s.sentMsgs[i]) + netID, _ := s.proc.netGroup.NetIDByIndex(i) + s.log.Debugf("[%v -%v-> %v] Resending peer message (retry).", s.proc.myNetID, s.sentMsgs[i].MsgType, netID) + s.proc.netGroup.SendMsgByIndex(i, s.sentMsgs[i].MsgReceiver, s.sentMsgs[i].MsgType, s.sentMsgs[i].MsgData) } } continue @@ -797,19 +797,19 @@ func (s *procStep) run() { } } -func (s *procStep) sendEcho(recv *peering.RecvEvent) { +func (s *procStep) sendEcho(recv *peering.PeerMessageGroupIn) { var err error - if sentMsg, sentMsgOK := s.sentMsgs[recv.Msg.SenderIndex]; sentMsgOK { + 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.Msg.MsgType, recv.From.NetID(), err) + s.log.Warnf("[%v -%v-> %v] Unable to send echo message, reason=%v", s.proc.myNetID, recv.MsgType, recv.SenderNetID, err) return } - s.log.Debugf("[%v -%v-> %v] Resending peer message (echo).", s.proc.myNetID, echoMsg.MsgType, recv.From.NetID()) - recv.From.SendMsg(&echoMsg) + s.log.Debugf("[%v -%v-> %v] Resending peer message (echo).", s.proc.myNetID, echoMsg.MsgType, recv.SenderNetID) + 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.Msg.MsgType, recv.From.NetID()) + s.log.Warnf("[%v -%v-> %v] Unable to send echo message, is was not produced yet.", s.proc.myNetID, recv.MsgType, recv.SenderNetID) } func (s *procStep) haveAll() bool { @@ -824,21 +824,21 @@ func (s *procStep) haveAll() bool { func (s *procStep) makeDone() { var err error s.onceResp.Do(func() { - var initResp *peering.PeerMessage + var initResp *peering.PeerMessageData if initResp, err = s.makeResp(s.step, s.initRecv, s.recvMsgs); err != nil { s.log.Errorf("Step failed to make round response, reason=%v", err) - s.markDone(makePeerMessage(s.proc.dkgID, s.step, &initiatorStatusMsg{error: err})) + s.markDone(makePeerMessage(s.proc.dkgID, peering.PeerMessageReceiverDkg, s.step, &initiatorStatusMsg{error: err})) } else { s.markDone(initResp) } }) } -func (s *procStep) markDone(initResp *peering.PeerMessage) { +func (s *procStep) markDone(initResp *peering.PeerMessageData) { s.doneCh <- s.recvMsgs // Activate the next step. s.initResp = initResp // Store the response for later resends. if s.initRecv != nil { - s.initRecv.From.SendMsg(initResp) // Send response to the initiator. + 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) } diff --git a/packages/evm/evmtypes/receipt.go b/packages/evm/evmtypes/receipt.go index 5fdd3547bd..b036a4dca5 100644 --- a/packages/evm/evmtypes/receipt.go +++ b/packages/evm/evmtypes/receipt.go @@ -37,6 +37,7 @@ func EncodeReceiptFull(r *types.Receipt) []byte { m.WriteBytes(r.BlockHash.Bytes()) writeBytes(m, r.BlockNumber.Bytes()) m.WriteBytes(r.ContractAddress.Bytes()) + m.WriteUint64(r.GasUsed) return m.Bytes() } @@ -73,7 +74,9 @@ func DecodeReceiptFull(receiptBytes []byte) (*types.Receipt, error) { } r.ContractAddress.SetBytes(b) - r.GasUsed = r.CumulativeGasUsed + if r.GasUsed, err = m.ReadUint64(); err != nil { + return nil, err + } return r, nil } diff --git a/packages/evm/jsonrpc/service.go b/packages/evm/jsonrpc/service.go index 65bf67726c..bae81e3868 100644 --- a/packages/evm/jsonrpc/service.go +++ b/packages/evm/jsonrpc/service.go @@ -274,7 +274,8 @@ func (e *EthService) GetLogs(q *RPCFilterQuery) ([]*types.Log, error) { } // ChainID implements the eth_chainId method according to https://eips.ethereum.org/EIPS/eip-695 -func (e *EthService) ChainId() hexutil.Uint { //nolint:revive // method name has to be ChainId instead of ChainID +// method name has to be ChainId instead of ChainID +func (e *EthService) ChainId() hexutil.Uint { //nolint:revive return hexutil.Uint(e.evmChain.chainID) } diff --git a/packages/iscp/agentid.go b/packages/iscp/agentid.go index 4821af2239..e273ad7341 100644 --- a/packages/iscp/agentid.go +++ b/packages/iscp/agentid.go @@ -71,10 +71,7 @@ func NewAgentIDFromBase58EncodedString(s string) (*AgentID, error) { // NewAgentIDFromString parses the human-readable string representation func NewAgentIDFromString(s string) (*AgentID, error) { - if len(s) < 2 { - return nil, xerrors.New("NewAgentIDFromString: invalid length") - } - if s[:2] != "A/" { + if !strings.HasPrefix(s, "A/") { return nil, xerrors.New("NewAgentIDFromString: wrong prefix") } parts := strings.Split(s[2:], "::") diff --git a/packages/iscp/assert/util.go b/packages/iscp/assert/util.go index 36a0037451..0773788bb3 100644 --- a/packages/iscp/assert/util.go +++ b/packages/iscp/assert/util.go @@ -39,11 +39,18 @@ func (a Assert) RequireNoError(err error, str ...string) { } func (a Assert) RequireChainOwner(ctx iscp.Sandbox, name ...string) { - if !ctx.ChainOwnerID().Equals(ctx.Caller()) { - if len(name) > 0 { - a.log.Panicf(a.prefix+"unauthorized access: %s", name[0]) - } else { - a.log.Panicf(a.prefix + "unauthorized access") + a.RequireCaller(ctx, []*iscp.AgentID{ctx.ChainOwnerID()}, name...) +} + +func (a Assert) RequireCaller(ctx iscp.Sandbox, allowed []*iscp.AgentID, name ...string) { + for _, agentID := range allowed { + if ctx.Caller().Equals(agentID) { + return } } + if len(name) > 0 { + a.log.Panicf(a.prefix+"%s: unauthorized access", name[0]) + } else { + a.log.Panicf(a.prefix + "unauthorized access") + } } diff --git a/packages/iscp/chainid.go b/packages/iscp/chainid.go index 2b823e5c53..72cdc1a2d2 100644 --- a/packages/iscp/chainid.go +++ b/packages/iscp/chainid.go @@ -5,6 +5,7 @@ package iscp import ( "io" + "strings" "github.com/iotaledger/hive.go/marshalutil" @@ -24,7 +25,7 @@ func NewChainID(addr *ledgerstate.AliasAddress) *ChainID { return &ChainID{addr} } -// ChainIDFromAddress creates a chainIDD from alias address. Returns and error if not an alias address type +// ChainIDFromAddress creates a chain ID from alias address. Returns and error if not an alias address type func ChainIDFromAddress(addr ledgerstate.Address) (*ChainID, error) { alias, ok := addr.(*ledgerstate.AliasAddress) if !ok { @@ -59,6 +60,11 @@ func ChainIDFromBytes(data []byte) (*ChainID, error) { return &ChainID{alias}, nil } +// ChainIDFromString reconstructs a ChainID from its string representation. +func ChainIDFromString(s string) (*ChainID, error) { + return ChainIDFromBase58(strings.TrimPrefix(s, "$/")) +} + // RandomChainID creates a random chain ID. func RandomChainID(seed ...[]byte) *ChainID { var h hashing.HashValue diff --git a/packages/iscp/request.go b/packages/iscp/request.go index 4c9fea20f6..73faf508a4 100644 --- a/packages/iscp/request.go +++ b/packages/iscp/request.go @@ -2,12 +2,15 @@ package iscp import ( "fmt" + "strconv" + "strings" "time" "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/wasp/packages/kv/dict" "github.com/iotaledger/wasp/packages/util" + "golang.org/x/xerrors" ) // region Request ////////////////////////////////////////////////////// @@ -28,7 +31,7 @@ type Request interface { // address of the sender for all requests, SenderAddress() ledgerstate.Address // returns contract/entry point pair - Target() (Hname, Hname) + Target() RequestTarget // Timestamp returns a request TX timestamp, if such TX exist, otherwise zero is returned. Timestamp() time.Time // Bytes returns binary representation of the request @@ -39,6 +42,18 @@ type Request interface { String() string } +type RequestTarget struct { + Contract Hname + EntryPoint Hname +} + +func NewRequestTarget(contract, entryPoint Hname) RequestTarget { + return RequestTarget{ + Contract: contract, + EntryPoint: entryPoint, + } +} + func TakeRequestIDs(reqs ...Request) []RequestID { ret := make([]RequestID, len(reqs)) for i := range reqs { @@ -82,6 +97,28 @@ func RequestIDFromBase58(b58 string) (ret RequestID, err error) { return } +func RequestIDFromString(s string) (ret RequestID, err error) { + if !strings.HasPrefix(s, "[") { + return RequestIDFromBase58(s) + } + parts := strings.Split(s[1:], "]") + if len(parts) != 2 { + err = xerrors.New("RequestIDFromString: wrong format") + return + } + index, err2 := strconv.ParseUint(parts[0], 10, 16) + if err2 != nil { + err = xerrors.Errorf("RequestIDFromString: %v", err2) + return + } + txid, err3 := ledgerstate.TransactionIDFromBase58(parts[1]) + if err3 != nil { + err = xerrors.Errorf("RequestIDFromString: %v", err3) + return + } + return NewRequestID(txid, uint16(index)), nil +} + func (rid RequestID) OutputID() ledgerstate.OutputID { return ledgerstate.OutputID(rid) } diff --git a/packages/iscp/request/request.go b/packages/iscp/request/request.go index 1836e9495f..702bf18265 100644 --- a/packages/iscp/request/request.go +++ b/packages/iscp/request/request.go @@ -289,6 +289,7 @@ func (req *OnLedger) Output() ledgerstate.Output { // Params returns solid args if decoded already or nil otherwise func (req *OnLedger) Params() (dict.Dict, bool) { + // FIXME: this returns nil after deserializing a processed request (see tools/wasp-cli/chain/blocklog.go) par := req.params.Load() if par == nil { return nil, false @@ -305,8 +306,8 @@ func (req *OnLedger) SenderAddress() ledgerstate.Address { } // Target returns target contract and target entry point -func (req *OnLedger) Target() (iscp.Hname, iscp.Hname) { - return req.requestMetadata.TargetContract(), req.requestMetadata.EntryPoint() +func (req *OnLedger) Target() iscp.RequestTarget { + return iscp.NewRequestTarget(req.requestMetadata.TargetContract(), req.requestMetadata.EntryPoint()) } func (req *OnLedger) Timestamp() time.Time { @@ -389,6 +390,7 @@ func (req *OnLedger) String() string { type OffLedger struct { args requestargs.RequestArgs + chainID *iscp.ChainID contract iscp.Hname entryPoint iscp.Hname params atomic.Value // mutable @@ -403,8 +405,9 @@ type OffLedger struct { var _ iscp.Request = &OffLedger{} // NewOffLedger creates a basic request -func NewOffLedger(contract, entryPoint iscp.Hname, args requestargs.RequestArgs) *OffLedger { +func NewOffLedger(chainID *iscp.ChainID, contract, entryPoint iscp.Hname, args requestargs.RequestArgs) *OffLedger { return &OffLedger{ + chainID: chainID, args: args.Clone(), contract: contract, entryPoint: entryPoint, @@ -447,7 +450,8 @@ func (req *OffLedger) readFromMarshalUtil(mu *marshalutil.MarshalUtil) error { } func (req *OffLedger) writeEssenceToMarshalUtil(mu *marshalutil.MarshalUtil) { - mu.Write(req.contract). + mu.Write(req.chainID). + Write(req.contract). Write(req.entryPoint). Write(req.args). WriteBytes(req.publicKey[:]). @@ -456,6 +460,11 @@ func (req *OffLedger) writeEssenceToMarshalUtil(mu *marshalutil.MarshalUtil) { } func (req *OffLedger) readEssenceFromMarshalUtil(mu *marshalutil.MarshalUtil) error { + var err error + if req.chainID, err = iscp.ChainIDFromMarshalUtil(mu); err != nil { + return err + } + if err := req.contract.ReadFromMarshalUtil(mu); err != nil { return err } @@ -521,6 +530,10 @@ func (req *OffLedger) ID() (requestID iscp.RequestID) { return iscp.RequestID(ledgerstate.NewOutputID(txid, 0)) } +func (req *OffLedger) ChainID() (chainID *iscp.ChainID) { + return req.chainID +} + // IsFeePrepaid always true for off-ledger func (req *OffLedger) IsFeePrepaid() bool { return true @@ -541,6 +554,7 @@ func (req *OffLedger) IsOffLedger() bool { } func (req *OffLedger) Params() (dict.Dict, bool) { + // FIXME: this returns nil after deserializing a processed request (see tools/wasp-cli/chain/blocklog.go) par := req.params.Load() if par == nil { return nil, false @@ -559,8 +573,8 @@ func (req *OffLedger) SenderAddress() ledgerstate.Address { return req.sender } -func (req *OffLedger) Target() (iscp.Hname, iscp.Hname) { - return req.contract, req.entryPoint +func (req *OffLedger) Target() iscp.RequestTarget { + return iscp.NewRequestTarget(req.contract, req.entryPoint) } func (req *OffLedger) Timestamp() time.Time { diff --git a/packages/iscp/request/request_test.go b/packages/iscp/request/request_test.go index 50fd190a3b..bc5c47f346 100644 --- a/packages/iscp/request/request_test.go +++ b/packages/iscp/request/request_test.go @@ -90,7 +90,7 @@ func TestOffLedger(t *testing.T) { target := iscp.Hn("target") ep := iscp.Hn("entry point") args := requestargs.New() - req := NewOffLedger(target, ep, args) + req := NewOffLedger(iscp.RandomChainID(), target, ep, args) reqBack, err := FromMarshalUtil(marshalutil.New(req.Bytes())) require.NoError(t, err) _, ok := reqBack.(*OffLedger) diff --git a/packages/iscp/rotate/rotate.go b/packages/iscp/rotate/rotate.go index 3557aec6e5..3a29c2fa24 100644 --- a/packages/iscp/rotate/rotate.go +++ b/packages/iscp/rotate/rotate.go @@ -17,14 +17,14 @@ import ( // IsRotateStateControllerRequest determines if request may be a committee rotation request func IsRotateStateControllerRequest(req iscp.Request) bool { - targetContract, targetEP := req.Target() - return targetContract == coreutil.CoreContractGovernanceHname && targetEP == coreutil.CoreEPRotateStateControllerHname + target := req.Target() + return target.Contract == coreutil.CoreContractGovernanceHname && target.EntryPoint == coreutil.CoreEPRotateStateControllerHname } -func NewRotateRequestOffLedger(newStateAddress ledgerstate.Address, keyPair *ed25519.KeyPair) iscp.Request { +func NewRotateRequestOffLedger(chainID *iscp.ChainID, newStateAddress ledgerstate.Address, keyPair *ed25519.KeyPair) *request.OffLedger { args := requestargs.New(nil) args.AddEncodeSimple(coreutil.ParamStateControllerAddress, codec.EncodeAddress(newStateAddress)) - ret := request.NewOffLedger(coreutil.CoreContractGovernanceHname, coreutil.CoreEPRotateStateControllerHname, args) + ret := request.NewOffLedger(chainID, coreutil.CoreContractGovernanceHname, coreutil.CoreEPRotateStateControllerHname, args) ret.Sign(keyPair) return ret } diff --git a/packages/iscp/rotate/rotate_test.go b/packages/iscp/rotate/rotate_test.go index 91f7720d99..256a328cde 100644 --- a/packages/iscp/rotate/rotate_test.go +++ b/packages/iscp/rotate/rotate_test.go @@ -3,13 +3,13 @@ package rotate import ( "testing" + "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/testutil/testkey" - "github.com/stretchr/testify/require" ) func TestBasicRotateRequest(t *testing.T) { kp, addr := testkey.GenKeyAddr() - req := NewRotateRequestOffLedger(addr, kp) + req := NewRotateRequestOffLedger(iscp.RandomChainID(), addr, kp) require.True(t, IsRotateStateControllerRequest(req)) } diff --git a/packages/kv/codec/bool.go b/packages/kv/codec/bool.go new file mode 100644 index 0000000000..902c2a5bc5 --- /dev/null +++ b/packages/kv/codec/bool.go @@ -0,0 +1,29 @@ +package codec + +import ( + "bytes" + + "github.com/iotaledger/wasp/packages/util" + "golang.org/x/xerrors" +) + +func DecodeBool(b []byte, def ...bool) (bool, error) { + if b == nil { + if len(def) == 0 { + return false, xerrors.Errorf("cannot decode nil bytes") + } + return def[0], nil + } + var ret bool + err := util.ReadBoolByte(bytes.NewReader(b), &ret) + return ret, err +} + +func EncodeBool(value bool) []byte { + buf := bytes.NewBuffer(make([]byte, 0)) + err := util.WriteBoolByte(buf, value) + if err != nil { + return nil + } + return buf.Bytes() +} diff --git a/packages/kv/codec/bool_test.go b/packages/kv/codec/bool_test.go new file mode 100644 index 0000000000..2ebe5282be --- /dev/null +++ b/packages/kv/codec/bool_test.go @@ -0,0 +1,19 @@ +package codec + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func testBoolEncodeDecode(t *testing.T, b bool) { + bin0 := EncodeBool(b) + zback, err := DecodeBool(bin0) + require.NoError(t, err) + require.Equal(t, zback, b) +} + +func TestBoolEncoding(t *testing.T) { + testBoolEncodeDecode(t, true) + testBoolEncodeDecode(t, false) +} diff --git a/packages/kv/codec/encodego.go b/packages/kv/codec/encodego.go index 686ca25c3b..fe36280d9c 100644 --- a/packages/kv/codec/encodego.go +++ b/packages/kv/codec/encodego.go @@ -11,18 +11,22 @@ import ( "github.com/iotaledger/wasp/packages/iscp" ) -func Encode(v interface{}) []byte { +func Encode(v interface{}) []byte { //nolint:funlen switch vt := v.(type) { + case bool: + return EncodeBool(vt) case int: // default to int64 return EncodeInt64(int64(vt)) - case byte: - return EncodeInt64(int64(vt)) + case int8: + return EncodeInt8(vt) case int16: return EncodeInt16(vt) case int32: return EncodeInt32(vt) case int64: return EncodeInt64(vt) + case uint8: + return EncodeUint8(vt) case uint16: return EncodeUint16(vt) case uint32: @@ -59,7 +63,6 @@ func Encode(v interface{}) []byte { return vt.Bytes() case time.Time: return EncodeTime(vt) - default: panic(fmt.Sprintf("Can't encode value %v", v)) } diff --git a/packages/kv/codec/int.go b/packages/kv/codec/int.go index c5c8c38b31..89f1f6dc70 100644 --- a/packages/kv/codec/int.go +++ b/packages/kv/codec/int.go @@ -5,6 +5,35 @@ import ( "golang.org/x/xerrors" ) +func DecodeInt8(b []byte, def ...int8) (int8, error) { + if b == nil { + if len(def) == 0 { + return 0, xerrors.Errorf("cannot decode nil bytes") + } + return def[0], nil + } + r, err := util.Uint8From1Bytes(b) + return int8(r), err +} + +func EncodeInt8(value int8) []byte { + return util.Uint8To1Bytes(uint8(value)) +} + +func DecodeUint8(b []byte, def ...uint8) (uint8, error) { + if b == nil { + if len(def) == 0 { + return 0, xerrors.Errorf("cannot decode nil bytes") + } + return def[0], nil + } + return util.Uint8From1Bytes(b) +} + +func EncodeUint8(value uint8) []byte { + return util.Uint8To1Bytes(value) +} + func DecodeInt16(b []byte, def ...int16) (int16, error) { if b == nil { if len(def) == 0 { diff --git a/packages/kv/collections/map.go b/packages/kv/collections/map.go index 46dbb2d658..6ef6347e99 100644 --- a/packages/kv/collections/map.go +++ b/packages/kv/collections/map.go @@ -167,9 +167,13 @@ func (m *ImmutableMap) Len() (uint32, error) { return util.MustUint32From4Bytes(v), nil } +// Erase the map. +// TODO: Improve by using DelPrefix method in KVStore. func (m *Map) Erase() { - // TODO needs DelPrefix method in KVStore - panic("implement me") + m.MustIterateKeys(func(elemKey []byte) bool { + m.MustDelAt(elemKey) + return true + }) } // Iterate non-deterministic diff --git a/packages/kv/kvdecoder/kvdecoder.go b/packages/kv/kvdecoder/kvdecoder.go index 5fa7f5b300..61018180e0 100644 --- a/packages/kv/kvdecoder/kvdecoder.go +++ b/packages/kv/kvdecoder/kvdecoder.go @@ -110,6 +110,17 @@ func (p *Decoder) MustGetUint64(key kv.Key, def ...uint64) uint64 { return ret } +func (p *Decoder) GetBool(key kv.Key, def ...bool) (bool, error) { + v, err := codec.DecodeBool(p.kv.MustGet(key), def...) + return v, p.wrapError(key, err) +} + +func (p *Decoder) MustGetBool(key kv.Key, def ...bool) bool { + ret, err := p.GetBool(key, def...) + p.check(err) + return ret +} + func (p *Decoder) GetTime(key kv.Key, def ...time.Time) (time.Time, error) { v, err := codec.DecodeTime(p.kv.MustGet(key), def...) return v, p.wrapError(key, err) diff --git a/packages/metrics/chain.go b/packages/metrics/chain.go index 0762d6779d..338d627c14 100644 --- a/packages/metrics/chain.go +++ b/packages/metrics/chain.go @@ -1,21 +1,23 @@ package metrics import ( + "fmt" "time" "github.com/iotaledger/wasp/packages/iscp" "github.com/prometheus/client_golang/prometheus" ) -// type StateManagerMetrics interface { -// } -// +type StateManagerMetrics interface { + RecordBlockSize(blockIndex uint32, size float64) +} type ChainMetrics interface { CountMessages() CountRequestAckMessages() MempoolMetrics ConsensusMetrics + StateManagerMetrics } type MempoolMetrics interface { @@ -23,10 +25,12 @@ type MempoolMetrics interface { CountOnLedgerRequestIn() CountRequestOut() RecordRequestProcessingTime(iscp.RequestID, time.Duration) + CountBlocksPerChain() } type ConsensusMetrics interface { RecordVMRunTime(time.Duration) + CountVMRuns() } type chainMetricsObj struct { @@ -67,6 +71,18 @@ func (c *chainMetricsObj) RecordVMRunTime(elapse time.Duration) { c.metrics.vmRunTime.With(prometheus.Labels{"chain": c.chainID.String()}).Set(elapse.Seconds()) } +func (c *chainMetricsObj) CountVMRuns() { + c.metrics.vmRunCounter.With(prometheus.Labels{"chain": c.chainID.String()}).Inc() +} + +func (c *chainMetricsObj) CountBlocksPerChain() { + c.metrics.blocksPerChain.With(prometheus.Labels{"chain": c.chainID.String()}).Inc() +} + +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) +} + type defaultChainMetrics struct{} func DefaultChainMetrics() ChainMetrics { @@ -86,3 +102,9 @@ func (m *defaultChainMetrics) CountRequestAckMessages() {} func (m *defaultChainMetrics) RecordRequestProcessingTime(_ iscp.RequestID, _ time.Duration) {} func (m *defaultChainMetrics) RecordVMRunTime(_ time.Duration) {} + +func (m *defaultChainMetrics) CountVMRuns() {} + +func (m *defaultChainMetrics) CountBlocksPerChain() {} + +func (m *defaultChainMetrics) RecordBlockSize(_ uint32, _ float64) {} diff --git a/packages/metrics/metrics.go b/packages/metrics/metrics.go index 602a38ee3f..a40f1e6bf6 100644 --- a/packages/metrics/metrics.go +++ b/packages/metrics/metrics.go @@ -8,6 +8,7 @@ import ( "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "github.com/prometheus/client_golang/prometheus" @@ -24,6 +25,10 @@ type Metrics struct { requestAckMessages *prometheus.CounterVec requestProcessingTime *prometheus.GaugeVec vmRunTime *prometheus.GaugeVec + vmRunCounter *prometheus.CounterVec + blocksPerChain *prometheus.CounterVec + blockSizes *prometheus.GaugeVec + nodeconnMetrics nodeconnmetrics.NodeConnectionMetrics } func (m *Metrics) NewChainMetrics(chainID *iscp.ChainID) ChainMetrics { @@ -38,7 +43,10 @@ func (m *Metrics) NewChainMetrics(chainID *iscp.ChainID) ChainMetrics { } func New(log *logger.Logger) *Metrics { - return &Metrics{log: log} + return &Metrics{ + log: log, + nodeconnMetrics: nodeconnmetrics.New(log), + } } var once sync.Once @@ -69,6 +77,7 @@ func (m *Metrics) Stop() error { } func (m *Metrics) registerMetrics() { + m.nodeconnMetrics.RegisterMetrics() m.log.Info("Registering mempool metrics to prometheus") m.offLedgerRequestCounter = prometheus.NewCounterVec(prometheus.CounterOpts{ Name: "wasp_off_ledger_request_counter", @@ -111,4 +120,29 @@ func (m *Metrics) registerMetrics() { Help: "Time it takes to run the vm", }, []string{"chain"}) prometheus.MustRegister(m.vmRunTime) + + m.vmRunCounter = prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "wasp_vm_run_counter", + Help: "Time it takes to run the vm", + }, []string{"chain"}) + prometheus.MustRegister(m.vmRunCounter) + + m.blocksPerChain = prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "wasp_block_counter", + Help: "Number of blocks per chain", + }, []string{"chain"}) + prometheus.MustRegister(m.blocksPerChain) + + m.blockSizes = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Name: "wasp_block_size", + Help: "Block sizes", + }, []string{"block_index", "chain"}) + prometheus.MustRegister(m.blockSizes) +} + +func (m *Metrics) GetNodeConnectionMetrics() nodeconnmetrics.NodeConnectionMetrics { + if m == nil { + return nodeconnmetrics.NewEmptyNodeConnectionMetrics() + } + return m.nodeconnMetrics } diff --git a/packages/metrics/nodeconnmetrics/empty_message.go b/packages/metrics/nodeconnmetrics/empty_message.go new file mode 100644 index 0000000000..617fb1fdcf --- /dev/null +++ b/packages/metrics/nodeconnmetrics/empty_message.go @@ -0,0 +1,18 @@ +package nodeconnmetrics + +import ( + "time" +) + +type emptyNodeConnectionMessageMetrics struct{} + +var _ NodeConnectionMessageMetrics = &emptyNodeConnectionMessageMetrics{} + +func newEmptyNodeConnectionMessageMetrics() NodeConnectionMessageMetrics { + return &emptyNodeConnectionMessageMetrics{} +} + +func (ncmmi *emptyNodeConnectionMessageMetrics) CountLastMessage(msg interface{}) {} +func (ncmmi *emptyNodeConnectionMessageMetrics) GetMessageTotal() uint32 { return 0 } +func (ncmmi *emptyNodeConnectionMessageMetrics) GetLastEvent() time.Time { return time.Time{} } +func (ncmmi *emptyNodeConnectionMessageMetrics) GetLastMessage() interface{} { return nil } diff --git a/packages/metrics/nodeconnmetrics/empty_messages.go b/packages/metrics/nodeconnmetrics/empty_messages.go new file mode 100644 index 0000000000..6a7c66ff4b --- /dev/null +++ b/packages/metrics/nodeconnmetrics/empty_messages.go @@ -0,0 +1,43 @@ +package nodeconnmetrics + +type emptyNodeConnectionMessagesMetrics struct { + empty NodeConnectionMessageMetrics +} + +var _ NodeConnectionMessagesMetrics = &emptyNodeConnectionMessagesMetrics{} + +func NewEmptyNodeConnectionMessagesMetrics() NodeConnectionMessagesMetrics { + return &emptyNodeConnectionMessagesMetrics{empty: newEmptyNodeConnectionMessageMetrics()} +} + +func (ecmm *emptyNodeConnectionMessagesMetrics) GetOutPullState() NodeConnectionMessageMetrics { + return ecmm.empty +} + +func (ecmm *emptyNodeConnectionMessagesMetrics) GetOutPullTransactionInclusionState() NodeConnectionMessageMetrics { + return ecmm.empty +} + +func (ecmm *emptyNodeConnectionMessagesMetrics) GetOutPullConfirmedOutput() NodeConnectionMessageMetrics { + return ecmm.empty +} + +func (ecmm *emptyNodeConnectionMessagesMetrics) GetOutPostTransaction() NodeConnectionMessageMetrics { + return ecmm.empty +} + +func (ecmm *emptyNodeConnectionMessagesMetrics) GetInTransaction() NodeConnectionMessageMetrics { + return ecmm.empty +} + +func (ecmm *emptyNodeConnectionMessagesMetrics) GetInInclusionState() NodeConnectionMessageMetrics { + return ecmm.empty +} + +func (ecmm *emptyNodeConnectionMessagesMetrics) GetInOutput() NodeConnectionMessageMetrics { + return ecmm.empty +} + +func (ecmm *emptyNodeConnectionMessagesMetrics) GetInUnspentAliasOutput() NodeConnectionMessageMetrics { + return ecmm.empty +} diff --git a/packages/metrics/nodeconnmetrics/empty_metrics.go b/packages/metrics/nodeconnmetrics/empty_metrics.go new file mode 100644 index 0000000000..7743ca02ac --- /dev/null +++ b/packages/metrics/nodeconnmetrics/empty_metrics.go @@ -0,0 +1,28 @@ +package nodeconnmetrics + +import ( + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/wasp/packages/iscp" +) + +type emptyNodeConnectionMetrics struct { + NodeConnectionMessagesMetrics +} + +var _ NodeConnectionMetrics = &emptyNodeConnectionMetrics{} + +func NewEmptyNodeConnectionMetrics() NodeConnectionMetrics { + return &emptyNodeConnectionMetrics{ + NodeConnectionMessagesMetrics: NewEmptyNodeConnectionMessagesMetrics(), + } +} + +func (ncmi *emptyNodeConnectionMetrics) RegisterMetrics() {} +func (ncmi *emptyNodeConnectionMetrics) NewMessagesMetrics(chainID *iscp.ChainID) NodeConnectionMessagesMetrics { + return NewEmptyNodeConnectionMessagesMetrics() +} +func (ncmi *emptyNodeConnectionMetrics) SetSubscribed(address ledgerstate.Address) {} +func (ncmi *emptyNodeConnectionMetrics) SetUnsubscribed(address ledgerstate.Address) {} +func (ncmi *emptyNodeConnectionMetrics) GetSubscribed() []ledgerstate.Address { + return []ledgerstate.Address{} +} diff --git a/packages/metrics/nodeconnmetrics/interface.go b/packages/metrics/nodeconnmetrics/interface.go new file mode 100644 index 0000000000..bf073bcbbe --- /dev/null +++ b/packages/metrics/nodeconnmetrics/interface.go @@ -0,0 +1,39 @@ +package nodeconnmetrics + +import ( + "time" + + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/wasp/packages/iscp" +) + +type NodeConnectionMessageMetrics interface { + CountLastMessage(interface{}) + + GetMessageTotal() uint32 + GetLastEvent() time.Time + GetLastMessage() interface{} +} + +type NodeConnectionMessagesMetrics interface { + GetOutPullState() NodeConnectionMessageMetrics + GetOutPullTransactionInclusionState() NodeConnectionMessageMetrics + GetOutPullConfirmedOutput() NodeConnectionMessageMetrics + GetOutPostTransaction() NodeConnectionMessageMetrics + + GetInTransaction() NodeConnectionMessageMetrics + GetInInclusionState() NodeConnectionMessageMetrics + GetInOutput() NodeConnectionMessageMetrics + GetInUnspentAliasOutput() NodeConnectionMessageMetrics +} + +type NodeConnectionMetrics interface { + NodeConnectionMessagesMetrics + + SetSubscribed(ledgerstate.Address) + SetUnsubscribed(ledgerstate.Address) + GetSubscribed() []ledgerstate.Address + + RegisterMetrics() + NewMessagesMetrics(chainID *iscp.ChainID) NodeConnectionMessagesMetrics +} diff --git a/packages/metrics/nodeconnmetrics/message.go b/packages/metrics/nodeconnmetrics/message.go new file mode 100644 index 0000000000..3090fe2509 --- /dev/null +++ b/packages/metrics/nodeconnmetrics/message.go @@ -0,0 +1,59 @@ +package nodeconnmetrics + +import ( + "time" + + "github.com/iotaledger/wasp/packages/iscp" + "github.com/prometheus/client_golang/prometheus" + "go.uber.org/atomic" +) + +type nodeConnectionMessageMetricsImpl struct { + nodeConnMetrics *nodeConnectionMetricsImpl + metricsLabel prometheus.Labels + total atomic.Uint32 + lastEvent time.Time + lastMessage interface{} +} + +var _ NodeConnectionMessageMetrics = &nodeConnectionMessageMetricsImpl{} + +func newNodeConnectionMessageMetrics(ncmi *nodeConnectionMetricsImpl, chainID *iscp.ChainID, msgType string) NodeConnectionMessageMetrics { + return &nodeConnectionMessageMetricsImpl{ + nodeConnMetrics: ncmi, + metricsLabel: ncmi.getMetricsLabel(chainID, msgType), + } +} + +func (ncmmi *nodeConnectionMessageMetricsImpl) incMessageTotal() { + ncmmi.total.Inc() + ncmmi.nodeConnMetrics.messageTotalCounter.With(ncmmi.metricsLabel).Inc() +} + +func (ncmmi *nodeConnectionMessageMetricsImpl) setLastEventToNow() { + ncmmi.lastEvent = time.Now() + ncmmi.nodeConnMetrics.lastEventTimeGauge.With(ncmmi.metricsLabel).SetToCurrentTime() +} + +// TODO: connect last message to Prometheus +func (ncmmi *nodeConnectionMessageMetricsImpl) setLastMessage(msg interface{}) { + ncmmi.lastMessage = msg +} + +func (ncmmi *nodeConnectionMessageMetricsImpl) CountLastMessage(msg interface{}) { + ncmmi.incMessageTotal() + ncmmi.setLastEventToNow() + ncmmi.setLastMessage(msg) +} + +func (ncmmi *nodeConnectionMessageMetricsImpl) GetMessageTotal() uint32 { + return ncmmi.total.Load() +} + +func (ncmmi *nodeConnectionMessageMetricsImpl) GetLastEvent() time.Time { + return ncmmi.lastEvent +} + +func (ncmmi *nodeConnectionMessageMetricsImpl) GetLastMessage() interface{} { + return ncmmi.lastMessage +} diff --git a/packages/metrics/nodeconnmetrics/messages.go b/packages/metrics/nodeconnmetrics/messages.go new file mode 100644 index 0000000000..b69ae73a4c --- /dev/null +++ b/packages/metrics/nodeconnmetrics/messages.go @@ -0,0 +1,65 @@ +package nodeconnmetrics + +import ( + "github.com/iotaledger/wasp/packages/iscp" +) + +type nodeConnectionMessagesMetricsImpl struct { + outPullStateMetrics NodeConnectionMessageMetrics + outPullTransactionInclusionStateMetrics NodeConnectionMessageMetrics + outPullConfirmedOutputMetrics NodeConnectionMessageMetrics + outPostTransactionMetrics NodeConnectionMessageMetrics + + inTransactionMetrics NodeConnectionMessageMetrics + inInclusionStateMetrics NodeConnectionMessageMetrics + inOutputMetrics NodeConnectionMessageMetrics + inUnspentAliasOutputMetrics NodeConnectionMessageMetrics +} + +var _ NodeConnectionMessagesMetrics = &nodeConnectionMessagesMetricsImpl{} + +func newNodeConnectionMessagesMetrics(ncmi *nodeConnectionMetricsImpl, chainID *iscp.ChainID) NodeConnectionMessagesMetrics { + return &nodeConnectionMessagesMetricsImpl{ + outPullStateMetrics: newNodeConnectionMessageMetrics(ncmi, chainID, "out_pull_state"), + outPullTransactionInclusionStateMetrics: newNodeConnectionMessageMetrics(ncmi, chainID, "out_pull_transaction_inclusion_state"), + outPullConfirmedOutputMetrics: newNodeConnectionMessageMetrics(ncmi, chainID, "out_pull_confirmed_output"), + outPostTransactionMetrics: newNodeConnectionMessageMetrics(ncmi, chainID, "out_post_transaction"), + + inTransactionMetrics: newNodeConnectionMessageMetrics(ncmi, chainID, "in_transaction"), + inInclusionStateMetrics: newNodeConnectionMessageMetrics(ncmi, chainID, "in_inclusion_state"), + inOutputMetrics: newNodeConnectionMessageMetrics(ncmi, chainID, "in_output"), + inUnspentAliasOutputMetrics: newNodeConnectionMessageMetrics(ncmi, chainID, "in_alias_output"), + } +} + +func (ncmmi *nodeConnectionMessagesMetricsImpl) GetOutPullState() NodeConnectionMessageMetrics { + return ncmmi.outPullStateMetrics +} + +func (ncmmi *nodeConnectionMessagesMetricsImpl) GetOutPullTransactionInclusionState() NodeConnectionMessageMetrics { + return ncmmi.outPullTransactionInclusionStateMetrics +} + +func (ncmmi *nodeConnectionMessagesMetricsImpl) GetOutPullConfirmedOutput() NodeConnectionMessageMetrics { + return ncmmi.outPullConfirmedOutputMetrics +} + +func (ncmmi *nodeConnectionMessagesMetricsImpl) GetOutPostTransaction() NodeConnectionMessageMetrics { + return ncmmi.outPostTransactionMetrics +} + +func (ncmmi *nodeConnectionMessagesMetricsImpl) GetInTransaction() NodeConnectionMessageMetrics { + return ncmmi.inTransactionMetrics +} + +func (ncmmi *nodeConnectionMessagesMetricsImpl) GetInInclusionState() NodeConnectionMessageMetrics { + return ncmmi.inInclusionStateMetrics +} + +func (ncmmi *nodeConnectionMessagesMetricsImpl) GetInOutput() NodeConnectionMessageMetrics { + return ncmmi.inOutputMetrics +} + +func (ncmmi *nodeConnectionMessagesMetricsImpl) GetInUnspentAliasOutput() NodeConnectionMessageMetrics { + return ncmmi.inUnspentAliasOutputMetrics +} diff --git a/packages/metrics/nodeconnmetrics/metrics.go b/packages/metrics/nodeconnmetrics/metrics.go new file mode 100644 index 0000000000..466aaf9123 --- /dev/null +++ b/packages/metrics/nodeconnmetrics/metrics.go @@ -0,0 +1,81 @@ +package nodeconnmetrics + +import ( + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/hive.go/logger" + "github.com/iotaledger/wasp/packages/iscp" + "github.com/prometheus/client_golang/prometheus" +) + +type nodeConnectionMetricsImpl struct { + NodeConnectionMessagesMetrics + log *logger.Logger + messageTotalCounter *prometheus.CounterVec + lastEventTimeGauge *prometheus.GaugeVec + subscribed []ledgerstate.Address +} + +var _ NodeConnectionMetrics = &nodeConnectionMetricsImpl{} + +const ( + chainLabelName = "chain" + msgTypeLabelName = "message_type" +) + +func New(log *logger.Logger) NodeConnectionMetrics { + ret := &nodeConnectionMetricsImpl{log: log.Named("nodeconn")} + ret.NodeConnectionMessagesMetrics = newNodeConnectionMessagesMetrics(ret, nil) + return ret +} + +func (ncmi *nodeConnectionMetricsImpl) RegisterMetrics() { + ncmi.log.Debug("Registering nodeconnection metrics to prometheus...") + ncmi.messageTotalCounter = prometheus.NewCounterVec(prometheus.CounterOpts{ + Name: "wasp_nodeconn_message_total_counter", + Help: "Number of messages send/received by node connection of the chain", + }, []string{chainLabelName, msgTypeLabelName}) + prometheus.MustRegister(ncmi.messageTotalCounter) + ncmi.lastEventTimeGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Name: "wasp_nodeconn_last_event_time_gauge", + Help: "Last time when the message was sent/received by node connection of the chain", + }, []string{chainLabelName, msgTypeLabelName}) + prometheus.MustRegister(ncmi.lastEventTimeGauge) + ncmi.log.Info("Registering nodeconnection metrics to prometheus... Done") +} + +func (ncmi *nodeConnectionMetricsImpl) NewMessagesMetrics(chainID *iscp.ChainID) NodeConnectionMessagesMetrics { + return newNodeConnectionMessagesMetrics(ncmi, chainID) +} + +func (ncmi *nodeConnectionMetricsImpl) getMetricsLabel(chainID *iscp.ChainID, msgType string) prometheus.Labels { + var chainIDStr string + if chainID == nil { + chainIDStr = "" + } else { + chainIDStr = chainID.String() + } + return prometheus.Labels{ + chainLabelName: chainIDStr, + msgTypeLabelName: msgType, + } +} + +// TODO: connect subscribed to Prometheus +func (ncmi *nodeConnectionMetricsImpl) SetSubscribed(address ledgerstate.Address) { + ncmi.subscribed = append(ncmi.subscribed, address) +} + +// TODO: connect subscribed to Prometheus +func (ncmi *nodeConnectionMetricsImpl) SetUnsubscribed(address ledgerstate.Address) { + var i int + for i = 0; i < len(ncmi.subscribed); i++ { + if ncmi.subscribed[i] == address { + ncmi.subscribed = append(ncmi.subscribed[:i], ncmi.subscribed[i+1:]...) + return + } + } +} + +func (ncmi *nodeConnectionMetricsImpl) GetSubscribed() []ledgerstate.Address { + return ncmi.subscribed +} diff --git a/packages/parameters/parameters.go b/packages/parameters/parameters.go index 458d9b063d..549b70ec13 100644 --- a/packages/parameters/parameters.go +++ b/packages/parameters/parameters.go @@ -22,9 +22,10 @@ const ( DatabaseDir = "database.directory" DatabaseInMemory = "database.inMemory" - WebAPIBindAddress = "webapi.bindAddress" - WebAPIAdminWhitelist = "webapi.adminWhitelist" - WebAPIAuth = "webapi.auth" + WebAPIBindAddress = "webapi.bindAddress" + WebAPIAdminWhitelist = "webapi.adminWhitelist" + WebAPIAdminWhitelistDisabled = "webapi.adminWhitelistDisabled" + WebAPIAuth = "webapi.auth" DashboardBindAddress = "dashboard.bindAddress" DashboardExploreAddressURL = "dashboard.exploreAddressUrl" @@ -70,6 +71,7 @@ func Init() *configuration.Configuration { flag.String(WebAPIBindAddress, "127.0.0.1:8080", "the bind address for the web API") flag.StringSlice(WebAPIAdminWhitelist, []string{}, "IP whitelist for /adm wndpoints") flag.StringToString(WebAPIAuth, nil, "authentication scheme for web API") + flag.Bool(WebAPIAdminWhitelistDisabled, false, "Disables IP whitelisting and allows requests from _any_ IP") flag.String(DashboardBindAddress, "127.0.0.1:7000", "the bind address for the node dashboard") flag.String(DashboardExploreAddressURL, "", "URL to add as href to addresses in the dashboard [default: :8081/explorer/address]") diff --git a/packages/peering/domain/domain.go b/packages/peering/domain/domain.go index ac042635a2..14bbc71cae 100644 --- a/packages/peering/domain/domain.go +++ b/packages/peering/domain/domain.go @@ -4,7 +4,6 @@ import ( "crypto/rand" "sort" "sync" - "time" "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/wasp/packages/peering" @@ -12,22 +11,27 @@ import ( ) type DomainImpl struct { - attachedTo peering.PeeringID netProvider peering.NetworkProvider nodes map[string]peering.PeerSender permutation *util.Permutation16 netIDs []string + peeringID peering.PeeringID + attachIDs []interface{} log *logger.Logger mutex *sync.RWMutex } +var _ peering.PeerDomainProvider = &DomainImpl{} + // NewPeerDomain creates a collection. Ignores self -func NewPeerDomain(netProvider peering.NetworkProvider, initialNodes []peering.PeerSender, log *logger.Logger) *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)), + peeringID: peeringID, + attachIDs: make([]interface{}, 0), log: log, mutex: &sync.RWMutex{}, } @@ -38,7 +42,7 @@ func NewPeerDomain(netProvider peering.NetworkProvider, initialNodes []peering.P return ret } -func NewPeerDomainByNetIDs(netProvider peering.NetworkProvider, peerNetIDs []string, log *logger.Logger) (*DomainImpl, error) { +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() { @@ -50,10 +54,10 @@ func NewPeerDomainByNetIDs(netProvider peering.NetworkProvider, peerNetIDs []str } peers = append(peers, peer) } - return NewPeerDomain(netProvider, peers, log), nil + return NewPeerDomain(netProvider, peeringID, peers, log), nil } -func (d *DomainImpl) SendMsgByNetID(netID string, msg *peering.PeerMessage) { +func (d *DomainImpl) SendMsgByNetID(netID string, msgReceiver, msgType byte, msgData []byte) { d.mutex.RLock() defer d.mutex.RUnlock() peer, ok := d.nodes[netID] @@ -61,39 +65,20 @@ func (d *DomainImpl) SendMsgByNetID(netID string, msg *peering.PeerMessage) { d.log.Warnf("SendMsgByNetID: NetID %v is not in the domain", netID) return } - peer.SendMsg(msg) -} - -func (d *DomainImpl) SendSimple(netID string, msgType byte, msgData []byte) { - d.SendMsgByNetID(netID, &peering.PeerMessage{ - PeeringID: d.attachedTo, - Timestamp: time.Now().UnixNano(), - MsgType: msgType, - MsgData: msgData, + peer.SendMsg(&peering.PeerMessageData{ + PeeringID: d.peeringID, + MsgReceiver: msgReceiver, + MsgType: msgType, + MsgData: msgData, }) } -func (d *DomainImpl) SendMsgToRandomPeers(upToNumPeers uint16, msg *peering.PeerMessage) { - d.mutex.RLock() - defer d.mutex.RUnlock() - - if int(upToNumPeers) > len(d.nodes) { - upToNumPeers = uint16(len(d.nodes)) - } - for i := uint16(0); i < upToNumPeers; i++ { - d.SendMsgByNetID(d.netIDs[d.permutation.Next()], 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) SendMsgToRandomPeersSimple(upToNumPeers uint16, msgType byte, msgData []byte) { - d.SendMsgToRandomPeers(upToNumPeers, &peering.PeerMessage{ - PeeringID: d.attachedTo, - Timestamp: time.Now().UnixNano(), - MsgType: msgType, - MsgData: msgData, - }) -} - func (d *DomainImpl) GetRandomPeers(upToNumPeers int) []string { d.mutex.RLock() defer d.mutex.RUnlock() @@ -157,18 +142,23 @@ func (d *DomainImpl) reshufflePeers(seedBytes ...[]byte) { d.permutation.Shuffle(seedB) } -func (d *DomainImpl) Attach(peeringID *peering.PeeringID, callback func(recv *peering.RecvEvent)) interface{} { - d.attachedTo = *peeringID - return d.netProvider.Attach(peeringID, func(recv *peering.RecvEvent) { - peer, ok := d.nodes[recv.From.NetID()] - if ok && peer.NetID() != d.netProvider.Self().NetID() { - recv.Msg.SenderNetID = peer.NetID() - callback(recv) +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() { + d.log.Warnf("dropping message for receiver=%v MsgType=%v from %v: message from self.", + recv.MsgReceiver, recv.MsgType, recv.SenderNetID) return } - d.log.Warnf("dropping message MsgType=%v from %v, it does not belong to the peer domain.", - recv.Msg.MsgType, recv.From.NetID()) + _, ok := d.nodes[recv.SenderNetID] + 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) + return + } + callback(recv) }) + d.attachIDs = append(d.attachIDs, attachID) + return attachID } func (d *DomainImpl) Detach(attachID interface{}) { @@ -176,6 +166,9 @@ func (d *DomainImpl) Detach(attachID interface{}) { } func (d *DomainImpl) Close() { + for _, attachID := range d.attachIDs { + d.Detach(attachID) + } for i := range d.nodes { d.nodes[i].Close() } diff --git a/packages/peering/domain/domain_test.go b/packages/peering/domain/domain_test.go index e3cb259c33..c5f1611808 100644 --- a/packages/peering/domain/domain_test.go +++ b/packages/peering/domain/domain_test.go @@ -24,31 +24,32 @@ func TestDomainProvider(t *testing.T) { // // Listen for messages on all the nodes. + peeringID := peering.RandomPeeringID() + receiver := byte(16) doneCh0 := make(chan bool) doneCh1 := make(chan bool) doneCh2 := make(chan bool) - nodes[0].Attach(nil, func(recv *peering.RecvEvent) { + nodes[0].Attach(&peeringID, receiver, func(recv *peering.PeerMessageIn) { t.Logf("0 received") doneCh0 <- true }) - nodes[1].Attach(nil, func(recv *peering.RecvEvent) { + nodes[1].Attach(&peeringID, receiver, func(recv *peering.PeerMessageIn) { t.Logf("1 received") doneCh1 <- true }) - nodes[2].Attach(nil, func(recv *peering.RecvEvent) { + nodes[2].Attach(&peeringID, receiver, func(recv *peering.PeerMessageIn) { t.Logf("2 received") doneCh2 <- true }) // // Create a group on one of nodes. var d peering.PeerDomainProvider - d, err := nodes[1].PeerDomain(netIDs) + d, err := nodes[1].PeerDomain(peeringID, netIDs) require.Nil(t, err) require.NotNil(t, d) - msg := &peering.PeerMessage{PeeringID: peering.RandomPeeringID(), MsgType: 125} - d.SendMsgByNetID(netIDs[0], msg) - d.SendMsgByNetID(netIDs[2], msg) + d.SendMsgByNetID(netIDs[0], receiver, 125, []byte{}) + d.SendMsgByNetID(netIDs[2], receiver, 125, []byte{}) <-doneCh0 <-doneCh2 // @@ -67,13 +68,14 @@ func TestRandom(t *testing.T) { 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(netIDs) + d1, err := nodes[1].PeerDomain(peeringID, netIDs) require.NoError(t, err) require.NotNil(t, d1) - d2, err := nodes[2].PeerDomain(netIDs) + d2, err := nodes[2].PeerDomain(peeringID, netIDs) require.NoError(t, err) require.NotNil(t, d1) @@ -81,14 +83,15 @@ func TestRandom(t *testing.T) { // Listen for messages on all the nodes. var wg sync.WaitGroup var r1, r2 int + receiver := byte(8) for i := range nodes { ii := i - nodes[i].Attach(nil, func(recv *peering.RecvEvent) { + nodes[i].Attach(&peeringID, receiver, func(recv *peering.PeerMessageIn) { t.Logf("%d received", ii) - if netIDs[1] == recv.From.NetID() { + if netIDs[1] == recv.SenderNetID { r1++ } - if netIDs[2] == recv.From.NetID() { + if netIDs[2] == recv.SenderNetID { r2++ } wg.Done() @@ -99,9 +102,12 @@ func TestRandom(t *testing.T) { for i := 0; i < 5; i++ { wg.Add(sendTo * 2) t.Log("----------------------------------") - msg := &peering.PeerMessage{PeeringID: peering.RandomPeeringID(), MsgType: 125} - d1.SendMsgToRandomPeers(sendTo, msg) - d2.SendMsgToRandomPeers(sendTo, msg) + for _, netID := range d1.GetRandomPeers(sendTo) { + d1.SendMsgByNetID(netID, receiver, 125, []byte{}) + } + for _, netID := range d2.GetRandomPeers(sendTo) { + d2.SendMsgByNetID(netID, receiver, 125, []byte{}) + } wg.Wait() } require.EqualValues(t, sendTo*5, r1) diff --git a/packages/peering/group/group.go b/packages/peering/group/group.go index 38b4e43099..b931e34ba2 100644 --- a/packages/peering/group/group.go +++ b/packages/peering/group/group.go @@ -24,12 +24,16 @@ type groupImpl struct { nodes []peering.PeerSender other map[uint16]peering.PeerSender selfIndex uint16 + peeringID peering.PeeringID + attachIDs []interface{} log *logger.Logger } +var _ peering.GroupProvider = &groupImpl{} + // NewPeeringGroupProvider creates a generic peering group. // That should be used as a helper for peering implementations. -func NewPeeringGroupProvider(netProvider peering.NetworkProvider, nodes []peering.PeerSender, log *logger.Logger) (peering.GroupProvider, error) { +func NewPeeringGroupProvider(netProvider peering.NetworkProvider, peeringID peering.PeeringID, nodes []peering.PeerSender, log *logger.Logger) (peering.GroupProvider, error) { other := make(map[uint16]peering.PeerSender) selfFound := false selfIndex := uint16(0) @@ -49,6 +53,8 @@ func NewPeeringGroupProvider(netProvider peering.NetworkProvider, nodes []peerin nodes: nodes, other: other, selfIndex: selfIndex, + peeringID: peeringID, + attachIDs: make([]interface{}, 0), log: log, }, nil } @@ -73,21 +79,27 @@ func (g *groupImpl) PeerIndexByNetID(peerNetID string) (uint16, error) { return NotInGroup, errors.New("peer_not_found_by_net_id") } +func (g *groupImpl) NetIDByIndex(index uint16) (string, error) { + if index < uint16(len(g.nodes)) { + return g.nodes[index].NetID(), nil + } + return "", errors.New("peer_index_out_of_scope") +} + // SendMsgByIndex implements peering.GroupProvider. -func (g *groupImpl) SendMsgByIndex(peerIdx uint16, msg *peering.PeerMessage) { - g.nodes[peerIdx].SendMsg(msg) +func (g *groupImpl) SendMsgByIndex(peerIdx uint16, msgReceiver, msgType byte, msgData []byte) { + g.nodes[peerIdx].SendMsg(&peering.PeerMessageData{ + PeeringID: g.peeringID, + MsgReceiver: msgReceiver, + MsgType: msgType, + MsgData: msgData, + }) } // Broadcast implements peering.GroupProvider. -func (g *groupImpl) Broadcast(msg *peering.PeerMessage, includingSelf bool, except ...uint16) { - var peers map[uint16]peering.PeerSender - if includingSelf { - peers = g.AllNodes(except...) - } else { - peers = g.OtherNodes(except...) - } - for i := range peers { - peers[i].SendMsg(msg) +func (g *groupImpl) SendMsgBroadcast(msgReceiver, msgType byte, msgData []byte, except ...uint16) { + for i := range g.OtherNodes(except...) { + g.SendMsgByIndex(i, msgReceiver, msgType, msgData) } } @@ -95,13 +107,12 @@ func (g *groupImpl) Broadcast(msg *peering.PeerMessage, includingSelf bool, exce // Resends the messages if acks are not received for some time. func (g *groupImpl) ExchangeRound( peers map[uint16]peering.PeerSender, - recvCh chan *peering.RecvEvent, + recvCh chan *peering.PeerMessageIn, retryTimeout time.Duration, giveUpTimeout time.Duration, sendCB func(peerIdx uint16, peer peering.PeerSender), - recvCB func(recv *peering.RecvEvent) (bool, error), + recvCB func(recv *peering.PeerMessageGroupIn) (bool, error), ) error { - var err error acks := make(map[uint16]bool) errs := make(map[uint16]error) retryCh := time.After(retryTimeout) @@ -120,33 +131,38 @@ func (g *groupImpl) ExchangeRound( } for !haveAllAcks() { select { - case recvMsg, ok := <-recvCh: + case recvMsgNoIndex, ok := <-recvCh: if !ok { return errors.New("recv_channel_closed") } - if recvMsg.Msg.SenderIndex, err = g.PeerIndex(recvMsg.From); err != nil { + senderIndex, err := g.PeerIndexByNetID(recvMsgNoIndex.SenderNetID) + if err != nil { g.log.Warnf( "Dropping message %v -> %v, MsgType=%v because of %v", - recvMsg.From.NetID(), g.netProvider.Self().NetID(), - recvMsg.Msg.MsgType, err, + recvMsgNoIndex.SenderNetID, g.netProvider.Self().NetID(), + recvMsgNoIndex.MsgType, err, ) continue } - if acks[recvMsg.Msg.SenderIndex] { // Only consider first successful message. + recvMsg := peering.PeerMessageGroupIn{ + PeerMessageIn: *recvMsgNoIndex, + SenderIndex: senderIndex, + } + if acks[recvMsg.SenderIndex] { // Only consider first successful message. g.log.Warnf( - "Dropping duplicate message %v -> %v, MsgType=%v", - recvMsg.From.NetID(), g.netProvider.Self().NetID(), - recvMsg.Msg.MsgType, + "Dropping duplicate message %v -> %v, receiver=%v, MsgType=%v", + recvMsg.SenderNetID, g.netProvider.Self().NetID(), + recvMsg.MsgReceiver, recvMsg.MsgType, ) continue } - if acks[recvMsg.Msg.SenderIndex], err = recvCB(recvMsg); err != nil { - errs[recvMsg.Msg.SenderIndex] = err + if acks[recvMsg.SenderIndex], err = recvCB(&recvMsg); err != nil { + errs[recvMsg.SenderIndex] = err continue } - if acks[recvMsg.Msg.SenderIndex] { + if acks[recvMsg.SenderIndex] { // Clear previous errors on success. - delete(errs, recvMsg.Msg.SenderIndex) + delete(errs, recvMsg.SenderIndex) } case <-retryCh: for i := range peers { @@ -216,15 +232,25 @@ func (g *groupImpl) OtherNodes(except ...uint16) map[uint16]peering.PeerSender { // Attach starts listening for messages. Messages in this case will be filtered // to those received from nodes in the group only. SenderIndex will be filled // for the messages according to the message source. -func (g *groupImpl) Attach(peeringID *peering.PeeringID, callback func(recv *peering.RecvEvent)) interface{} { - return g.netProvider.Attach(peeringID, func(recv *peering.RecvEvent) { - if idx, err := g.PeerIndexByNetID(recv.From.NetID()); err == nil && idx != NotInGroup { - recv.Msg.SenderIndex = idx - callback(recv) +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) + 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) return } - g.log.Warnf("Dropping message MsgType=%v from %v, it does not belong to the group.", recv.Msg.MsgType, recv.From.NetID()) + gRecv := &peering.PeerMessageGroupIn{ + PeerMessageIn: *recv, + SenderIndex: idx, + } + callback(gRecv) }) + g.attachIDs = append(g.attachIDs, attachID) + return attachID } // Detach terminates listening for messages. @@ -234,6 +260,9 @@ func (g *groupImpl) Detach(attachID interface{}) { // Close implements peering.GroupProvider. func (g *groupImpl) Close() { + for _, attachID := range g.attachIDs { + g.Detach(attachID) + } for i := range g.nodes { g.nodes[i].Close() } diff --git a/packages/peering/group/group_test.go b/packages/peering/group/group_test.go index f40057b50b..02659f5359 100644 --- a/packages/peering/group/group_test.go +++ b/packages/peering/group/group_test.go @@ -14,7 +14,7 @@ func TestGroupProvider(t *testing.T) { log := testlogger.NewLogger(t) defer log.Sync() - nodeCount := 3 + nodeCount := 4 netIDs, nodeIdentities := testpeers.SetupKeys(uint16(nodeCount)) nodes, netCloser := testpeers.SetupNet(netIDs, nodeIdentities, testutil.NewPeeringNetReliable(log), log) for i := range nodes { @@ -23,29 +23,31 @@ func TestGroupProvider(t *testing.T) { // // Listen for messages on all the nodes. - doneCh0 := make(chan bool) + peeringID := peering.RandomPeeringID() + receiver := byte(4) doneCh1 := make(chan bool) doneCh2 := make(chan bool) - nodes[0].Attach(nil, func(recv *peering.RecvEvent) { - doneCh0 <- true - }) - nodes[1].Attach(nil, func(recv *peering.RecvEvent) { + doneCh3 := make(chan bool) + nodes[1].Attach(&peeringID, receiver, func(recv *peering.PeerMessageIn) { doneCh1 <- true }) - nodes[2].Attach(nil, func(recv *peering.RecvEvent) { + nodes[2].Attach(&peeringID, receiver, func(recv *peering.PeerMessageIn) { doneCh2 <- true }) + nodes[3].Attach(&peeringID, receiver, func(recv *peering.PeerMessageIn) { + doneCh3 <- true + }) // // Create a group on one of nodes. var g peering.GroupProvider - g, err := nodes[1].PeerGroup(netIDs) + g, err := nodes[0].PeerGroup(peeringID, netIDs) require.Nil(t, err) // // Broadcast a message and wait until it will be received on all the nodes. - g.Broadcast(&peering.PeerMessage{PeeringID: peering.RandomPeeringID(), MsgType: 125}, true) - <-doneCh0 + g.SendMsgBroadcast(receiver, 125, []byte{}) <-doneCh1 <-doneCh2 + <-doneCh3 // // Done. g.Close() diff --git a/packages/peering/lpp/lppNetImpl.go b/packages/peering/lpp/lppNetImpl.go index a73e447aba..6cd4faf086 100644 --- a/packages/peering/lpp/lppNetImpl.go +++ b/packages/peering/lpp/lppNetImpl.go @@ -70,6 +70,11 @@ type netImpl struct { log *logger.Logger } +var ( + _ peering.NetworkProvider = &netImpl{} + _ peering.PeerSender = &netImpl{} +) + // NewNetworkProvider is a constructor for the TCP based // peering network implementation. func NewNetworkProvider( @@ -208,19 +213,12 @@ func (n *netImpl) lppPeeringProtocolHandler(stream network.Stream) { n.log.Warnf("Failed to read incoming payload from %v, reason=%v", remotePeer.remoteNetID, err) return } - peerMsg, err := peering.NewPeerMessageFromBytes(payload, nil) // Do not use the signatures, we have TLS. + peerMsg, err := peering.NewPeerMessageNetFromBytes(payload) // Do not use the signatures, we have TLS. if err != nil { n.log.Warnf("Error while decoding a message, reason=%v", err) return } - remotePeer.noteReceived() - peerMsg.SenderNetID = remotePeer.NetID() - remotePeer.RecvMsg( - &peering.RecvEvent{ - From: remotePeer, - Msg: peerMsg, - }, - ) + remotePeer.RecvMsg(peerMsg) } func (n *netImpl) lppHeartbeatProtocolHandler(stream network.Stream) { @@ -296,8 +294,8 @@ func (n *netImpl) delPeer(peer *peer) { // A handler suitable for events.NewEvent(). func (n *netImpl) eventHandler(handler interface{}, params ...interface{}) { - callback := handler.(func(_ *peering.RecvEvent)) - recvEvent := params[0].(*peering.RecvEvent) + callback := handler.(func(_ *peering.PeerMessageIn)) + recvEvent := params[0].(*peering.PeerMessageIn) callback(recvEvent) } @@ -321,7 +319,7 @@ func (n *netImpl) Self() peering.PeerSender { } // Group creates peering.GroupProvider. -func (n *netImpl) PeerGroup(peerNetIDs []string) (peering.GroupProvider, error) { +func (n *netImpl) PeerGroup(peeringID peering.PeeringID, peerNetIDs []string) (peering.GroupProvider, error) { var err error groupPeers := make([]peering.PeerSender, len(peerNetIDs)) for i := range peerNetIDs { @@ -329,11 +327,11 @@ func (n *netImpl) PeerGroup(peerNetIDs []string) (peering.GroupProvider, error) return nil, err } } - return group.NewPeeringGroupProvider(n, groupPeers, n.log) + return group.NewPeeringGroupProvider(n, peeringID, groupPeers, n.log) } // Domain creates peering.PeerDomainProvider. -func (n *netImpl) PeerDomain(peerNetIDs []string) (peering.PeerDomainProvider, error) { +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() { @@ -345,13 +343,22 @@ func (n *netImpl) PeerDomain(peerNetIDs []string) (peering.PeerDomainProvider, e } peers = append(peers, p) } - return domain.NewPeerDomain(n, peers, n.log), nil + return domain.NewPeerDomain(n, peeringID, peers, n.log), nil +} + +func (n *netImpl) SendMsgByNetID(netID string, msg *peering.PeerMessageData) { + peer, err := n.PeerByNetID(netID) + if err != nil { + n.log.Warnf("SendMsgByNetID: NetID %v is not in the network", netID) + return + } + peer.SendMsg(msg) } // Attach implements peering.NetworkProvider. -func (n *netImpl) Attach(peeringID *peering.PeeringID, callback func(recv *peering.RecvEvent)) interface{} { - closure := events.NewClosure(func(recv *peering.RecvEvent) { - if peeringID == nil || *peeringID == recv.Msg.PeeringID { +func (n *netImpl) Attach(peeringID *peering.PeeringID, receiver byte, callback func(recv *peering.PeerMessageIn)) interface{} { + closure := events.NewClosure(func(recv *peering.PeerMessageIn) { + if *peeringID == recv.PeeringID && receiver == recv.MsgReceiver { callback(recv) } }) @@ -361,12 +368,8 @@ func (n *netImpl) Attach(peeringID *peering.PeeringID, callback func(recv *peeri // Detach implements peering.NetworkProvider. func (n *netImpl) Detach(attachID interface{}) { - switch closure := attachID.(type) { - case *events.Closure: - n.recvEvents.Detach(closure) - default: - panic("invalid_attach_id") - } + closure := attachID.(*events.Closure) + n.recvEvents.Detach(closure) } // PeerByNetID implements peering.NetworkProvider. @@ -410,16 +413,16 @@ func (n *netImpl) PubKey() *ed25519.PublicKey { } // SendMsg implements peering.PeerSender for the Self() node. -func (n *netImpl) SendMsg(msg *peering.PeerMessage) { +func (n *netImpl) SendMsg(msg *peering.PeerMessageData) { // Don't go via the network, if sending a message to self. - n.triggerRecvEvents(&peering.RecvEvent{ - From: n.Self(), - Msg: msg, - }) + n.triggerRecvEvents(n.Self().NetID(), &peering.PeerMessageNet{PeerMessageData: *msg}) } -func (n *netImpl) triggerRecvEvents(msg interface{}) { - n.recvEvents.Trigger(msg) +func (n *netImpl) triggerRecvEvents(from string, msg *peering.PeerMessageNet) { + n.recvEvents.Trigger(&peering.PeerMessageIn{ + PeerMessageData: msg.PeerMessageData, + SenderNetID: from, + }) } // IsAlive implements peering.PeerSender for the Self() node. diff --git a/packages/peering/lpp/lppNetImpl_test.go b/packages/peering/lpp/lppNetImpl_test.go index ce81f1185b..02e5294146 100644 --- a/packages/peering/lpp/lppNetImpl_test.go +++ b/packages/peering/lpp/lppNetImpl_test.go @@ -53,15 +53,16 @@ func TestLPPPeeringImpl(t *testing.T) { n2p0, err := nodes[2].PeerByNetID(netIDs[0]) require.NoError(t, err) - nodes[0].Attach(nil, func(recv *peering.RecvEvent) { + chain1 := peering.RandomPeeringID() + chain2 := peering.RandomPeeringID() + receiver := byte(3) + nodes[0].Attach(&chain2, receiver, func(recv *peering.PeerMessageIn) { doneCh <- true }) - chain1 := peering.RandomPeeringID() - chain2 := peering.RandomPeeringID() - n0p2.SendMsg(&peering.PeerMessage{PeeringID: chain1, MsgType: 125}) - n1p1.SendMsg(&peering.PeerMessage{PeeringID: chain1, MsgType: 125}) - n2p0.SendMsg(&peering.PeerMessage{PeeringID: chain2, MsgType: 125}) + n0p2.SendMsg(&peering.PeerMessageData{PeeringID: chain1, MsgReceiver: receiver, MsgType: 125}) + n1p1.SendMsg(&peering.PeerMessageData{PeeringID: chain1, MsgReceiver: receiver, MsgType: 125}) + n2p0.SendMsg(&peering.PeerMessageData{PeeringID: chain2, MsgReceiver: receiver, MsgType: 125}) <-doneCh time.Sleep(100 * time.Millisecond) diff --git a/packages/peering/lpp/lppPeer.go b/packages/peering/lpp/lppPeer.go index 386fe0c9b6..b5dbf946c9 100644 --- a/packages/peering/lpp/lppPeer.go +++ b/packages/peering/lpp/lppPeer.go @@ -10,14 +10,16 @@ import ( "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/pipe" libp2ppeer "github.com/libp2p/go-libp2p-core/peer" "golang.org/x/xerrors" - "gopkg.in/eapache/channels.v1" ) const ( inactiveDeadline = 1 * time.Minute inactivePingTime = 30 * time.Second + maxPeerMsgBuffer = 10000 + traceMessages = false ) type peer struct { @@ -25,8 +27,8 @@ type peer struct { remotePubKey *ed25519.PublicKey remoteLppID libp2ppeer.ID accessLock *sync.RWMutex - sendCh *channels.InfiniteChannel - recvCh *channels.InfiniteChannel + sendPipe pipe.Pipe + recvPipe pipe.Pipe lastMsgSent time.Time lastMsgRecv time.Time numUsers int @@ -35,15 +37,21 @@ type peer struct { log *logger.Logger } +var _ peering.PeerSender = &peer{} + func newPeer(remoteNetID string, remotePubKey *ed25519.PublicKey, remoteLppID libp2ppeer.ID, n *netImpl) *peer { log := n.log.Named("peer:" + remoteNetID) + messagePriorityFun := func(msg interface{}) bool { + // TODO: decide if prioritetisation is needed and implement it then. + return false + } p := &peer{ remoteNetID: remoteNetID, remotePubKey: remotePubKey, remoteLppID: remoteLppID, accessLock: &sync.RWMutex{}, - sendCh: channels.NewInfiniteChannel(), - recvCh: channels.NewInfiniteChannel(), + sendPipe: pipe.NewInfinitePipe(messagePriorityFun, maxPeerMsgBuffer), + recvPipe: pipe.NewInfinitePipe(messagePriorityFun, maxPeerMsgBuffer), lastMsgSent: time.Time{}, lastMsgRecv: time.Time{}, numUsers: 0, @@ -84,8 +92,8 @@ func (p *peer) maintenanceCheck() { } if numUsers == 0 && !trusted && lastMsgOld { p.net.delPeer(p) - p.sendCh.Close() - p.recvCh.Close() + p.sendPipe.Close() + p.recvPipe.Close() } } @@ -107,35 +115,44 @@ func (p *peer) PubKey() *ed25519.PublicKey { // SendMsg implements peering.PeerSender interface for the remote peers. // The send operation is performed asynchronously. // The async sending helped to cope with sporadic deadlocks. -func (p *peer) SendMsg(msg *peering.PeerMessage) { +func (p *peer) SendMsg(msg *peering.PeerMessageData) { // p.accessLock.RLock() + msgNet := &peering.PeerMessageNet{PeerMessageData: *msg} if !p.trusted { p.log.Infof("Dropping outgoing message, because it was meant to send to a distrusted peer.") p.accessLock.RUnlock() return } p.accessLock.RUnlock() - p.sendCh.In() <- msg + p.sendPipe.In() <- msgNet } -func (p *peer) RecvMsg(msg *peering.RecvEvent) { - p.recvCh.In() <- msg +func (p *peer) RecvMsg(msg *peering.PeerMessageNet) { + if traceMessages { + p.log.Debugf("Peer message received from peer %v, peeringID %v, receiver %v, type %v, length %v, first bytes %v", + p.NetID(), msg.PeeringID, msg.MsgReceiver, msg.MsgType, len(msg.MsgData), firstBytes(16, msg.MsgData)) + } + p.noteReceived() + p.recvPipe.In() <- msg } func (p *peer) sendLoop() { - for msg := range p.sendCh.Out() { - p.sendMsgDirect(msg.(*peering.PeerMessage)) + for msg := range p.sendPipe.Out() { + p.sendMsgDirect(msg.(*peering.PeerMessageNet)) } } func (p *peer) recvLoop() { - for msg := range p.recvCh.Out() { - p.net.triggerRecvEvents(msg) + for msg := range p.recvPipe.Out() { + peerMsg, ok := msg.(*peering.PeerMessageNet) + if ok { + p.net.triggerRecvEvents(p.NetID(), peerMsg) + } } } -func (p *peer) sendMsgDirect(msg *peering.PeerMessage) { +func (p *peer) sendMsgDirect(msg *peering.PeerMessageNet) { stream, err := p.net.lppHost.NewStream(p.net.ctx, p.remoteLppID, lppProtocolPeering) if err != nil { p.log.Warnf("Failed to send outgoing message, unable to allocate stream, reason=%v", err) @@ -143,7 +160,7 @@ func (p *peer) sendMsgDirect(msg *peering.PeerMessage) { } defer stream.Close() // - msgBytes, err := msg.Bytes(nil) // Do not use msg signatures, we are using TLS. + msgBytes, err := msg.Bytes() // Do not use msg signatures, we are using TLS. if err != nil { p.log.Warnf("Failed to send outgoing message, unable to serialize, reason=%v", err) return @@ -155,6 +172,17 @@ func (p *peer) sendMsgDirect(msg *peering.PeerMessage) { p.accessLock.Lock() p.lastMsgSent = time.Now() p.accessLock.Unlock() + if traceMessages { + p.log.Debugf("Peer message sent to peer %v, peeringID %v, receiver %v, type %v, length %v, first bytes %v", + p.NetID(), msg.PeeringID, msg.MsgReceiver, msg.MsgType, len(msg.MsgData), firstBytes(16, msg.MsgData)) + } +} + +func firstBytes(maxCount int, array []byte) []byte { + if len(array) <= maxCount { + return array + } + return array[:maxCount] } // IsAlive implements peering.PeerSender and peering.PeerStatusProvider interfaces for the remote peers. diff --git a/packages/peering/peer_message.go b/packages/peering/peer_message.go new file mode 100644 index 0000000000..11f9851e29 --- /dev/null +++ b/packages/peering/peer_message.go @@ -0,0 +1,112 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// Package peering provides an overlay network for communicating +// between nodes in a peer-to-peer style with low overhead +// encoding and persistent connections. The network provides only +// the asynchronous communication. +// +// It is intended to use for the committee consensus protocol. +// +package peering + +import ( + "bytes" + + "github.com/iotaledger/wasp/packages/hashing" + "github.com/iotaledger/wasp/packages/util" + "github.com/iotaledger/wasp/packages/util/pipe" +) + +// PeerMessage is an envelope for all the messages exchanged via +// the peering module. +type PeerMessageData struct { + PeeringID PeeringID + MsgReceiver byte + MsgType byte + MsgData []byte +} + +type PeerMessageNet struct { + PeerMessageData + serialized *[]byte +} + +type PeerMessageIn struct { + PeerMessageData + SenderNetID string +} + +type PeerMessageGroupIn struct { + PeerMessageIn + SenderIndex uint16 +} + +var _ pipe.Hashable = &PeerMessageNet{} + +//nolint:gocritic +func NewPeerMessageDataFromBytes(buf []byte) (*PeerMessageData, error) { + var err error + r := bytes.NewBuffer(buf) + m := PeerMessageData{} + if m.MsgReceiver, err = util.ReadByte(r); err != nil { + return nil, err + } + if m.MsgType, err = util.ReadByte(r); err != nil { + return nil, err + } + if err = m.PeeringID.Read(r); err != nil { + return nil, err + } + if m.MsgData, err = util.ReadBytes32(r); err != nil { + return nil, err + } + return &m, nil +} + +func NewPeerMessageNetFromBytes(buf []byte) (*PeerMessageNet, error) { + data, err := NewPeerMessageDataFromBytes(buf) + if err != nil { + return nil, err + } + return &PeerMessageNet{ + PeerMessageData: *data, + serialized: &buf, + }, nil +} + +func (m *PeerMessageNet) Bytes() ([]byte, error) { + if m.serialized == nil { + serialized, err := m.PeerMessageData.bytes() + if err != nil { + return nil, err + } + m.serialized = &serialized + } + return *(m.serialized), nil +} + +func (m *PeerMessageData) bytes() ([]byte, error) { + var buf bytes.Buffer + if err := util.WriteByte(&buf, m.MsgReceiver); err != nil { + return nil, err + } + if err := util.WriteByte(&buf, m.MsgType); err != nil { + return nil, err + } + if err := m.PeeringID.Write(&buf); err != nil { + return nil, err + } + if err := util.WriteBytes32(&buf, m.MsgData); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (m *PeerMessageNet) GetHash() hashing.HashValue { + mBytes, err := m.Bytes() + if err != nil { + return hashing.HashValue{} + } + return hashing.HashData(mBytes) +} diff --git a/packages/peering/peering.go b/packages/peering/peering.go index 655e50bb31..0b4005136f 100644 --- a/packages/peering/peering.go +++ b/packages/peering/peering.go @@ -11,75 +11,41 @@ package peering import ( - "bytes" - "io" - "math/rand" "strconv" "strings" "time" - "github.com/iotaledger/goshimmer/packages/ledgerstate" - "github.com/iotaledger/goshimmer/packages/txstream/chopper" "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/wasp/packages/util" - "github.com/mr-tron/base58" "golang.org/x/xerrors" ) const ( - MsgTypeReserved = byte(0) - MsgTypeHandshake = byte(1) - MsgTypeMsgChunk = byte(2) - // 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) - chunkMessageOverhead = 8 + 1 + PeerMessageReceiverStateManager = byte(iota) + PeerMessageReceiverConsensus + PeerMessageReceiverCommonSubset + PeerMessageReceiverChain + PeerMessageReceiverDkg + PeerMessageReceiverDkgInit ) -// PeeringID is relates peers in different nodes for a particular -// communication group. E.g. PeeringID identifies a committee in -// the consensus, etc. -type PeeringID [ledgerstate.AddressLength]byte - -func RandomPeeringID(seed ...[]byte) PeeringID { - var pid PeeringID - _, _ = rand.Read(pid[:]) - return pid -} - -func (pid *PeeringID) String() string { - return base58.Encode(pid[:]) -} - -func (pid *PeeringID) Read(r io.Reader) error { - if n, err := r.Read(pid[:]); err != nil || n != ledgerstate.AddressLength { - return xerrors.Errorf("error while parsing PeeringID (err=%v)", err) - } - return nil -} - -func (pid *PeeringID) Write(w io.Writer) error { - if n, err := w.Write(pid[:]); err != nil || n != ledgerstate.AddressLength { - return xerrors.Errorf("error while serializing PeeringID (err=%v)", err) - } - return nil -} - // NetworkProvider stands for the peer-to-peer network, as seen // from the viewpoint of a single participant. type NetworkProvider interface { Run(stopCh <-chan struct{}) Self() PeerSender - PeerGroup(peerAddrs []string) (GroupProvider, error) - PeerDomain(peerAddrs []string) (PeerDomainProvider, error) - Attach(peeringID *PeeringID, callback func(recv *RecvEvent)) interface{} - Detach(attachID interface{}) + PeerGroup(peeringID PeeringID, peerAddrs []string) (GroupProvider, error) + PeerDomain(peeringID PeeringID, peerAddrs []string) (PeerDomainProvider, error) PeerByNetID(peerNetID string) (PeerSender, error) PeerByPubKey(peerPub *ed25519.PublicKey) (PeerSender, error) 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. @@ -93,51 +59,6 @@ type TrustedNetworkManager interface { TrustedPeers() ([]*TrustedPeer, error) } -// TrustedPeer carries a peer information we use to trust it. -type TrustedPeer struct { - PubKey ed25519.PublicKey - NetID string -} - -func TrustedPeerFromBytes(buf []byte) (*TrustedPeer, error) { - var err error - r := bytes.NewBuffer(buf) - tp := TrustedPeer{} - var keyBytes []byte - if keyBytes, err = util.ReadBytes16(r); err != nil { - return nil, err - } - tp.PubKey, _, err = ed25519.PublicKeyFromBytes(keyBytes) - if err != nil { - return nil, err - } - if tp.NetID, err = util.ReadString16(r); err != nil { - return nil, err - } - return &tp, nil -} - -func (tp *TrustedPeer) Bytes() ([]byte, error) { - var buf bytes.Buffer - if err := util.WriteBytes16(&buf, tp.PubKey.Bytes()); err != nil { - return nil, err - } - if err := util.WriteString16(&buf, tp.NetID); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -func (tp *TrustedPeer) PubKeyBytes() ([]byte, error) { - return tp.PubKey.Bytes(), nil -} - -type PeerCollection interface { - Attach(peeringID *PeeringID, callback func(recv *RecvEvent)) interface{} - Detach(attachID interface{}) - Close() -} - // GroupProvider stands for a subset of a peer-to-peer network // that is responsible for achieving some common goal, eg, // consensus committee, DKG group, etc. @@ -148,31 +69,34 @@ type GroupProvider interface { SelfIndex() uint16 PeerIndex(peer PeerSender) (uint16, error) PeerIndexByNetID(peerNetID string) (uint16, error) - SendMsgByIndex(peerIdx uint16, msg *PeerMessage) - Broadcast(msg *PeerMessage, includingSelf bool, except ...uint16) + NetIDByIndex(index uint16) (string, error) + Attach(receiver byte, callback func(recv *PeerMessageGroupIn)) interface{} + Detach(attachID interface{}) + SendMsgByIndex(peerIdx uint16, msgReceiver byte, msgType byte, msgData []byte) + SendMsgBroadcast(msgReceiver byte, msgType byte, msgData []byte, except ...uint16) ExchangeRound( peers map[uint16]PeerSender, - recvCh chan *RecvEvent, + recvCh chan *PeerMessageIn, retryTimeout time.Duration, giveUpTimeout time.Duration, sendCB func(peerIdx uint16, peer PeerSender), - recvCB func(recv *RecvEvent) (bool, error), + recvCB func(recv *PeerMessageGroupIn) (bool, error), ) error AllNodes(except ...uint16) map[uint16]PeerSender // Returns all the nodes in the group except specified. OtherNodes(except ...uint16) map[uint16]PeerSender // Returns other nodes in the group (excluding Self and specified). - PeerCollection + Close() } // PeerDomainProvider implements unordered set of peers which can dynamically change // All peers in the domain shares same peeringID. Each peer within domain is identified via its netID type PeerDomainProvider interface { - SendMsgByNetID(netID string, msg *PeerMessage) - SendMsgToRandomPeers(upToNumPeers uint16, msg *PeerMessage) - SendSimple(netID string, msgType byte, msgData []byte) - SendMsgToRandomPeersSimple(upToNumPeers uint16, msgType byte, msgData []byte) ReshufflePeers(seedBytes ...[]byte) GetRandomPeers(upToNumPeers int) []string - PeerCollection + 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) + Close() } // PeerSender represents an interface to some remote peer. @@ -189,7 +113,7 @@ type PeerSender interface { // SendMsg works in an asynchronous way, and therefore the // errors are not returned here. - SendMsg(msg *PeerMessage) + SendMsg(msg *PeerMessageData) // IsAlive indicates, if there is a working connection with the peer. // It is always an approximate state. @@ -216,160 +140,6 @@ type PeerStatusProvider interface { NumUsers() int } -// RecvEvent stands for a received message along with -// the reference to its sender peer. -type RecvEvent struct { - From PeerSender - Msg *PeerMessage -} - -// PeerMessage is an envelope for all the messages exchanged via -// the peering module. -type PeerMessage struct { - PeeringID PeeringID - SenderIndex uint16 // TODO: Only meaningful in a group, and when calculated by the client. - SenderNetID string // TODO: Non persistent. Only used by PeeringDomain, filled by the receiver - Timestamp int64 - MsgType byte - MsgData []byte -} - -//nolint:gocritic -func NewPeerMessageFromBytes(buf []byte, peerPubKey *ed25519.PublicKey) (*PeerMessage, error) { - var err error - r := bytes.NewBuffer(buf) - m := PeerMessage{} - if err = util.ReadInt64(r, &m.Timestamp); err != nil { - return nil, err - } - if m.MsgType, err = util.ReadByte(r); err != nil { - return nil, err - } - switch m.MsgType { - case MsgTypeReserved: - case MsgTypeHandshake: - if m.MsgData, err = util.ReadBytes32(r); err != nil { - return nil, err - } - case MsgTypeMsgChunk: - if m.MsgData, err = util.ReadBytes32(r); err != nil { - return nil, err - } - default: - if err = m.PeeringID.Read(r); err != nil { - return nil, err - } - if err = util.ReadUint16(r, &m.SenderIndex); err != nil { - return nil, err - } - if m.MsgData, err = util.ReadBytes32(r); err != nil { - return nil, err - } - if peerPubKey != nil { - // Check the signature, if key is provided. - lenBeforeSig := r.Len() - var signatureBin []byte - if signatureBin, err = util.ReadBytes16(r); err != nil { - return nil, xerrors.Errorf("failed to read signature: %w", err) - } - var signature ed25519.Signature - if signature, _, err = ed25519.SignatureFromBytes(signatureBin); err != nil { - return nil, xerrors.Errorf("failed to parse signature: %w", err) - } - if !peerPubKey.VerifySignature(buf[:len(buf)-lenBeforeSig], signature) { - return nil, xerrors.New("signature verification failed") - } - } - } - return &m, nil -} - -// NewPeerMessageFromChunks can return nil, if there is not enough chunks to reconstruct the message. -func NewPeerMessageFromChunks(chunkBytes []byte, chunkSize int, msgChopper *chopper.Chopper, peerPubKey *ed25519.PublicKey) (*PeerMessage, error) { - var err error - var msgBytes []byte - if msgBytes, err = msgChopper.IncomingChunk(chunkBytes, chunkSize, chunkMessageOverhead); err != nil { - return nil, err - } - if msgBytes == nil { - return nil, nil - } - return NewPeerMessageFromBytes(msgBytes, peerPubKey) -} - -func (m *PeerMessage) Bytes(nodeIdentity *ed25519.KeyPair) ([]byte, error) { - var buf bytes.Buffer - if err := util.WriteInt64(&buf, m.Timestamp); err != nil { - return nil, err - } - if err := util.WriteByte(&buf, m.MsgType); err != nil { - return nil, err - } - switch m.MsgType { - case MsgTypeReserved: - case MsgTypeHandshake: - if err := util.WriteBytes32(&buf, m.MsgData); err != nil { - return nil, err - } - case MsgTypeMsgChunk: - if err := util.WriteBytes32(&buf, m.MsgData); err != nil { - return nil, err - } - default: - if err := m.PeeringID.Write(&buf); err != nil { - return nil, err - } - if err := util.WriteUint16(&buf, m.SenderIndex); err != nil { - return nil, err - } - if err := util.WriteBytes32(&buf, m.MsgData); err != nil { - return nil, err - } - if nodeIdentity != nil { - // Only use signatures, if the key is provided. - payload := buf.Bytes() - signature := nodeIdentity.PrivateKey.Sign(payload).Bytes() - if err := util.WriteBytes16(&buf, signature); err != nil { - return nil, xerrors.Errorf("failed to write signature: %w", err) - } - } - } - return buf.Bytes(), nil -} - -func (m *PeerMessage) ChunkedBytes(chunkSize int, msgChopper *chopper.Chopper, nodeIdentity *ed25519.KeyPair) ([][]byte, error) { - var err error - var msgBytes []byte - if msgBytes, err = m.Bytes(nodeIdentity); err != nil { - return nil, err - } - var choppedBytes [][]byte - var chopped bool - choppedBytes, chopped, err = msgChopper.ChopData(msgBytes, chunkSize, chunkMessageOverhead) - if err != nil { - return nil, err - } - if chopped { - msgs := make([][]byte, len(choppedBytes)) - for i := range choppedBytes { - chunkMsg := PeerMessage{ - Timestamp: m.Timestamp, - MsgType: MsgTypeMsgChunk, - MsgData: choppedBytes[i], - } - if msgs[i], err = chunkMsg.Bytes(nil); err != nil { - return nil, err - } - } - return msgs, nil - } - return [][]byte{msgBytes}, nil -} - -func (m *PeerMessage) IsUserMessage() bool { - return m.MsgType >= FirstUserMsgCode -} - // ParseNetID parses the NetID and returns the corresponding host and port. func ParseNetID(netID string) (string, int, error) { parts := strings.Split(netID, ":") diff --git a/packages/peering/peering_id.go b/packages/peering/peering_id.go new file mode 100644 index 0000000000..78803d82b3 --- /dev/null +++ b/packages/peering/peering_id.go @@ -0,0 +1,49 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// Package peering provides an overlay network for communicating +// between nodes in a peer-to-peer style with low overhead +// encoding and persistent connections. The network provides only +// the asynchronous communication. +// +// It is intended to use for the committee consensus protocol. +// +package peering + +import ( + "io" + "math/rand" + + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/mr-tron/base58" + "golang.org/x/xerrors" +) + +// PeeringID is relates peers in different nodes for a particular +// communication group. E.g. PeeringID identifies a committee in +// the consensus, etc. +type PeeringID [ledgerstate.AddressLength]byte + +func RandomPeeringID(seed ...[]byte) PeeringID { + var pid PeeringID + _, _ = rand.Read(pid[:]) + return pid +} + +func (pid *PeeringID) String() string { + return base58.Encode(pid[:]) +} + +func (pid *PeeringID) Read(r io.Reader) error { + if n, err := r.Read(pid[:]); err != nil || n != ledgerstate.AddressLength { + return xerrors.Errorf("error while parsing PeeringID (err=%v)", err) + } + return nil +} + +func (pid *PeeringID) Write(w io.Writer) error { + if n, err := w.Write(pid[:]); err != nil || n != ledgerstate.AddressLength { + return xerrors.Errorf("error while serializing PeeringID (err=%v)", err) + } + return nil +} diff --git a/packages/peering/peering_test.go b/packages/peering/peering_test.go index 7440947a2d..cbe56aeaf9 100644 --- a/packages/peering/peering_test.go +++ b/packages/peering/peering_test.go @@ -2,79 +2,32 @@ package peering_test import ( "bytes" - "math/rand" "testing" - "time" - "github.com/iotaledger/goshimmer/packages/txstream/chopper" - "github.com/iotaledger/hive.go/crypto/ed25519" "github.com/iotaledger/wasp/packages/peering" "github.com/stretchr/testify/require" ) func TestPeerMessageCodec(t *testing.T) { var err error - var src, dst *peering.PeerMessage - nodeIdentity := ed25519.GenerateKeyPair() - src = &peering.PeerMessage{ - PeeringID: peering.RandomPeeringID(), - SenderIndex: uint16(123), - Timestamp: time.Now().UnixNano(), - MsgType: peering.FirstUserMsgCode + 17, - MsgData: []byte{1, 2, 3, 4, 5}, + var src, dst *peering.PeerMessageNet + src = &peering.PeerMessageNet{ + PeerMessageData: peering.PeerMessageData{ + PeeringID: peering.RandomPeeringID(), + MsgReceiver: byte(10), + MsgType: peering.FirstUserMsgCode + 17, + MsgData: []byte{1, 2, 3, 4, 5}, + }, } var bin []byte - bin, err = src.Bytes(&nodeIdentity) + bin, err = src.Bytes() require.Nil(t, err) require.NotNil(t, bin) - dst, err = peering.NewPeerMessageFromBytes(bin, &nodeIdentity.PublicKey) + dst, err = peering.NewPeerMessageNetFromBytes(bin) require.Nil(t, err) require.NotNil(t, dst) require.EqualValues(t, src.PeeringID, dst.PeeringID) - require.Equal(t, src.SenderIndex, dst.SenderIndex) - require.Equal(t, src.Timestamp, dst.Timestamp) - require.Equal(t, src.MsgType, dst.MsgType) - require.True(t, bytes.Equal(src.MsgData, dst.MsgData)) -} - -func TestPeerMessageChunks(t *testing.T) { - var err error - var src, dst *peering.PeerMessage - nodeIdentity := ed25519.GenerateKeyPair() - chunkSize := 100 - chp := chopper.NewChopper() - data := make([]byte, 2013) - for i := range data { - data[i] = byte(rand.Intn(255)) - } - src = &peering.PeerMessage{ - PeeringID: peering.RandomPeeringID(), - SenderIndex: uint16(123), - Timestamp: time.Now().UnixNano(), - MsgType: peering.FirstUserMsgCode + 17, - MsgData: data, - } - var chunks [][]byte - chunks, err = src.ChunkedBytes(chunkSize, chp, &nodeIdentity) - require.Nil(t, err) - require.NotNil(t, chunks) - require.True(t, len(chunks) > 1) - for i := range chunks { - var chunkMsg *peering.PeerMessage - chunkMsg, err = peering.NewPeerMessageFromBytes(chunks[i], &nodeIdentity.PublicKey) - require.Nil(t, err) - require.Equal(t, peering.MsgTypeMsgChunk, chunkMsg.MsgType) - dst, err = peering.NewPeerMessageFromChunks(chunkMsg.MsgData, chunkSize, chp, &nodeIdentity.PublicKey) - require.Nil(t, err) - if i == len(chunks)-1 { - require.NotNil(t, dst) - } else { - require.Nil(t, dst) - } - } - require.EqualValues(t, src.PeeringID, dst.PeeringID) - require.Equal(t, src.SenderIndex, dst.SenderIndex) - require.Equal(t, src.Timestamp, dst.Timestamp) + require.Equal(t, src.MsgReceiver, dst.MsgReceiver) require.Equal(t, src.MsgType, dst.MsgType) require.True(t, bytes.Equal(src.MsgData, dst.MsgData)) } diff --git a/packages/peering/tcp/constants.go b/packages/peering/tcp/constants.go deleted file mode 100644 index 88d2366aec..0000000000 --- a/packages/peering/tcp/constants.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package tcp - -import "time" - -const ( - msgTypeReserved = byte(0) - msgTypeHandshake = byte(1) - msgTypeMsgChunk = byte(2) - - restartAfter = 1 * time.Second - dialTimeout = 1 * time.Second - dialRetries = 10 - backoffDelay = 500 * time.Millisecond -) diff --git a/packages/peering/tcp/doc.go b/packages/peering/tcp/doc.go deleted file mode 100644 index 6a08de2eea..0000000000 --- a/packages/peering/tcp/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -// Package tcp provides a TCP based implementation of the -// peering overlay network. -// -package tcp diff --git a/packages/peering/tcp/encode.go b/packages/peering/tcp/encode.go deleted file mode 100644 index 4c0e1b9ce2..0000000000 --- a/packages/peering/tcp/encode.go +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package tcp - -import ( - "bytes" - "fmt" - "log" - - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/wasp/packages/peering" - "github.com/iotaledger/wasp/packages/util" -) - -// structure of the encoded PeerMessage: -// OutputTimestamp 8 bytes -// MsgType type 1 byte -// -- if MsgType == 0 (heartbeat) --> the end of message -// -- if MsgType == 1 (handshake) -// MsgData (handshakeMsg) --> end of message -// -- if MsgType >= FirstUserMsgCode -// PeeringID 32 bytes -// SenderIndex 2 bytes -// MsgData variable bytes to the end -// -- otherwise panic wrong MsgType - -const chunkMessageOverhead = 8 + 1 - -// always puts timestamp into first 8 bytes and 1 byte msg type -func encodeMessage(msg *peering.PeerMessage, ts int64) []byte { - var buf bytes.Buffer - // puts timestamp first - _ = util.WriteUint64(&buf, uint64(ts)) - switch { - case msg == nil: - panic("msgTypeReserved") - - case msg.MsgType == msgTypeReserved: - panic("msgTypeReserved") - - case msg.MsgType == msgTypeHandshake: - buf.WriteByte(msgTypeHandshake) - buf.Write(msg.MsgData) - - case msg.MsgType == msgTypeMsgChunk: - buf.WriteByte(msgTypeMsgChunk) - buf.Write(msg.MsgData) - - case msg.MsgType >= peering.FirstUserMsgCode: - buf.WriteByte(msg.MsgType) - //TODO should these errors be checked? - //nolint:errcheck - msg.PeeringID.Write(&buf) - //nolint:errcheck - util.WriteUint16(&buf, msg.SenderIndex) - //nolint:errcheck - util.WriteBytes32(&buf, msg.MsgData) - - default: - log.Panicf("wrong msg type %d", msg.MsgType) - } - return buf.Bytes() -} - -func decodeMessage(data []byte) (*peering.PeerMessage, error) { - if len(data) < 9 { - return nil, fmt.Errorf("too short message") - } - rdr := bytes.NewBuffer(data) - var uts uint64 - err := util.ReadUint64(rdr, &uts) - if err != nil { - return nil, err - } - ret := &peering.PeerMessage{ - Timestamp: int64(uts), - } - ret.MsgType, err = util.ReadByte(rdr) - if err != nil { - return nil, err - } - switch { - case ret.MsgType == msgTypeHandshake: - ret.MsgData = rdr.Bytes() - return ret, nil - - case ret.MsgType == msgTypeMsgChunk: - ret.MsgData = rdr.Bytes() - return ret, nil - - case ret.MsgType >= peering.FirstUserMsgCode: - // committee message - if err := ret.PeeringID.Read(rdr); err != nil { - return nil, err - } - if err := util.ReadUint16(rdr, &ret.SenderIndex); err != nil { - return nil, err - } - if ret.MsgData, err = util.ReadBytes32(rdr); err != nil { - return nil, err - } - return ret, nil - - default: - return nil, fmt.Errorf("peering.decodeMessage.wrong message type: %d", ret.MsgType) - } -} - -type handshakeMsg struct { - peeringID string // Pair of peer NetIDs - srcNetID string // Their NetID - pubKey ed25519.PublicKey // Our PubKey. -} - -func (m *handshakeMsg) bytes() ([]byte, error) { - var buf bytes.Buffer - if err := util.WriteString16(&buf, m.peeringID); err != nil { - return nil, err - } - if err := util.WriteString16(&buf, m.srcNetID); err != nil { - return nil, err - } - if err := util.WriteBytes16(&buf, m.pubKey.Bytes()); err != nil { - return nil, err - } - return buf.Bytes(), nil -} - -func handshakeMsgFromBytes(buf []byte) (*handshakeMsg, error) { - var err error - r := bytes.NewReader(buf) - m := handshakeMsg{} - if m.peeringID, err = util.ReadString16(r); err != nil { - return nil, err - } - if m.srcNetID, err = util.ReadString16(r); err != nil { - return nil, err - } - var pubKeyBytes []byte - if pubKeyBytes, err = util.ReadBytes16(r); err != nil { - return nil, err - } - if m.pubKey, _, err = ed25519.PublicKeyFromBytes(pubKeyBytes); err != nil { - return nil, err - } - return &m, nil -} diff --git a/packages/peering/tcp/netImpl.go b/packages/peering/tcp/netImpl.go deleted file mode 100644 index b158e15bfd..0000000000 --- a/packages/peering/tcp/netImpl.go +++ /dev/null @@ -1,235 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package tcp - -import ( - "errors" - "sync" - "time" - - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/hive.go/events" - "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/wasp/packages/peering" - "github.com/iotaledger/wasp/packages/peering/domain" - "github.com/iotaledger/wasp/packages/peering/group" -) - -// NetImpl implements a peering.NetworkProvider interface. -type NetImpl struct { - myNetID string // NetID of this node. - port int // Port to use for peering. - - peers map[string]*peer - peersMutex *sync.RWMutex - events *events.Event - - nodeKeyPair *ed25519.KeyPair - log *logger.Logger -} - -// NewNetworkProvider is a constructor for the TCP based -// peering network implementation. -func NewNetworkProvider(myNetID string, port int, nodeKeyPair *ed25519.KeyPair, log *logger.Logger) (*NetImpl, error) { - if err := peering.CheckMyNetID(myNetID, port); err != nil { - // can't continue because NetID parameter is not correct - log.Panicf("checkMyNetworkID: '%v'. || Check the 'netid' parameter in config.json", err) - return nil, err - } - n := NetImpl{ - myNetID: myNetID, - port: port, - peers: make(map[string]*peer), - peersMutex: &sync.RWMutex{}, - nodeKeyPair: nodeKeyPair, - log: log, - } - n.events = events.NewEvent(n.eventHandler) - return &n, nil -} - -// A handler suitable for events.NewEvent(). -func (n *NetImpl) eventHandler(handler interface{}, params ...interface{}) { - callback := handler.(func(_ *peering.RecvEvent)) - recvEvent := params[0].(*peering.RecvEvent) - callback(recvEvent) -} - -// Run starts listening and communicating with the network. -func (n *NetImpl) Run(shutdownSignal <-chan struct{}) { - go n.connectOutboundLoop() - go n.connectInboundLoop() - - <-shutdownSignal - - n.log.Info("Closing all connections with peers...") - n.closeAll() - n.log.Info("Closing all connections with peers... done") -} - -// Self implements peering.NetworkProvider. -func (n *NetImpl) Self() peering.PeerSender { - return n -} - -// Group implements peering.NetworkProvider. -func (n *NetImpl) PeerGroup(peerNetIDs []string) (peering.GroupProvider, error) { - var err error - peers := make([]peering.PeerSender, len(peerNetIDs)) - for i := range peerNetIDs { - if peers[i], err = n.PeerByNetID(peerNetIDs[i]); err != nil { - return nil, err - } - } - return group.NewPeeringGroupProvider(n, peers, n.log) -} - -// Domain creates peering.PeerDomainProvider. -func (n *NetImpl) PeerDomain(peerNetIDs []string) (peering.PeerDomainProvider, error) { - return domain.NewPeerDomainByNetIDs(n, peerNetIDs, n.log) -} - -// Attach implements peering.NetworkProvider. -func (n *NetImpl) Attach(peeringID *peering.PeeringID, callback func(recv *peering.RecvEvent)) interface{} { - closure := events.NewClosure(func(recv *peering.RecvEvent) { - if peeringID == nil || *peeringID == recv.Msg.PeeringID { - callback(recv) - } - }) - n.events.Attach(closure) - return closure -} - -// Detach implements peering.NetworkProvider. -func (n *NetImpl) Detach(attachID interface{}) { - switch closure := attachID.(type) { - case *events.Closure: - n.events.Detach(closure) - default: - panic("invalid_attach_id") - } -} - -// PeerByNetID implements peering.NetworkProvider. -func (n *NetImpl) PeerByNetID(peerNetID string) (peering.PeerSender, error) { - if p := n.usePeer(peerNetID); p != nil { - return p, nil - } - return n, nil // Self -} - -// 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) { - for i := range n.peers { - pk := n.peers[i].PubKey() - if pk != nil && *pk == *peerPub { - return n.PeerByNetID(n.peers[i].NetID()) - } - } - return nil, errors.New("known peer not found by pubKey") -} - -// PeerStatus implements peering.NetworkProvider. -func (n *NetImpl) PeerStatus() []peering.PeerStatusProvider { - peerStatus := make([]peering.PeerStatusProvider, 0) - for i := range n.peers { - peerStatus = append(peerStatus, n.peers[i]) - } - return peerStatus -} - -// NetID implements peering.PeerSender for the Self() node. -func (n *NetImpl) NetID() string { - return n.myNetID -} - -// PubKey implements peering.PeerSender for the Self() node. -func (n *NetImpl) PubKey() *ed25519.PublicKey { - return &n.nodeKeyPair.PublicKey -} - -// SendMsg implements peering.PeerSender for the Self() node. -func (n *NetImpl) SendMsg(msg *peering.PeerMessage) { - // Don't go via the network, if sending a message to self. - n.events.Trigger(&peering.RecvEvent{ - From: n.Self(), - Msg: msg, - }) -} - -// IsAlive implements peering.PeerSender for the Self() node. -func (n *NetImpl) IsAlive() bool { - return true // This node is alive. -} - -// Await implements peering.PeerSender for the Self() node. -func (n *NetImpl) Await(timeout time.Duration) error { - return nil // This node is alive. -} - -// Close implements peering.PeerSender for the Self() node. -func (n *NetImpl) Close() { - // We will con close the connection of the own node. -} - -func (n *NetImpl) isInbound(remoteNetID string) bool { - // if remoteNetID == n.myNetID { // TODO: [KP] Do we need this? - // panic("remoteNetID == myNetID") - // } - return remoteNetID < n.myNetID -} - -// That's a name of the pairing, equal on both ends. -func (n *NetImpl) peeringID(remoteNetID string) string { - if n.isInbound(remoteNetID) { - return remoteNetID + "<" + n.myNetID - } - return n.myNetID + "<" + remoteNetID -} - -// usePeer adds new connection to the peer pool -// if it already exists, returns existing. -// Return nil for for own netID -// connection added to the pool is picked by loops which will try to establish connection -func (n *NetImpl) usePeer(netID string) *peer { - if netID == n.myNetID { - // nil for itself - return nil // TODO: [KP] return self - } - n.peersMutex.Lock() - defer n.peersMutex.Unlock() - - if peer, ok := n.peers[n.peeringID(netID)]; ok { - // existing peer - peer.numUsers++ - return peer - } - // new peer - ret := newPeer(netID, n) - n.peers[ret.peeringID()] = ret - n.log.Debugf("added new peer id %s", ret.peeringID()) - return ret -} - -// stopUsingPeer decreases counter. -func (n *NetImpl) stopUsingPeer(peerID string) { - n.peersMutex.Lock() - defer n.peersMutex.Unlock() - - if peer, ok := n.peers[peerID]; ok { - peer.numUsers-- - if peer.numUsers == 0 { - peer.isDismissed.Store(true) - - go func() { - n.peersMutex.Lock() - defer n.peersMutex.Unlock() - - delete(n.peers, peerID) - peer.closeConn() - }() - } - } -} diff --git a/packages/peering/tcp/netImpl_test.go b/packages/peering/tcp/netImpl_test.go deleted file mode 100644 index 47b6de5ad7..0000000000 --- a/packages/peering/tcp/netImpl_test.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package tcp_test - -import ( - "testing" - "time" - - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/wasp/packages/peering" - "github.com/iotaledger/wasp/packages/peering/tcp" - "github.com/iotaledger/wasp/packages/testutil/testlogger" - "github.com/stretchr/testify/require" -) - -func TestBasic(t *testing.T) { - log := testlogger.NewLogger(t) - defer log.Sync() - var err0, err1, err2 error - doneCh := make(chan bool) - netIDs := []string{"localhost:9017", "localhost:9018", "localhost:9019"} - nodeIdentities := []ed25519.KeyPair{ - ed25519.GenerateKeyPair(), - ed25519.GenerateKeyPair(), - ed25519.GenerateKeyPair(), - } - nodes := make([]peering.NetworkProvider, len(netIDs)) - nodes[0], err0 = tcp.NewNetworkProvider(netIDs[0], 9017, &nodeIdentities[0], log.Named("node0")) - nodes[1], err1 = tcp.NewNetworkProvider(netIDs[1], 9018, &nodeIdentities[1], log.Named("node1")) - nodes[2], err2 = tcp.NewNetworkProvider(netIDs[2], 9019, &nodeIdentities[2], log.Named("node2")) - require.Nil(t, err0) - require.Nil(t, err1) - require.Nil(t, err2) - for i := range nodes { - go nodes[i].Run(make(<-chan struct{})) - } - - <-time.After(time.Second) // TODO: [KP] Temporary. - - n0p2, _ := nodes[0].PeerByNetID(netIDs[2]) - n1p1, _ := nodes[1].PeerByNetID(netIDs[1]) - n2p0, _ := nodes[2].PeerByNetID(netIDs[0]) - - <-time.After(time.Second) // TODO: [KP] Temporary. - - nodes[0].Attach(nil, func(recv *peering.RecvEvent) { - doneCh <- true - }) - - chain1 := peering.RandomPeeringID() - chain2 := peering.RandomPeeringID() - n0p2.SendMsg(&peering.PeerMessage{PeeringID: chain1, MsgType: 125}) - n1p1.SendMsg(&peering.PeerMessage{PeeringID: chain1, MsgType: 125}) - n2p0.SendMsg(&peering.PeerMessage{PeeringID: chain2, MsgType: 125}) - - <-doneCh -} diff --git a/packages/peering/tcp/peer.go b/packages/peering/tcp/peer.go deleted file mode 100644 index fa0e73612b..0000000000 --- a/packages/peering/tcp/peer.go +++ /dev/null @@ -1,292 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package tcp - -import ( - "errors" - "fmt" - "net" - "sync" - "time" - - "github.com/iotaledger/goshimmer/packages/tangle" - "github.com/iotaledger/hive.go/backoff" - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/wasp/packages/peering" - "go.uber.org/atomic" -) - -// retry net.Dial once, on fail after 0.5s -var dialRetryPolicy = backoff.ConstantBackOff(backoffDelay).With(backoff.MaxRetries(dialRetries)) // TODO: Global variables. - -// peer represents point-to-point TCP connection between two nodes and another -// it is used as transport for message exchange -// Another end is always using the same connection -// the peer takes care about exchanging heartbeat messages. -// It keeps last several received heartbeats as "lad" data to be able to calculate how synced/unsynced -// clocks of peer are. -type peer struct { - *sync.RWMutex - isDismissed atomic.Bool // to be GC-ed - peerconn *peeredConnection // nil means not connected - handshakeOk bool - - remoteNetID string // network locations as taken from the SC data - remotePubKey *ed25519.PublicKey - - startOnce *sync.Once - waitReady *sync.WaitGroup - numUsers int - net *NetImpl - log *logger.Logger -} - -func newPeer(remoteNetID string, netw *NetImpl) *peer { - var waitReady sync.WaitGroup - waitReady.Add(1) - return &peer{ - RWMutex: &sync.RWMutex{}, - remoteNetID: remoteNetID, - startOnce: &sync.Once{}, - waitReady: &waitReady, - numUsers: 1, - net: netw, - log: netw.log, - } -} - -// NetID implements peering.PeerSender and peering.PeerStatusProvider interfaces for the remote peers. -func (p *peer) NetID() string { - return p.remoteNetID -} - -// PubKey implements peering.PeerSender and peering.PeerStatusProvider interfaces for the remote peers. -func (p *peer) PubKey() *ed25519.PublicKey { - p.log.Infof("Waiting for connection to become ready to get %v peer's public key.", p.remoteNetID) - p.waitReady.Wait() - return p.remotePubKey -} - -// SendMsg implements peering.PeerSender interface for the remote peers. -func (p *peer) SendMsg(msg *peering.PeerMessage) { - if err := p.doSendMsg(msg); err != nil { - // Async sending, we should ignore the errors. - p.log.Warnf("Failed to send a message, reason: %v", err) - } -} - -// IsAlive implements peering.PeerSender and peering.PeerStatusProvider interfaces for the remote peers. -// Return true if is alive and average latencyRingBuf in nanosec. -func (p *peer) IsAlive() bool { - p.RLock() - defer p.RUnlock() - return p.peerconn != nil && p.handshakeOk -} - -// IsAlive implements peering.PeerSender interface for the remote peers. -func (p *peer) Await(timeout time.Duration) error { - p.waitReady.Wait() // TODO: Use other locking to consider the timeout. - return nil -} - -// IsInbound implements peering.PeerStatusProvider. -// It is used in the dashboard. -func (p *peer) IsInbound() bool { - return p.net.isInbound(p.remoteNetID) -} - -// IsInbound implements peering.PeerStatusProvider. -// It is used in the dashboard. -func (p *peer) NumUsers() int { - p.RLock() - defer p.RUnlock() - return p.numUsers -} - -// SendMsg implements peering.PeerSender interface for the remote peers. -func (p *peer) Close() { - p.net.stopUsingPeer(p.remoteNetID) -} - -func (p *peer) peeringID() string { - return p.net.peeringID(p.remoteNetID) -} - -//nolint:unused -func (p *peer) connStatus() (bool, bool) { - p.RLock() - defer p.RUnlock() - if p.isDismissed.Load() { - return false, false - } - return p.peerconn != nil, p.handshakeOk -} - -func (p *peer) closeConn() { - p.Lock() - defer p.Unlock() - - if p.isDismissed.Load() { - return - } - if p.peerconn != nil { - _ = p.peerconn.Close() - } -} - -// dials outbound address and established connection -func (p *peer) runOutbound() { - log := p.net.log - if p.isDismissed.Load() { - return - } - if p.IsInbound() { - return - } - if p.peerconn != nil { - panic("peer.peerconn != nil") - } - log.Debugf("runOutbound %s", p.remoteNetID) - - // always try to reconnect - defer func() { - go func() { - time.Sleep(restartAfter) - p.Lock() - if !p.isDismissed.Load() { - p.startOnce = &sync.Once{} - log.Debugf("will run again: %s", p.peeringID()) - } - p.Unlock() - }() - }() - - var conn net.Conn - - if err := backoff.Retry(dialRetryPolicy, func() error { - var err error - conn, err = net.DialTimeout("tcp", p.remoteNetID, dialTimeout) - if err != nil { - return fmt.Errorf("dial %s failed: %w", p.remoteNetID, err) - } - return nil - }); err != nil { - log.Warn(err) - return - } - p.peerconn = newPeeredConnection(conn, p.net, p) - if err := p.sendHandshake(); err != nil { - log.Errorf("error during sendHandshake: %v", err) - return - } - log.Infof("starting reading outbound %s", p.remoteNetID) - err := p.peerconn.Read() - log.Errorw("stopped reading outbound. Closing", "remote", p.remoteNetID, "err", err) - p.closeConn() -} - -// sends handshake message. It contains myNetID -func (p *peer) sendHandshake() error { - var err error - msg := handshakeMsg{ - peeringID: p.peeringID(), - srcNetID: p.net.Self().NetID(), - pubKey: p.net.nodeKeyPair.PublicKey, - } - var msgData []byte - if msgData, err = msg.bytes(); err != nil { - return err - } - data := encodeMessage(&peering.PeerMessage{ - MsgType: msgTypeHandshake, - MsgData: msgData, - }, time.Now().UnixNano()) - _, err = p.peerconn.Write(data) - p.net.log.Debugf("sendHandshake '%s' --> '%s', id = %s", p.net.myNetID, p.remoteNetID, p.peeringID()) - return err -} - -func (p *peer) doSendMsg(msg *peering.PeerMessage) error { - if msg.MsgType < peering.FirstUserMsgCode { - return errors.New("reserved message code") - } - ts := msg.Timestamp - if ts == 0 { - ts = time.Now().UnixNano() - } - data := encodeMessage(msg, ts) - - choppedData, chopped, err := p.peerconn.msgChopper.ChopData(data, tangle.MaxMessageSize, chunkMessageOverhead) - if err != nil { - return err - } - - p.RLock() - defer p.RUnlock() - - if !chopped { - return p.sendData(data) - } - return p.sendChunks(choppedData) -} - -func (p *peer) sendChunks(chopped [][]byte) error { - ts := time.Now().UnixNano() - for _, piece := range chopped { - d := encodeMessage(&peering.PeerMessage{ - MsgType: msgTypeMsgChunk, - MsgData: piece, - }, ts) - if err := p.sendData(d); err != nil { - return err - } - } - return nil -} - -// SendMsgToPeers sends same msg to all peers in the slice which are not nil -// with the same timestamp -// return number of successfully sent messages and timestamp -func SendMsgToPeers(msg *peering.PeerMessage, ts int64, peers ...*peer) uint16 { // TODO: [KP] Remove, unused. - if msg.MsgType < peering.FirstUserMsgCode { - return 0 - } - // timestamped here, once - data := encodeMessage(msg, ts) - - numSent := uint16(0) - for _, peer := range peers { - if peer == nil { - continue - } - peer.RLock() - choppedData, chopped, err := peer.peerconn.msgChopper.ChopData(data, tangle.MaxMessageSize, chunkMessageOverhead) - if err != nil { - return 0 - } - if !chopped { - if err := peer.sendData(data); err == nil { - numSent++ - } - } else { - if err := peer.sendChunks(choppedData); err == nil { - numSent++ - } - } - peer.RUnlock() - } - return numSent -} - -func (p *peer) sendData(data []byte) error { - if p.peerconn == nil { - return fmt.Errorf("no connection with %s", p.remoteNetID) - } - num, err := p.peerconn.Write(data) - if num != len(data) { - return fmt.Errorf("not all bytes were written. err = %v", err) - } - return nil -} diff --git a/packages/peering/tcp/peeredconn.go b/packages/peering/tcp/peeredconn.go deleted file mode 100644 index 56e091f630..0000000000 --- a/packages/peering/tcp/peeredconn.go +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package tcp - -import ( - "net" - - "github.com/iotaledger/goshimmer/packages/tangle" - "github.com/iotaledger/goshimmer/packages/txstream/chopper" - "github.com/iotaledger/hive.go/events" - "github.com/iotaledger/hive.go/netutil/buffconn" - "github.com/iotaledger/wasp/packages/peering" -) - -// extension of BufferedConnection from hive.go -// BufferedConnection is a wrapper for net.Conn -// peeredConnection first handles handshake and then links -// with peer according to the handshake information -type peeredConnection struct { - *buffconn.BufferedConnection - peer *peer - net *NetImpl - msgChopper *chopper.Chopper - handshakeOk bool //nolint:structcheck,unused -} - -// creates new peered connection and attach event handlers for received data and closing -func newPeeredConnection(conn net.Conn, netw *NetImpl, peer *peer) *peeredConnection { - c := &peeredConnection{ - BufferedConnection: buffconn.NewBufferedConnection(conn, tangle.MaxMessageSize), - peer: peer, // may be nil - net: netw, - msgChopper: chopper.NewChopper(), - } - c.Events.ReceiveMessage.Attach(events.NewClosure(func(data []byte) { - c.receiveData(data) - })) - c.Events.Close.Attach(events.NewClosure(func() { - if c.peer != nil { - c.peer.Lock() - c.peer.peerconn = nil - c.peer.handshakeOk = false - c.peer.Unlock() - } - netw.log.Debugw("closed buff connection", "conn", conn.RemoteAddr().String()) - })) - return c -} - -// receive data handler for peered connection -func (c *peeredConnection) receiveData(data []byte) { - msg, err := decodeMessage(data) - if err != nil { - // gross violation of the protocol - c.net.log.Errorf("!!!!! peeredConnection.receiveData.decodeMessage: %v", err) - c.Close() - return - } - if msg.MsgType == peering.MsgTypeMsgChunk { - finalMsg, err := c.msgChopper.IncomingChunk(msg.MsgData, tangle.MaxMessageSize, chunkMessageOverhead) - if err != nil { - c.net.log.Errorf("peeredConnection.receiveData: %v", err) - return - } - if finalMsg != nil { - c.receiveData(finalMsg) - } - } - if c.peer != nil { - // it is peered but maybe not handshaked yet (can only be outbound) - if c.peer.handshakeOk { - // it is handshake-ed - msg.SenderNetID = c.peer.NetID() - c.net.events.Trigger(&peering.RecvEvent{ - From: c.peer, - Msg: msg, - }) - } else { - // expected handshake msg - if msg.MsgType != peering.MsgTypeHandshake { - c.net.log.Errorf("peeredConnection.receiveData: unexpected message during handshake 1") - return - } - // not handshaked => do handshake - c.processHandShakeOutbound(msg) - } - } else { - // can only be inbound - // expected handshake msg - if msg.MsgType != peering.MsgTypeHandshake { - c.net.log.Errorf("peeredConnection.receiveData: unexpected message during handshake 2") - return - } - // not peered yet can be only inbound - // peer up and do handshake - c.processHandShakeInbound(msg) - } -} - -// receives handshake response from the outbound peer -// assumes the connection is already peered (i can be only for outbound peers) -func (c *peeredConnection) processHandShakeOutbound(msg *peering.PeerMessage) { - var err error - var hMsg *handshakeMsg - if hMsg, err = handshakeMsgFromBytes(msg.MsgData); err != nil { - c.net.log.Errorf( - "closeConn the peer connection: wrong handshake message from outbound peer %v, error: %v", - c.peer.peeringID(), err, - ) - panic(err) - } - c.net.log.Debugf("received handshake from outbound %s", hMsg.peeringID) - if hMsg.peeringID != c.peer.peeringID() { - c.net.log.Errorf( - "closeConn the peer connection: wrong handshake message from outbound peer: expected %s got '%s'", - c.peer.peeringID(), hMsg.peeringID, - ) - if c.peer != nil { - // may ne be peered yet - c.peer.closeConn() - } - } else { - c.net.log.Infof("CONNECTED WITH PEER %s (outbound)", hMsg.peeringID) - c.peer.remotePubKey = &hMsg.pubKey - c.peer.handshakeOk = true - c.peer.waitReady.Done() - } -} - -// receives handshake from the inbound peer -// links connection with the peer -// sends response back to finish the handshake -func (c *peeredConnection) processHandShakeInbound(msg *peering.PeerMessage) { - var err error - var hMsg *handshakeMsg - if hMsg, err = handshakeMsgFromBytes(msg.MsgData); err != nil { - c.net.log.Errorf( - "closeConn the peer connection: wrong handshake message from outbound peer %v, error: %v", - c.peer.peeringID(), err, - ) - panic(err) - } - - c.net.log.Infof("received handshake from inbound id = %s, peers=%+v", hMsg.peeringID, c.net.peers) - - c.net.peersMutex.RLock() - peer, ok := c.net.peers[hMsg.peeringID] - c.net.peersMutex.RUnlock() - - if !ok || !peer.IsInbound() { - c.net.log.Warnf("inbound connection from unexpected peer id %s. Closing..", hMsg.peeringID) - _ = c.Close() - return - } - c.peer = peer - - peer.Lock() - peer.peerconn = c - peer.remotePubKey = &hMsg.pubKey - peer.handshakeOk = true - peer.waitReady.Done() - peer.Unlock() - - c.net.log.Infof("CONNECTED WITH PEER %s (inbound)", hMsg.peeringID) - - if err := peer.sendHandshake(); err != nil { - c.net.log.Errorf("error while responding to handshake: %v. Closing connection", err) - _ = c.Close() - } -} diff --git a/packages/peering/tcp/peerpool.go b/packages/peering/tcp/peerpool.go deleted file mode 100644 index 6ebf2d7e26..0000000000 --- a/packages/peering/tcp/peerpool.go +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package tcp - -import ( - "fmt" - "io" - "net" - "strings" - "time" - - "github.com/iotaledger/wasp/plugins/gracefulshutdown" -) - -//nolint:unused -func (n *NetImpl) iteratePeers(f func(p *peer)) { - n.peersMutex.Lock() - defer n.peersMutex.Unlock() - - for _, peer := range n.peers { - if !peer.isDismissed.Load() { - f(peer) - } - } -} - -func (n *NetImpl) closeAll() { - n.peersMutex.Lock() - defer n.peersMutex.Unlock() - - for _, cconn := range n.peers { - cconn.closeConn() - } -} - -// loop which maintains outbound peers connected (if possible) -func (n *NetImpl) connectOutboundLoop() { - for { - time.Sleep(100 * time.Millisecond) - n.peersMutex.Lock() - for _, c := range n.peers { - c.startOnce.Do(func() { - go c.runOutbound() - }) - } - n.peersMutex.Unlock() - } -} - -// loop which maintains inbound peers connected (when possible) -func (n *NetImpl) connectInboundLoop() { - listenOn := fmt.Sprintf(":%d", n.port) - listener, err := net.Listen("tcp", listenOn) - if err != nil { - n.log.Errorf("tcp listen on %s failed: %v. Shutting down...", listenOn, err) - gracefulshutdown.Shutdown() // TODO: Move it to the plugin. - - //log.Errorf("tcp listen on %s failed: %v. Restarting connectInboundLoop after 1 sec", listenOn, err) - //go func() { - // time.Sleep(1 * time.Second) - // connectInboundLoop() - //}() - return - } - n.log.Infof("tcp listen inbound on %s", listenOn) - for { - conn, err := listener.Accept() - if err != nil { - n.log.Errorf("failed accepting a connection request: %v", err) - continue - } - n.log.Debugf("accepted connection from %s", conn.RemoteAddr().String()) - - // peer is not known yet - bconn := newPeeredConnection(conn, n, nil) - go func() { - n.log.Debugf("starting reading inbound %s", conn.RemoteAddr().String()) - err := bconn.Read() - n.log.Debugw("stopped reading inbound. Closing", "remote", conn.RemoteAddr(), "err", err) - - //if err := bconn.Read(); err != nil { - // if permanentBufConnReadingError(err) { - // n.log.Warnf("Permanent error reading inbound %s: %v", conn.RemoteAddr().String(), err) - // } - //} - _ = bconn.Close() - }() - } -} - -// for testing -//nolint:unused -func (n *NetImpl) countConnectionsLoop() { - var totalNum, inboundNum, outboundNum, inConnectedNum, outConnectedNum, inHSNum, outHSNum int - for { - time.Sleep(2 * time.Second) - totalNum, inboundNum, outboundNum, inConnectedNum, outConnectedNum, inHSNum, outHSNum = 0, 0, 0, 0, 0, 0, 0 - n.peersMutex.Lock() - for _, c := range n.peers { - totalNum++ - isConn, isHandshaken := c.connStatus() - if c.IsInbound() { - inboundNum++ - if isConn { - inConnectedNum++ - } - if isHandshaken { - inHSNum++ - } - } else { - outboundNum++ - if isConn { - outConnectedNum++ - } - if isHandshaken { - outHSNum++ - } - } - } - n.peersMutex.Unlock() - n.log.Debugf("CONN STATUS: total conn: %d, in: %d, out: %d, inConnected: %d, outConnected: %d, inHS: %d, outHS: %d", - totalNum, inboundNum, outboundNum, inConnectedNum, outConnectedNum, inHSNum, outHSNum) - } -} - -//nolint:unused,deadcode -func permanentBufConnReadingError(err error) bool { - if err == io.EOF { - return false - } - if strings.Contains(err.Error(), "use of closed network connection") { - return false - } - if strings.Contains(err.Error(), "invalid message header") { - // someone with wrong protocol - return false - } - return true -} diff --git a/packages/peering/trusted_peer.go b/packages/peering/trusted_peer.go new file mode 100644 index 0000000000..31e446ac4e --- /dev/null +++ b/packages/peering/trusted_peer.go @@ -0,0 +1,57 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// Package peering provides an overlay network for communicating +// between nodes in a peer-to-peer style with low overhead +// encoding and persistent connections. The network provides only +// the asynchronous communication. +// +// It is intended to use for the committee consensus protocol. +// +package peering + +import ( + "bytes" + + "github.com/iotaledger/hive.go/crypto/ed25519" + "github.com/iotaledger/wasp/packages/util" +) + +// TrustedPeer carries a peer information we use to trust it. +type TrustedPeer struct { + PubKey ed25519.PublicKey + NetID string +} + +func TrustedPeerFromBytes(buf []byte) (*TrustedPeer, error) { + var err error + r := bytes.NewBuffer(buf) + tp := TrustedPeer{} + var keyBytes []byte + if keyBytes, err = util.ReadBytes16(r); err != nil { + return nil, err + } + tp.PubKey, _, err = ed25519.PublicKeyFromBytes(keyBytes) + if err != nil { + return nil, err + } + if tp.NetID, err = util.ReadString16(r); err != nil { + return nil, err + } + return &tp, nil +} + +func (tp *TrustedPeer) Bytes() ([]byte, error) { + var buf bytes.Buffer + if err := util.WriteBytes16(&buf, tp.PubKey.Bytes()); err != nil { + return nil, err + } + if err := util.WriteString16(&buf, tp.NetID); err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +func (tp *TrustedPeer) PubKeyBytes() ([]byte, error) { + return tp.PubKey.Bytes(), nil +} diff --git a/packages/peering/udp/udpHandshake.go b/packages/peering/udp/udpHandshake.go deleted file mode 100644 index c460bd7d3d..0000000000 --- a/packages/peering/udp/udpHandshake.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package udp - -import ( - "bytes" - - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/wasp/packages/util" - "golang.org/x/xerrors" -) - -type handshakeMsg struct { - netID string // Their NetID - pubKey ed25519.PublicKey // Our PubKey. - respond bool // Do the message asks for a response? -} - -//nolint: gocritic -func (m *handshakeMsg) bytes(secKey ed25519.PrivateKey) ([]byte, error) { - var err error - // - // Payload. - var payloadBuf bytes.Buffer - if err = util.WriteString16(&payloadBuf, m.netID); err != nil { - return nil, err - } - if err = util.WriteBytes16(&payloadBuf, m.pubKey.Bytes()); err != nil { - return nil, err - } - if err = util.WriteBoolByte(&payloadBuf, m.respond); err != nil { - return nil, err - } - // - // Signed frame. - payload := payloadBuf.Bytes() - signature := secKey.Sign(payload) - signedBuf := bytes.Buffer{} - if err = util.WriteBytes16(&signedBuf, signature.Bytes()); err != nil { - return nil, err - } - if err = util.WriteBytes16(&signedBuf, payload); err != nil { - return nil, err - } - return signedBuf.Bytes(), nil -} - -//nolint: gocritic -func handshakeMsgFromBytes(buf []byte) (*handshakeMsg, error) { - var err error - // - // Signed frame. - rSigned := bytes.NewReader(buf) - var payload []byte - var signatureBytes []byte - if signatureBytes, err = util.ReadBytes16(rSigned); err != nil { - return nil, err - } - if payload, err = util.ReadBytes16(rSigned); err != nil { - return nil, err - } - // - // Payload. - rPayload := bytes.NewReader(payload) - m := handshakeMsg{} - if m.netID, err = util.ReadString16(rPayload); err != nil { - return nil, err - } - var pubKeyBytes []byte - if pubKeyBytes, err = util.ReadBytes16(rPayload); err != nil { - return nil, err - } - if m.pubKey, _, err = ed25519.PublicKeyFromBytes(pubKeyBytes); err != nil { - return nil, err - } - if err = util.ReadBoolByte(rPayload, &m.respond); err != nil { - return nil, err - } - // - // Verify the signature. - var signature ed25519.Signature - if signature, _, err = ed25519.SignatureFromBytes(signatureBytes); err != nil { - return nil, err - } - if !m.pubKey.VerifySignature(payload, signature) { - return nil, xerrors.New("invalid message signature") - } - return &m, nil -} diff --git a/packages/peering/udp/udpHandshake_test.go b/packages/peering/udp/udpHandshake_test.go deleted file mode 100644 index bbb5b055b2..0000000000 --- a/packages/peering/udp/udpHandshake_test.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package udp - -import ( - "net" - "testing" - - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/stretchr/testify/require" -) - -func TestHandshakeCodec(t *testing.T) { - var err error - pair := ed25519.GenerateKeyPair() - a := handshakeMsg{ - netID: "some", - pubKey: pair.PublicKey, - respond: true, - } - var buf []byte - buf, err = a.bytes(pair.PrivateKey) - require.Nil(t, err) - require.NotNil(t, buf) - // - // Correct message. - var b *handshakeMsg - b, err = handshakeMsgFromBytes(buf) - require.Nil(t, err) - require.NotNil(t, b) - require.Equal(t, a.netID, b.netID) - require.Equal(t, a.pubKey, b.pubKey) - require.Equal(t, a.respond, b.respond) - // - // Damaged message. - buf[2]++ - var c *handshakeMsg - c, err = handshakeMsgFromBytes(buf) - require.NotNil(t, err) - require.Nil(t, c) -} - -func TestUDPAddrString(t *testing.T) { - var err error - var addr *net.UDPAddr - addr, err = net.ResolveUDPAddr("udp", "localhost:1248") - require.Nil(t, err) - require.Equal(t, "127.0.0.1:1248", addr.String()) -} diff --git a/packages/peering/udp/udpNetImpl.go b/packages/peering/udp/udpNetImpl.go deleted file mode 100644 index af99b5624a..0000000000 --- a/packages/peering/udp/udpNetImpl.go +++ /dev/null @@ -1,426 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -// Package udp implements a UDP based peering.NetworkProvider. -package udp - -import ( - "errors" - "net" - "os" - "sync" - "time" - - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/hive.go/events" - "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/wasp/packages/peering" - "github.com/iotaledger/wasp/packages/peering/domain" - "github.com/iotaledger/wasp/packages/peering/group" -) - -const ( - maintenancePeriod = 1 * time.Second - recvQueueSize = 1024 * 5 - recvBlockingDuration = 3 * time.Second -) - -// NetImpl implements a peering.NetworkProvider interface. -type NetImpl struct { - myNetID string // NetID of this node. - myUDPConn *net.UDPConn - port int // Port to use for peering. - peers map[string]*peer // By NetID - peersByAddr map[string]*peer // By UDPAddr.String() - peersLock *sync.RWMutex - recvEvents *events.Event - recvQueue chan *peering.RecvEvent // A queue for received messages. - nodeKeyPair *ed25519.KeyPair - trusted peering.TrustedNetworkManager - log *logger.Logger -} - -// NewNetworkProvider is a constructor for the TCP based -// peering network implementation. -func NewNetworkProvider( - myNetID string, - port int, - nodeKeyPair *ed25519.KeyPair, - trusted peering.TrustedNetworkManager, - log *logger.Logger, -) (*NetImpl, error) { - var err error - var myUDPConn *net.UDPConn - if myUDPConn, err = net.ListenUDP("udp", &net.UDPAddr{Port: port}); err != nil { - return nil, err - } - n := NetImpl{ - myNetID: myNetID, - myUDPConn: myUDPConn, - port: port, - peers: make(map[string]*peer), - peersByAddr: make(map[string]*peer), - peersLock: &sync.RWMutex{}, - recvEvents: nil, // Initialized bellow. - recvQueue: make(chan *peering.RecvEvent, recvQueueSize), - nodeKeyPair: nodeKeyPair, - trusted: trusted, - log: log, - } - n.recvEvents = events.NewEvent(n.eventHandler) - return &n, nil -} - -// A handler suitable for events.NewEvent(). -func (n *NetImpl) eventHandler(handler interface{}, params ...interface{}) { - callback := handler.(func(_ *peering.RecvEvent)) - recvEvent := params[0].(*peering.RecvEvent) - callback(recvEvent) -} - -// Run starts listening and communicating with the network. -func (n *NetImpl) Run(shutdownSignal <-chan struct{}) { - queueRecvStopCh := make(chan bool) - receiveStopCh := make(chan bool) - maintenanceStopCh := make(chan bool) - go n.queueRecvLoop(queueRecvStopCh) - go n.receiveLoop(receiveStopCh) - go n.maintenanceLoop(maintenanceStopCh) - - <-shutdownSignal - close(maintenanceStopCh) - close(receiveStopCh) - close(queueRecvStopCh) -} - -// Self implements peering.NetworkProvider. -func (n *NetImpl) Self() peering.PeerSender { - return n -} - -// Group creates peering.GroupProvider. -func (n *NetImpl) PeerGroup(peerNetIDs []string) (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 { - return nil, err - } - } - return group.NewPeeringGroupProvider(n, groupPeers, n.log) -} - -// Domain creates peering.PeerDomainProvider. -func (n *NetImpl) PeerDomain(peerNetIDs []string) (peering.PeerDomainProvider, error) { - peers := make([]peering.PeerSender, 0, len(peerNetIDs)) - for _, nid := range peerNetIDs { - if nid == n.Self().NetID() { - continue - } - p, err := n.usePeer(nid) - if err != nil { - return nil, err - } - peers = append(peers, p) - } - return domain.NewPeerDomain(n, peers, n.log), nil -} - -// Attach implements peering.NetworkProvider. -func (n *NetImpl) Attach(peeringID *peering.PeeringID, callback func(recv *peering.RecvEvent)) interface{} { - closure := events.NewClosure(func(recv *peering.RecvEvent) { - if peeringID == nil || *peeringID == recv.Msg.PeeringID { - callback(recv) - } - }) - n.recvEvents.Attach(closure) - return closure -} - -// Detach implements peering.NetworkProvider. -func (n *NetImpl) Detach(attachID interface{}) { - switch closure := attachID.(type) { - case *events.Closure: - n.recvEvents.Detach(closure) - default: - panic("invalid_attach_id") - } -} - -// 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") -} - -// PeerStatus implements peering.NetworkProvider. -func (n *NetImpl) PeerStatus() []peering.PeerStatusProvider { - n.peersLock.RLock() - defer n.peersLock.RUnlock() - peerStatus := make([]peering.PeerStatusProvider, 0) - for i := range n.peers { - peerStatus = append(peerStatus, n.peers[i]) - } - return peerStatus -} - -// NetID implements peering.PeerSender for the Self() node. -func (n *NetImpl) NetID() string { - return n.myNetID -} - -// PubKey implements peering.PeerSender for the Self() node. -func (n *NetImpl) PubKey() *ed25519.PublicKey { - return &n.nodeKeyPair.PublicKey -} - -// SendMsg implements peering.PeerSender for the Self() node. -func (n *NetImpl) SendMsg(msg *peering.PeerMessage) { - // Don't go via the network, if sending a message to self. - n.recvQueue <- &peering.RecvEvent{ - From: n.Self(), - Msg: msg, - } -} - -// IsAlive implements peering.PeerSender for the Self() node. -func (n *NetImpl) IsAlive() bool { - return true // This node is alive. -} - -// Await implements peering.PeerSender for the Self() node. -func (n *NetImpl) Await(timeout time.Duration) error { - return nil // This node is alive immediately. -} - -// Close implements peering.PeerSender for the Self() node. -func (n *NetImpl) Close() { - // We will con close the connection of the own node. -} - -// IsTrustedPeer implements the peering.TrustedNetworkManager interface. -func (n *NetImpl) IsTrustedPeer(pubKey ed25519.PublicKey) error { - return n.trusted.IsTrustedPeer(pubKey) -} - -// TrustPeer implements the peering.TrustedNetworkManager interface. -// It delegates everything to other implementation and updates the connections accordingly. -func (n *NetImpl) TrustPeer(pubKey ed25519.PublicKey, netID string) (*peering.TrustedPeer, error) { - n.peersLock.Lock() - for _, peer := range n.peers { - peerPubKey := peer.remotePubKey - if peerPubKey != nil && *peerPubKey == pubKey { - peer.trust(true) - } - } - n.peersLock.Unlock() - return n.trusted.TrustPeer(pubKey, netID) -} - -// DistrustPeer implements the peering.TrustedNetworkManager interface. -// It delegates everything to other implementation and updates the connections accordingly. -func (n *NetImpl) DistrustPeer(pubKey ed25519.PublicKey) (*peering.TrustedPeer, error) { - n.peersLock.Lock() - for _, peer := range n.peers { - peerPubKey := peer.remotePubKey - if peerPubKey != nil && *peerPubKey == pubKey { - peer.trust(false) - } - } - n.peersLock.Unlock() - return n.trusted.DistrustPeer(pubKey) -} - -// TrustedPeers implements the peering.TrustedNetworkManager interface. -func (n *NetImpl) TrustedPeers() ([]*peering.TrustedPeer, error) { - return n.trusted.TrustedPeers() -} - -func (n *NetImpl) usePeer(remoteNetID string) (peering.PeerSender, error) { - var err error - if remoteNetID == n.myNetID { - return n, nil - } - n.peersLock.Lock() - defer n.peersLock.Unlock() - if p, ok := n.peers[remoteNetID]; ok { - p.usePeer() - return p, nil - } - var p *peer - if p, err = newPeerOnUserRequest(remoteNetID, n); err != nil { - return nil, err - } - n.peers[p.NetID()] = p - n.peersByAddr[p.remoteUDPAddr.String()] = p - return p, nil -} - -func (n *NetImpl) queueRecvLoop(stopCh chan bool) { - for { - select { - case <-stopCh: - return - case recvEvent, ok := <-n.recvQueue: - if ok { - n.recvEvents.Trigger(recvEvent) - } - } - } -} - -func (n *NetImpl) receiveLoop(stopCh chan bool) { - var err error - buf := make([]byte, 2024) - for { - select { // Terminate the loop, if such request has been made. - case <-stopCh: - return - default: - } - var peerUDPAddr *net.UDPAddr - recvDeadline := time.Now().Add(recvBlockingDuration) - if err := n.myUDPConn.SetReadDeadline(recvDeadline); err != nil { - n.log.Warnf("Error while setting UDP read timeout, %v", err) - time.Sleep(1 * time.Second) // To avoid too frequent retries. - continue - } - if _, peerUDPAddr, err = n.myUDPConn.ReadFromUDP(buf); err != nil { - if errors.Is(err, os.ErrDeadlineExceeded) { - // We need to limit the blocking to make graceful stop possible. - continue - } - n.log.Warnf("Error while reading from UDP socket, reason=%v", err) - continue - } - var peerPubKey *ed25519.PublicKey - n.peersLock.RLock() - if p, ok := n.peersByAddr[peerUDPAddr.String()]; ok { - if !p.isTrusted() { - n.peersLock.RUnlock() - n.log.Debugf("Dropping message from untrusted peer: %v.", p.NetID()) - continue - } - // We will only find the pub key, if the session is already established. - // The pub key is here needed only for user messages, so the handshake can proceed with nil. - peerPubKey = p.remotePubKey // Do not use PubKey() here, has it waits for it to be set. - } - n.peersLock.RUnlock() - var peerMsg *peering.PeerMessage - if peerMsg, err = peering.NewPeerMessageFromBytes(buf, peerPubKey); err != nil { - n.log.Warnf("Error while decoding a UDP message, reason=%v", err) - continue - } - switch peerMsg.MsgType { - case peering.MsgTypeReserved: - // Nothing - case peering.MsgTypeHandshake: - n.receiveHandshake(peerMsg, peerUDPAddr) - case peering.MsgTypeMsgChunk: - n.receiveMsgChunk(peerMsg, peerUDPAddr) - default: - n.receiveUserMsg(peerMsg, peerUDPAddr) - } - } -} - -func (n *NetImpl) receiveHandshake(peerMsg *peering.PeerMessage, peerUDPAddr *net.UDPAddr) { - var err error - var h *handshakeMsg - if h, err = handshakeMsgFromBytes(peerMsg.MsgData); err != nil { - n.log.Warnf("Error while decoding a UDP handshake, reason=%v", err) - return - } - if err = n.trusted.IsTrustedPeer(h.pubKey); err != nil { - n.log.Warnf("Dropping handshakeMsg from %v with pubKey=%v, error=%v", peerUDPAddr, h.pubKey, err) - return - } - n.peersLock.Lock() - if p, ok := n.peers[h.netID]; ok { - if oldUDPAddrStr, newUDPAddrStr := p.handleHandshake(h, peerUDPAddr); oldUDPAddrStr != newUDPAddrStr { - // Update the index to find the peer later on. - n.peersByAddr[newUDPAddrStr] = p - delete(n.peersByAddr, oldUDPAddrStr) - } - } else { - if p, err = newPeerFromHandshake(h, peerUDPAddr, n); err != nil { - n.log.Warnf("Error while creating a peer based on UDP handshake, reason=%v", err) - n.peersLock.Unlock() - return - } - n.peers[p.NetID()] = p - n.peersByAddr[p.remoteUDPAddr.String()] = p - } - n.peersLock.Unlock() -} - -func (n *NetImpl) receiveMsgChunk(peerMsg *peering.PeerMessage, peerUDPAddr *net.UDPAddr) { - var err error - remoteUDPAddrStr := peerUDPAddr.String() - n.peersLock.RLock() - if p, ok := n.peersByAddr[remoteUDPAddrStr]; ok { - n.peersLock.RUnlock() - var reconstructedMsg *peering.PeerMessage - if reconstructedMsg, err = peering.NewPeerMessageFromChunks(peerMsg.MsgData, maxChunkSize, p.msgChopper, p.remotePubKey); err != nil { - n.log.Warnf("Error while decoding chunked message, reason=%v", err) - return - } - if reconstructedMsg != nil { - n.receiveUserMsg(reconstructedMsg, peerUDPAddr) - } - } else { - n.peersLock.RUnlock() - n.log.Warnf("Dropping received message from unknown peer=%v", remoteUDPAddrStr) - return - } -} - -func (n *NetImpl) receiveUserMsg(msg *peering.PeerMessage, peerUDPAddr *net.UDPAddr) { - if !msg.IsUserMessage() { - n.log.Warnf("Dropping received message, unexpected MsgType=%v", msg.MsgType) - return - } - remoteUDPAddrStr := peerUDPAddr.String() - - n.peersLock.RLock() - if p, ok := n.peersByAddr[remoteUDPAddrStr]; ok { - n.peersLock.RUnlock() - p.noteReceived() - msg.SenderNetID = p.NetID() - n.recvQueue <- &peering.RecvEvent{ - From: p, - Msg: msg, - } - return - } - n.peersLock.RUnlock() - n.log.Warnf("Dropping received message from unknown peer=%v", remoteUDPAddrStr) -} - -func (n *NetImpl) maintenanceLoop(stopCh chan bool) { - for { - select { - case <-time.After(maintenancePeriod): - n.peersLock.RLock() - for _, p := range n.peers { - p.maintenanceCheck() - } - n.peersLock.RUnlock() - case <-stopCh: - return - } - } -} diff --git a/packages/peering/udp/udpNetImpl_test.go b/packages/peering/udp/udpNetImpl_test.go deleted file mode 100644 index 737ae975f6..0000000000 --- a/packages/peering/udp/udpNetImpl_test.go +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package udp_test - -import ( - "testing" - - "github.com/iotaledger/hive.go/crypto/ed25519" - "github.com/iotaledger/wasp/packages/peering" - "github.com/iotaledger/wasp/packages/peering/udp" - "github.com/iotaledger/wasp/packages/testutil" - "github.com/iotaledger/wasp/packages/testutil/testlogger" - "github.com/stretchr/testify/require" - "go.dedis.ch/kyber/v3/group/edwards25519" - "go.dedis.ch/kyber/v3/sign/eddsa" - "go.dedis.ch/kyber/v3/sign/schnorr" - "go.dedis.ch/kyber/v3/util/key" -) - -func TestUDPPeeringImpl(t *testing.T) { - var err error - log := testlogger.NewLogger(t) - defer log.Sync() - - doneCh := make(chan bool) - netIDs := []string{"localhost:9017", "localhost:9018", "localhost:9019"} - nodes := make([]peering.NetworkProvider, len(netIDs)) - - keys := make([]ed25519.KeyPair, len(netIDs)) - tnms := make([]peering.TrustedNetworkManager, len(netIDs)) - for i := range keys { - keys[i] = ed25519.GenerateKeyPair() - tnms[i] = testutil.NewTrustedNetworkManager() - } - for _, tnm := range tnms { - for i := range netIDs { - _, err = tnm.TrustPeer(keys[i].PublicKey, netIDs[i]) - require.NoError(t, err) - } - } - nodes[0], err = udp.NewNetworkProvider(netIDs[0], 9017, &keys[0], tnms[0], log.Named("node0")) - require.NoError(t, err) - nodes[1], err = udp.NewNetworkProvider(netIDs[1], 9018, &keys[1], tnms[1], log.Named("node1")) - require.NoError(t, err) - nodes[2], err = udp.NewNetworkProvider(netIDs[2], 9019, &keys[2], tnms[2], log.Named("node2")) - require.NoError(t, err) - for i := range nodes { - go nodes[i].Run(make(<-chan struct{})) - } - - n0p2, err := nodes[0].PeerByNetID(netIDs[2]) - require.NoError(t, err) - n1p1, err := nodes[1].PeerByNetID(netIDs[1]) - require.NoError(t, err) - n2p0, err := nodes[2].PeerByNetID(netIDs[0]) - require.NoError(t, err) - - nodes[0].Attach(nil, func(recv *peering.RecvEvent) { - doneCh <- true - }) - - chain1 := peering.RandomPeeringID() - chain2 := peering.RandomPeeringID() - n0p2.SendMsg(&peering.PeerMessage{PeeringID: chain1, MsgType: 125}) - n1p1.SendMsg(&peering.PeerMessage{PeeringID: chain1, MsgType: 125}) - n2p0.SendMsg(&peering.PeerMessage{PeeringID: chain2, MsgType: 125}) - - <-doneCh -} - -// TestHiveKyberInterop checks, if hive keys can be used in kyber. -// ``` -// public, private, _ := hive.GenerateKey() -// var kyber eddsa.EdDSA -// kyber.UnmarshalBinary(private.Bytes()) -// kyberSig, _ := kyber.Sign(msg) -// hiveSig, _, _ := hive.SignatureFromBytes(kyberSig) -// public.VerifySignature(msg, hiveSig) -// ``` -func TestHiveKyberInterop(t *testing.T) { - var err error - hiveKeyPair := ed25519.GenerateKeyPair() - kyberSuite := edwards25519.NewBlakeSHA256Ed25519() - kyberEdDSSA := eddsa.EdDSA{} - require.NoError(t, kyberEdDSSA.UnmarshalBinary(hiveKeyPair.PrivateKey.Bytes())) - kyberKeyPair := &key.Pair{ - Public: kyberEdDSSA.Public, - Private: kyberEdDSSA.Secret, - } - // Check, if pub key can be unmarshalled directly. - kyberPubUnmarshaled := kyberSuite.Point() - require.NoError(t, kyberPubUnmarshaled.UnmarshalBinary(hiveKeyPair.PublicKey.Bytes())) - // - // Check signatures. - message := []byte{0, 1, 2} - // - // Hive-to-Hive - hiveSig := hiveKeyPair.PrivateKey.Sign(message) - require.True(t, hiveKeyPair.PublicKey.VerifySignature(message, hiveSig)) - // - // Kyber-to-Kyber - kyberSig, err := schnorr.Sign(kyberSuite, kyberKeyPair.Private, message) - require.NoError(t, err) - require.NoError(t, schnorr.Verify(kyberSuite, kyberKeyPair.Public, message, kyberSig)) - require.NoError(t, schnorr.Verify(kyberSuite, kyberPubUnmarshaled, message, kyberSig)) -} diff --git a/packages/peering/udp/udpPeer.go b/packages/peering/udp/udpPeer.go deleted file mode 100644 index fd3116557e..0000000000 --- a/packages/peering/udp/udpPeer.go +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package udp - -import ( - "errors" - "fmt" - "net" - "sync" - "time" - - "github.com/iotaledger/goshimmer/packages/txstream/chopper" - "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" -) - -const ( - inactiveDeadline = 1 * time.Minute - inactivePingTime = 30 * time.Second - sendMsgSyncTimeout = 3 * time.Second - - maxChunkSize = 508 // Safe payload size for UDP. -) - -type peer struct { - remoteNetID string - remotePubKey *ed25519.PublicKey - remoteUDPAddr *net.UDPAddr - waitReady *util.WaitChan - accessLock *sync.RWMutex - lastMsgSent time.Time - lastMsgRecv time.Time - numUsers int - trusted bool - msgChopper *chopper.Chopper - net *NetImpl - log *logger.Logger -} - -func newPeerOnUserRequest(remoteNetID string, n *NetImpl) (*peer, error) { - var err error - var remoteUDPAddr *net.UDPAddr - if remoteUDPAddr, err = net.ResolveUDPAddr("udp", remoteNetID); err != nil { - return nil, err - } - p := newPeer(remoteNetID, remoteUDPAddr, n) - p.usePeer() - return p, nil -} - -func newPeerFromHandshake(handshake *handshakeMsg, remoteUDPAddr *net.UDPAddr, n *NetImpl) (*peer, error) { - p := newPeer(handshake.netID, remoteUDPAddr, n) - if oldUDPAddrStr, newUDPAddrStr := p.handleHandshake(handshake, remoteUDPAddr); oldUDPAddrStr != newUDPAddrStr { - return nil, errors.New("inconsistent_udp_addr_on_create") - } - return p, nil -} - -// That's internal, called from other constructors. -func newPeer(remoteNetID string, remoteUDPAddr *net.UDPAddr, n *NetImpl) *peer { - log := n.log.Named("peer:" + remoteNetID) - p := &peer{ - remoteNetID: remoteNetID, - remotePubKey: nil, // Will be set on the handshake. - remoteUDPAddr: remoteUDPAddr, - waitReady: util.NewWaitChan(), - accessLock: &sync.RWMutex{}, - lastMsgSent: time.Time{}, - lastMsgRecv: time.Time{}, - numUsers: 0, - trusted: true, - msgChopper: chopper.NewChopper(), - net: n, - log: log, - } - p.sendHandshake(true) - return p -} - -func (p *peer) usePeer() { - p.accessLock.Lock() - defer p.accessLock.Unlock() - p.numUsers++ -} - -func (p *peer) handleHandshake(handshake *handshakeMsg, remoteUDPAddr *net.UDPAddr) (string, string) { - p.accessLock.Lock() - oldUDPAddrStr := p.remoteUDPAddr.String() - newUDPAddrStr := remoteUDPAddr.String() - if oldUDPAddrStr != newUDPAddrStr { - p.log.Warnf("Remote UDPAddr has changed, old=%v, new=%v", oldUDPAddrStr, newUDPAddrStr) - p.remoteUDPAddr = remoteUDPAddr - } - if p.remotePubKey == nil { - // That's the first received handshake, pairing established. - p.remotePubKey = &handshake.pubKey - p.waitReady.Done() - p.log.Infof("Node %v is now paired with %v", p.net.NetID(), p.remoteNetID) - } else if p.remotePubKey != nil && *p.remotePubKey == handshake.pubKey { - // It's just a ping. - } else { - // New PublicKey is used by the peer! - if *p.remotePubKey != handshake.pubKey { - p.log.Warnf("Remote PubKey has changed, old=%v, new=%v", p.remotePubKey, handshake.pubKey) - } - p.remotePubKey = &handshake.pubKey - } - p.lastMsgRecv = time.Now() - p.accessLock.Unlock() - if handshake.respond { - // Respond to the handshake, if asked. - p.sendHandshake(false) - } - return oldUDPAddrStr, newUDPAddrStr -} - -func (p *peer) sendHandshake(respond bool) { - var err error - handshake := handshakeMsg{ - netID: p.net.NetID(), - pubKey: *p.net.PubKey(), - respond: respond, - } - var msgDataBin []byte - if msgDataBin, err = handshake.bytes(p.net.nodeKeyPair.PrivateKey); err != nil { - p.log.Errorf("Unable to encode outgoing handshake msg, reason=%v", err) - } - p.SendMsg(&peering.PeerMessage{ - Timestamp: time.Now().UnixNano(), - MsgType: peering.MsgTypeHandshake, - MsgData: msgDataBin, - }) -} - -func (p *peer) noteReceived() { - p.accessLock.Lock() - defer p.accessLock.Unlock() - - p.lastMsgRecv = time.Now() -} - -// Send pings, if needed. Other periodic actions can be added here. -func (p *peer) maintenanceCheck() { - now := time.Now() - old := now.Add(-inactivePingTime) - p.accessLock.RLock() - if p.numUsers > 0 && p.lastMsgRecv.Before(old) { - p.accessLock.RUnlock() - p.sendHandshake(true) - } else { - p.accessLock.RUnlock() - // if p.numUsers == 0 && p.lastMsgRecv.Before(old) { - // TODO: Do a peer cleanup. - // } - } -} - -// NetID implements peering.PeerSender and peering.PeerStatusProvider interfaces for the remote peers. -func (p *peer) NetID() string { - p.accessLock.RLock() - defer p.accessLock.RUnlock() - return p.remoteNetID -} - -// PubKey implements peering.PeerSender and peering.PeerStatusProvider interfaces for the remote peers. -// This function tries to await for the public key to be resolves for some time, but with no guarantees. -func (p *peer) PubKey() *ed25519.PublicKey { - _ = p.waitReady.WaitTimeout(sendMsgSyncTimeout) - p.accessLock.RLock() - defer p.accessLock.RUnlock() - return p.remotePubKey -} - -// SendMsg implements peering.PeerSender interface for the remote peers. -func (p *peer) SendMsg(msg *peering.PeerMessage) { - var err error - var msgChunks [][]byte - // - p.accessLock.RLock() - if !p.trusted { - p.log.Infof("Dropping outgoing message, because it was meant to send to a distrusted peer.") - p.accessLock.RUnlock() - } - p.accessLock.RUnlock() - // - if msg.IsUserMessage() { - if !p.waitReady.WaitTimeout(sendMsgSyncTimeout) { - // Just log a warning and try to send a message anyway. - p.log.Warnf("Sending a message despite the peering %v -> %v is not established yet, MsgType=%v", p.net.myNetID, p.NetID(), msg.MsgType) - } - } - if msgChunks, err = msg.ChunkedBytes(maxChunkSize, p.msgChopper, p.net.nodeKeyPair); err != nil { - p.log.Warnf("Dropping outgoing message, unable to encode, reason=%v", err) - return - } - for i := range msgChunks { - var n int - if n, err = p.net.myUDPConn.WriteTo(msgChunks[i], p.remoteUDPAddr); err != nil { - p.log.Warnf("Dropping outgoing message, unable to send, reason=%v", err) - return - } - if n != len(msgChunks[i]) { - p.log.Warnf("Partial message sent, sent=%v, msgBin=%v", n, len(msgChunks[i])) - return - } - } - - p.accessLock.Lock() - defer p.accessLock.Unlock() - p.lastMsgSent = time.Now() -} - -// IsAlive implements peering.PeerSender and peering.PeerStatusProvider interfaces for the remote peers. -// Return true if is alive and average latencyRingBuf in nanosec. -func (p *peer) IsAlive() bool { - p.accessLock.RLock() - defer p.accessLock.RUnlock() - return p.remotePubKey != nil && p.lastMsgRecv.After(time.Now().Add(-inactiveDeadline)) -} - -// Await implements peering.PeerSender interface for the remote peers. -func (p *peer) Await(timeout time.Duration) error { - if p.waitReady.WaitTimeout(timeout) { - return nil - } - return fmt.Errorf("timeout waiting for %v to become ready", p.remoteNetID) -} - -// IsInbound implements peering.PeerStatusProvider. -// It is used in the dashboard. -func (p *peer) IsInbound() bool { - p.accessLock.RLock() - defer p.accessLock.RUnlock() - return p.remoteNetID < p.net.myNetID -} - -// IsInbound implements peering.PeerStatusProvider. -// It is used in the dashboard. -func (p *peer) NumUsers() int { - p.accessLock.RLock() - defer p.accessLock.RUnlock() - return p.numUsers -} - -// SendMsg implements peering.PeerSender interface for the remote peers. -func (p *peer) Close() { - p.accessLock.Lock() - defer p.accessLock.Unlock() - p.numUsers-- -} - -func (p *peer) trust(trusted bool) { - p.accessLock.Lock() - defer p.accessLock.Unlock() - p.trusted = trusted -} - -func (p *peer) isTrusted() bool { - p.accessLock.RLock() - defer p.accessLock.RUnlock() - return p.trusted -} diff --git a/packages/solo/fun.go b/packages/solo/fun.go index d13e3b7ad0..6d1c65ec23 100644 --- a/packages/solo/fun.go +++ b/packages/solo/fun.go @@ -241,9 +241,14 @@ func (ch *Chain) GetWasmBinary(progHash hashing.HashValue) ([]byte, error) { // - it can be a hash (ID) of the example smart contract ("hardcoded"). The "hardcoded" // smart contract must be made available with the call examples.AddProcessor func (ch *Chain) DeployContract(keyPair *ed25519.KeyPair, name string, programHash hashing.HashValue, params ...interface{}) error { - par := []interface{}{root.ParamProgramHash, programHash, root.ParamName, name} - par = append(par, params...) - req := NewCallParams(root.Contract.Name, root.FuncDeployContract.Name, par...).WithIotas(1) + par := codec.MakeDict(map[string]interface{}{ + root.ParamProgramHash: programHash, + root.ParamName: name, + }) + for k, v := range parseParams(params) { + par[k] = v + } + req := NewCallParams(root.Contract.Name, root.FuncDeployContract.Name, par).WithIotas(1) _, err := ch.PostRequestSync(req, keyPair) return err } diff --git a/packages/solo/req.go b/packages/solo/req.go index 257e73be87..6f1cf0ac9f 100644 --- a/packages/solo/req.go +++ b/packages/solo/req.go @@ -101,8 +101,8 @@ func (r *CallParams) WithMint(targetAddress ledgerstate.Address, amount uint64) } // NewRequestOffLedger creates off-ledger request from parameters -func (r *CallParams) NewRequestOffLedger(keyPair *ed25519.KeyPair) *request.OffLedger { - ret := request.NewOffLedger(r.target, r.entryPoint, r.args).WithTransfer(r.transfer) +func (r *CallParams) NewRequestOffLedger(chainID *iscp.ChainID, keyPair *ed25519.KeyPair) *request.OffLedger { + ret := request.NewOffLedger(chainID, r.target, r.entryPoint, r.args).WithTransfer(r.transfer) ret.Sign(keyPair) return ret } @@ -212,7 +212,7 @@ func (ch *Chain) PostRequestOffLedger(req *CallParams, keyPair *ed25519.KeyPair) if keyPair == nil { keyPair = ch.OriginatorKeyPair } - r := req.NewRequestOffLedger(keyPair) + r := req.NewRequestOffLedger(ch.ChainID, keyPair) res, err := ch.runRequestsSync([]iscp.Request{r}, "off-ledger") if err != nil { return nil, err @@ -278,10 +278,9 @@ func (ch *Chain) CallView(scName, funName string, params ...interface{}) (dict.D return vctx.CallView(iscp.Hn(scName), iscp.Hn(funName), p) } -// WaitForRequestsThrough waits for the moment when counters for incoming requests and removed -// requests in the mempool of the chain both become equal to the specified number -func (ch *Chain) WaitForRequestsThrough(numReq int, maxWait ...time.Duration) bool { - maxw := 5 * time.Second +// WaitUntil waits until the condition specified by the given predicate yields true +func (ch *Chain) WaitUntil(p func(chain.MempoolInfo) bool, maxWait ...time.Duration) bool { + maxw := 10 * time.Second var deadline time.Time if len(maxWait) > 0 { maxw = maxWait[0] @@ -289,18 +288,25 @@ func (ch *Chain) WaitForRequestsThrough(numReq int, maxWait ...time.Duration) bo deadline = time.Now().Add(maxw) for { mstats := ch.mempool.Info() - if mstats.InBufCounter == numReq && mstats.OutPoolCounter == numReq { + if p(mstats) { return true } if time.Now().After(deadline) { - ch.Log.Errorf("WaitForRequestsThrough. failed waiting max %v for %d requests through . Current IN: %d, OUT: %d", - maxw, numReq, mstats.InBufCounter, mstats.OutPoolCounter) + ch.Log.Errorf("WaitUntil failed waiting max %v", maxw) return false } time.Sleep(10 * time.Millisecond) } } +// WaitForRequestsThrough waits for the moment when counters for incoming requests and removed +// requests in the mempool of the chain both become equal to the specified number +func (ch *Chain) WaitForRequestsThrough(numReq int, maxWait ...time.Duration) bool { + return ch.WaitUntil(func(mstats chain.MempoolInfo) bool { + return mstats.InBufCounter == numReq && mstats.OutPoolCounter == numReq + }, maxWait...) +} + // MempoolInfo returns stats about the chain mempool func (ch *Chain) MempoolInfo() chain.MempoolInfo { return ch.mempool.Info() diff --git a/packages/solo/solo.go b/packages/solo/solo.go index 1f0f1fdd34..b6607b1840 100644 --- a/packages/solo/solo.go +++ b/packages/solo/solo.go @@ -434,9 +434,17 @@ func (ch *Chain) collateBatch() []iscp.Request { // batchLoop mimics behavior Wasp consensus func (ch *Chain) batchLoop() { + for { + ch.Sync() + time.Sleep(50 * time.Millisecond) + } +} + +// Sync runs all ready requests +func (ch *Chain) Sync() { for { if !ch.collateAndRunBatch() { - time.Sleep(50 * time.Millisecond) + return } } } @@ -456,8 +464,8 @@ func (ch *Chain) collateAndRunBatch() bool { return false } -// backlogLen is a thread-safe function to return size of the current backlog -func (ch *Chain) backlogLen() int { //nolint:unused +// BacklogLen is a thread-safe function to return size of the current backlog +func (ch *Chain) BacklogLen() int { mstats := ch.mempool.Info() return mstats.InBufCounter - mstats.OutPoolCounter } diff --git a/packages/state/state.go b/packages/state/state.go index 8822e90c19..120a56cac7 100644 --- a/packages/state/state.go +++ b/packages/state/state.go @@ -48,10 +48,8 @@ func newVirtualState(db kvstore.KVStore, chainID *iscp.ChainID) *virtualStateAcc func newZeroVirtualState(db kvstore.KVStore, chainID *iscp.ChainID) (VirtualStateAccess, Block) { ret := newVirtualState(db, chainID) - originBlock, err := ret.applyOriginBlock() - if err != nil { - panic(err) - } + originBlock := newOriginBlock() + ret.applyBlockNoCheck(originBlock) _, _ = ret.ExtractBlock() // clear the update log return ret, originBlock } @@ -129,29 +127,22 @@ func (vs *virtualStateAccess) PreviousStateHash() hashing.HashValue { } // ApplyBlock applies a block of state updates. Checks consistency of the block and previous state. Updates state hash +// It is not suitible for applying origin block to empty virtual state. This is done in `newZeroVirtualState` func (vs *virtualStateAccess) ApplyBlock(b Block) error { - return vs.applyAnyBlock(b, false) -} - -func (vs *virtualStateAccess) applyOriginBlock() (Block, error) { - originBlock := newOriginBlock() - return originBlock, vs.applyAnyBlock(originBlock, true) -} - -func (vs *virtualStateAccess) applyAnyBlock(b Block, empty bool) error { - if empty && b.BlockIndex() != 0 { - return xerrors.Errorf("ApplyBlock: b state index #%d can't be applied to the empty state", b.BlockIndex()) - } - if !empty && vs.BlockIndex()+1 != b.BlockIndex() { + if vs.BlockIndex()+1 != b.BlockIndex() { return xerrors.Errorf("ApplyBlock: b state index #%d can't be applied to the state with index #%d", b.BlockIndex(), vs.BlockIndex()) } - if !empty && vs.Timestamp().After(b.Timestamp()) { + if vs.Timestamp().After(b.Timestamp()) { return xerrors.New("ApplyBlock: inconsistent timestamps") } + vs.applyBlockNoCheck(b) + return nil +} + +func (vs *virtualStateAccess) applyBlockNoCheck(b Block) { vs.ApplyStateUpdates(b.(*blockImpl).stateUpdate) vs.appliedBlockHashes = append(vs.appliedBlockHashes, hashing.HashData(b.EssenceBytes())) - return nil } // ApplyStateUpdates applies one state update. Doesn't change the state hash: it can be changed by Apply block diff --git a/packages/state/state_test.go b/packages/state/state_test.go index 88649b57d4..babbac2c35 100644 --- a/packages/state/state_test.go +++ b/packages/state/state_test.go @@ -52,18 +52,11 @@ func TestOriginHashes(t *testing.T) { require.True(t, origBlock.Timestamp().IsZero()) require.EqualValues(t, hashing.NilHash, origBlock.PreviousStateHash()) t.Logf("zero state hash = %s", z.StateCommitment().String()) + require.EqualValues(t, 0, z.BlockIndex()) + require.True(t, z.Timestamp().IsZero()) + require.EqualValues(t, hashing.NilHash, z.PreviousStateHash()) require.EqualValues(t, calcOriginStateHash(), z.StateCommitment()) }) - t.Run("origin state construct", func(t *testing.T) { - emptyState := newVirtualState(mapdb.NewMapDB(), nil) - origBlock, err := emptyState.applyOriginBlock() - require.EqualValues(t, 0, origBlock.BlockIndex()) - require.True(t, origBlock.Timestamp().IsZero()) - require.EqualValues(t, hashing.NilHash, origBlock.PreviousStateHash()) - require.NoError(t, err) - require.EqualValues(t, emptyState.StateCommitment(), calcOriginStateHash()) - require.EqualValues(t, hashing.NilHash, emptyState.PreviousStateHash()) - }) } func TestStateWithDB(t *testing.T) { diff --git a/packages/testutil/dummyrequest.go b/packages/testutil/dummyrequest.go new file mode 100644 index 0000000000..1034ac6bdd --- /dev/null +++ b/packages/testutil/dummyrequest.go @@ -0,0 +1,19 @@ +package testutil + +import ( + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/iscp/request" + "github.com/iotaledger/wasp/packages/iscp/requestargs" + "github.com/iotaledger/wasp/packages/kv/dict" + "github.com/iotaledger/wasp/packages/testutil/testkey" +) + +func DummyOffledgerRequest(chainID *iscp.ChainID) *request.OffLedger { + contract := iscp.Hn("somecontract") + entrypoint := iscp.Hn("someentrypoint") + args := requestargs.New(dict.Dict{}) + req := request.NewOffLedger(chainID, contract, entrypoint, args) + keys, _ := testkey.GenKeyAddr() + req.Sign(keys) + return req +} diff --git a/packages/testutil/peeringNetBehaviour.go b/packages/testutil/peeringNetBehaviour.go index 8436a7f219..5e1f52fb8c 100644 --- a/packages/testutil/peeringNetBehaviour.go +++ b/packages/testutil/peeringNetBehaviour.go @@ -106,7 +106,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.netID, recv.msg.MsgType, dstNetID) + n.log.Debugf("Network dropped message %v -%v-> %v", recv.from, recv.msg.MsgType, dstNetID) continue // Drop the message. } // @@ -137,7 +137,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.netID, recv.msg.MsgType, dstNetID, dupNum, dupCount, delay.Milliseconds(), + recv.from, recv.msg.MsgType, dstNetID, dupNum, dupCount, delay.Milliseconds(), ) safeSendPeeringMsg(outCh, recv, n.log) } diff --git a/packages/testutil/peeringNetBehaviourDynamic.go b/packages/testutil/peeringNetBehaviourDynamic.go index cd4ccaeeeb..f3765d54c4 100644 --- a/packages/testutil/peeringNetBehaviourDynamic.go +++ b/packages/testutil/peeringNetBehaviourDynamic.go @@ -141,7 +141,7 @@ func (pndT *PeeringNetDynamic) recvLoop(inCh, outCh chan *peeringMsg, closeCh ch if len(nextHandlers) > 0 { nextHandlers[0].handleSendMessage(recv, dstNetID, nextHandlers[1:], callHandlersAndSendFun, pndT.log) } else { - pndT.log.Debugf("Network delivers message %v -%v-> %v", recv.from.netID, recv.msg.MsgType, dstNetID) + pndT.log.Debugf("Network delivers message %v -%v-> %v", recv.from, recv.msg.MsgType, dstNetID) safeSendPeeringMsg(outCh, recv, pndT.log) } } @@ -170,7 +170,7 @@ func (lcT *peeringNetDynamicHandlerLosingChannel) handleSendMessage( log *logger.Logger, ) { if rand.Intn(100) > lcT.probability { - log.Debugf("Network dropped message %v -%v-> %v", msg.from.netID, msg.msg.MsgType, dstNetID) + log.Debugf("Network dropped message %v -%v-> %v", msg.from, msg.msg.MsgType, dstNetID) return } callHandlersAndSendFun(nextHandlers) @@ -191,7 +191,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.netID, msg.msg.MsgType, dstNetID, numRepeat) + log.Debugf("Network repeated message %v -%v-> %v %v times", msg.from, msg.msg.MsgType, dstNetID, numRepeat) for i := 0; i < numRepeat; i++ { callHandlersAndSendFun(nextHandlers) } @@ -219,7 +219,7 @@ func (dcT *peeringNetDynamicHandlerDelayingChannel) handleSendMessage( } else { delay = time.Duration(fromMS) * time.Millisecond } - log.Debugf("Network delayed message %v -%v-> %v for %v", msg.from.netID, msg.msg.MsgType, dstNetID, delay) + log.Debugf("Network delayed message %v -%v-> %v for %v", msg.from, msg.msg.MsgType, dstNetID, delay) <-time.After(delay) } callHandlersAndSendFun(nextHandlers) @@ -238,11 +238,11 @@ func (pdT *peeringNetDynamicHandlerPeerDisconnected) handleSendMessage( log *logger.Logger, ) { if dstNetID == pdT.peerName { - log.Debugf("Network dropped message %v -%v-> %v, because destination is disconnected", msg.from.netID, msg.msg.MsgType, dstNetID) + log.Debugf("Network dropped message %v -%v-> %v, because destination is disconnected", msg.from, msg.msg.MsgType, dstNetID) return } - if msg.from.netID == pdT.peerName { - log.Debugf("Network dropped message %v -%v-> %v, because source is disconnected", msg.from.netID, msg.msg.MsgType, dstNetID) + if msg.from == pdT.peerName { + log.Debugf("Network dropped message %v -%v-> %v, because source is disconnected", msg.from, msg.msg.MsgType, dstNetID) return } callHandlersAndSendFun(nextHandlers) diff --git a/packages/testutil/peeringNetBehaviourDynamic_test.go b/packages/testutil/peeringNetBehaviourDynamic_test.go index 1eeb92fe07..c54c10a920 100644 --- a/packages/testutil/peeringNetBehaviourDynamic_test.go +++ b/packages/testutil/peeringNetBehaviourDynamic_test.go @@ -8,7 +8,6 @@ import ( "time" "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/testutil/testlogger" "github.com/stretchr/testify/require" ) @@ -242,7 +241,7 @@ func testRecvLoop(outCh chan *peeringMsg, durations *[]time.Duration, stopCh cha case <-stopCh: return case msg := <-outCh: - *durations = append(*durations, time.Since(time.Unix(0, msg.msg.Timestamp))) + *durations = append(*durations, time.Since(time.Unix(0, msg.timestamp))) } } } @@ -257,9 +256,7 @@ func averageDuration(durations []time.Duration) int64 { func sendMessage(from *peeringNode, inCh chan *peeringMsg) { inCh <- &peeringMsg{ - from: from, - msg: peering.PeerMessage{ - Timestamp: time.Now().UnixNano(), - }, + from: from.netID, + timestamp: time.Now().UnixNano(), } } diff --git a/packages/testutil/peeringNetBehaviour_test.go b/packages/testutil/peeringNetBehaviour_test.go index 17b47a44a4..bd50d544a3 100644 --- a/packages/testutil/peeringNetBehaviour_test.go +++ b/packages/testutil/peeringNetBehaviour_test.go @@ -26,7 +26,7 @@ func TestPeeringNetReliable(t *testing.T) { behavior := NewPeeringNetReliable(testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)) behavior.AddLink(inCh, outCh, "dst") for i := 0; i < 10; i++ { - inCh <- &peeringMsg{from: &someNode} + inCh <- &peeringMsg{from: someNode.netID} } <-doneCh behavior.Close() @@ -58,7 +58,7 @@ func TestPeeringNetUnreliable(t *testing.T) { behavior := NewPeeringNetUnreliable(50, 50, 50*time.Millisecond, 100*time.Millisecond, testlogger.WithLevel(testlogger.NewLogger(t), logger.LevelError, false)) behavior.AddLink(inCh, outCh, "dst") for i := 0; i < 1000; i++ { - inCh <- &peeringMsg{from: &someNode} + inCh <- &peeringMsg{from: someNode.netID} } time.Sleep(500 * time.Millisecond) // @@ -106,7 +106,7 @@ func TestPeeringNetGoodQuality(t *testing.T) { 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") for i := 0; i < 1000; i++ { - inCh <- &peeringMsg{from: &someNode} + inCh <- &peeringMsg{from: someNode.netID} } time.Sleep(500 * time.Millisecond) // diff --git a/packages/testutil/peeringNetworkProvider.go b/packages/testutil/peeringNetworkProvider.go index 8c2211860d..2ad8e92466 100644 --- a/packages/testutil/peeringNetworkProvider.go +++ b/packages/testutil/peeringNetworkProvider.go @@ -108,14 +108,16 @@ type peeringNode struct { } type peeringMsg struct { - from *peeringNode - msg peering.PeerMessage + from string + msg peering.PeerMessageData + timestamp int64 } type peeringCb struct { - callback func(recv *peering.RecvEvent) // Receive callback. - destNP *peeringNetworkProvider // Destination node. - peeringID *peering.PeeringID // Only listen for specific chain msgs. + callback func(recv *peering.PeerMessageIn) // Receive callback. + destNP *peeringNetworkProvider // Destination node. + peeringID *peering.PeeringID // Only listen for specific chain msgs. + receiver byte } func newPeeringNode(netID string, identity *ed25519.KeyPair, network *PeeringNetwork) *peeringNode { @@ -140,17 +142,17 @@ func (n *peeringNode) recvLoop() { for pm := range n.recvCh { msgPeeringID := pm.msg.PeeringID.String() for _, cb := range n.recvCbs { - if cb.peeringID == nil || cb.peeringID.String() == msgPeeringID { - cb.callback(&peering.RecvEvent{ - From: cb.destNP.senderByNetID(pm.from.netID), - Msg: &pm.msg, + if cb.peeringID.String() == msgPeeringID && cb.receiver == pm.msg.MsgReceiver { + cb.callback(&peering.PeerMessageIn{ + PeerMessageData: pm.msg, + SenderNetID: pm.from, }) } } } } -func (n *peeringNode) sendMsg(from *peeringNode, msg *peering.PeerMessage) { +func (n *peeringNode) sendMsg(from string, msg *peering.PeerMessageData) { n.sendCh <- &peeringMsg{ from: from, msg: *msg, @@ -171,6 +173,8 @@ type peeringNetworkProvider struct { senders []*peeringSender // Senders for all the nodes. } +var _ peering.NetworkProvider = &peeringNetworkProvider{} + // NewpeeringNetworkProvider initializes new network provider (a local view). func newPeeringNetworkProvider(self *peeringNode, network *PeeringNetwork) *peeringNetworkProvider { senders := make([]*peeringSender, len(network.nodes)) @@ -196,7 +200,7 @@ func (p *peeringNetworkProvider) Self() peering.PeerSender { } // Group implements peering.NetworkProvider. -func (p *peeringNetworkProvider) PeerGroup(peerAddrs []string) (peering.GroupProvider, error) { +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]) @@ -205,23 +209,25 @@ func (p *peeringNetworkProvider) PeerGroup(peerAddrs []string) (peering.GroupPro } peers[i] = p.senders[i] } - return group.NewPeeringGroupProvider(p, peers, p.network.log) + return group.NewPeeringGroupProvider(p, peeringID, peers, p.network.log) } // Domain creates peering.PeerDomainProvider. -func (p *peeringNetworkProvider) PeerDomain(peerNetIDs []string) (peering.PeerDomainProvider, error) { - return domain.NewPeerDomainByNetIDs(p, peerNetIDs, p.network.log) +func (p *peeringNetworkProvider) PeerDomain(peeringID peering.PeeringID, peerNetIDs []string) (peering.PeerDomainProvider, error) { + return domain.NewPeerDomainByNetIDs(p, peeringID, peerNetIDs, p.network.log) } // Attach implements peering.NetworkProvider. func (p *peeringNetworkProvider) Attach( peeringID *peering.PeeringID, - callback func(recv *peering.RecvEvent), + receiver byte, + callback func(recv *peering.PeerMessageIn), ) interface{} { p.self.recvCbs = append(p.self.recvCbs, &peeringCb{ callback: callback, destNP: p, peeringID: peeringID, + receiver: receiver, }) return nil // We don't care on the attachIDs for now. } @@ -231,6 +237,13 @@ 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) + if err == nil { + s.SendMsg(msg) + } +} + // PeerByNetID implements peering.NetworkProvider. func (p *peeringNetworkProvider) PeerByNetID(peerNetID string) (peering.PeerSender, error) { if s := p.senderByNetID(peerNetID); s != nil { @@ -276,6 +289,8 @@ type peeringSender struct { netProvider *peeringNetworkProvider } +var _ peering.PeerSender = &peeringSender{} + func newPeeringSender(node *peeringNode, netProvider *peeringNetworkProvider) *peeringSender { return &peeringSender{ node: node, @@ -294,8 +309,8 @@ func (p *peeringSender) PubKey() *ed25519.PublicKey { } // Send implements peering.PeerSender. -func (p *peeringSender) SendMsg(msg *peering.PeerMessage) { - p.node.sendMsg(p.netProvider.self, msg) +func (p *peeringSender) SendMsg(msg *peering.PeerMessageData) { + p.node.sendMsg(p.netProvider.self.netID, msg) } // IsAlive implements peering.PeerSender. diff --git a/packages/testutil/peeringNetworkProvider_test.go b/packages/testutil/peeringNetworkProvider_test.go index e1757086f0..47229ac676 100644 --- a/packages/testutil/peeringNetworkProvider_test.go +++ b/packages/testutil/peeringNetworkProvider_test.go @@ -19,11 +19,12 @@ func TestFakeNetwork(t *testing.T) { doneCh := make(chan bool) chain1 := peering.RandomPeeringID() chain2 := peering.RandomPeeringID() + receiver := byte(0) network := testutil.NewPeeringNetworkForLocs([]string{"a", "b", "c"}, 100, log) var netProviders []peering.NetworkProvider = network.NetworkProviders() // // Node "a" listens for chain1 messages. - netProviders[0].Attach(&chain1, func(recv *peering.RecvEvent) { + netProviders[0].Attach(&chain1, receiver, func(recv *peering.PeerMessageIn) { doneCh <- true }) // @@ -31,9 +32,10 @@ func TestFakeNetwork(t *testing.T) { var a, c peering.PeerSender a, _ = netProviders[1].PeerByNetID("a") c, _ = netProviders[1].PeerByNetID("c") - a.SendMsg(&peering.PeerMessage{PeeringID: chain1, MsgType: 1}) // Will be delivered. - a.SendMsg(&peering.PeerMessage{PeeringID: chain2, MsgType: 2}) // Will be dropped. - c.SendMsg(&peering.PeerMessage{PeeringID: chain1, MsgType: 3}) // Will be dropped. + 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. + c.SendMsg(&peering.PeerMessageData{PeeringID: chain1, MsgReceiver: receiver, MsgType: 4}) // Will be dropped. // // Wait for the result. select { diff --git a/packages/testutil/testchain/mock_acs.go b/packages/testutil/testchain/mock_acs.go index 3b231f83f5..f011178f70 100644 --- a/packages/testutil/testchain/mock_acs.go +++ b/packages/testutil/testchain/mock_acs.go @@ -4,7 +4,6 @@ import ( "sync" "github.com/iotaledger/hive.go/logger" - "github.com/iotaledger/wasp/packages/peering" ) type MockedACSRunner struct { @@ -55,10 +54,6 @@ func (acs *MockedACSRunner) RunACSConsensus(value []byte, sessionID uint64, stat } } -func (acs *MockedACSRunner) TryHandleMessage(recv *peering.RecvEvent) bool { - return false -} - func (acs *MockedACSRunner) Close() { // Nothing. } diff --git a/packages/testutil/testchain/mock_chain_core.go b/packages/testutil/testchain/mock_chain_core.go index 25c80d1c14..70833248d2 100644 --- a/packages/testutil/testchain/mock_chain_core.go +++ b/packages/testutil/testchain/mock_chain_core.go @@ -2,6 +2,7 @@ package testchain import ( "testing" + "time" "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/hive.go/events" @@ -11,35 +12,37 @@ import ( "github.com/iotaledger/wasp/packages/chain/messages" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/coreutil" - "github.com/iotaledger/wasp/packages/iscp/request" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/state" "github.com/iotaledger/wasp/packages/vm/processors" - "go.uber.org/atomic" ) type MockedChainCore struct { - T *testing.T - chainID *iscp.ChainID - processors *processors.Cache - eventStateTransition *events.Event - eventRequestProcessed *events.Event - onGlobalStateSync func() coreutil.ChainStateSync - onGetStateReader func() state.OptimisticStateReader - onEventStateTransition func(data *chain.ChainTransitionEventData) - onEventRequestProcessed func(id iscp.RequestID) - onReceivePeerMessage func(*peering.PeerMessage) - onReceiveDismissChainMsg func(*messages.DismissChainMsg) - onReceiveStateTransitionMsg func(*messages.StateTransitionMsg) - onReceiveStateCandidateMsg func(*messages.StateCandidateMsg) - onReceiveInclusionStateMsg func(*messages.InclusionStateMsg) - onReceiveStateMsg func(*messages.StateMsg) - onReceiveVMResultMsg func(*messages.VMResultMsg) - onReceiveAsynchronousCommonSubsetMsg func(*messages.AsynchronousCommonSubsetMsg) - onReceiveTimerTick func(messages.TimerTick) - onSync func(out ledgerstate.OutputID, blockIndex uint32) //nolint:structcheck,unused - log *logger.Logger -} + T *testing.T + chainID *iscp.ChainID + processors *processors.Cache + peeringID peering.PeeringID + eventStateTransition *events.Event + eventRequestProcessed *events.Event + getNetIDsFun func() []string + onGlobalStateSync func() coreutil.ChainStateSync + onGetStateReader func() state.OptimisticStateReader + onEventStateTransition func(data *chain.ChainTransitionEventData) + onEventRequestProcessed func(id iscp.RequestID) + onSendPeerMsg func(netID string, msgReceiver byte, msgType byte, msgData []byte) + onStateCandidate func(state state.VirtualStateAccess, outputID ledgerstate.OutputID) + onDismissChain func(reason string) + onLedgerState func(chainOutput *ledgerstate.AliasOutput, timestamp time.Time) + onOffLedgerRequest func(msg *messages.OffLedgerRequestMsgIn) + onRequestAck func(msg *messages.RequestAckMsgIn) + onMissingRequestIDs func(msg *messages.MissingRequestIDsMsgIn) + onMissingRequest func(msg *messages.MissingRequestMsg) + onTimerTick func(tick int) + onSync func(out ledgerstate.OutputID, blockIndex uint32) //nolint:structcheck,unused + log *logger.Logger +} + +var _ chain.ChainCore = &MockedChainCore{} func NewMockedChainCore(t *testing.T, chainID *iscp.ChainID, log *logger.Logger) *MockedChainCore { receiveFailFun := func(typee string, msg interface{}) { @@ -49,7 +52,12 @@ func NewMockedChainCore(t *testing.T, chainID *iscp.ChainID, log *logger.Logger) T: t, chainID: chainID, processors: processors.MustNew(processors.NewConfig(inccounter.Processor)), + peeringID: chainID.Array(), log: log, + getNetIDsFun: func() []string { + t.Fatalf("List of netIDs is not known") + return []string{} + }, eventStateTransition: events.NewEvent(func(handler interface{}, params ...interface{}) { handler.(func(_ *chain.ChainTransitionEventData))(params[0].(*chain.ChainTransitionEventData)) }), @@ -59,17 +67,21 @@ func NewMockedChainCore(t *testing.T, chainID *iscp.ChainID, log *logger.Logger) onEventRequestProcessed: func(id iscp.RequestID) { log.Infof("onEventRequestProcessed: %s", id) }, - onReceivePeerMessage: func(msg *peering.PeerMessage) { receiveFailFun("*peering.PeerMessage", msg) }, - onReceiveDismissChainMsg: func(msg *messages.DismissChainMsg) { receiveFailFun("*messages.DismissChainMs", msg) }, - onReceiveStateTransitionMsg: func(msg *messages.StateTransitionMsg) { receiveFailFun("*messages.StateTransitionMsg", msg) }, - onReceiveStateCandidateMsg: func(msg *messages.StateCandidateMsg) { receiveFailFun("*messages.StateCandidateMsg", msg) }, - onReceiveInclusionStateMsg: func(msg *messages.InclusionStateMsg) { receiveFailFun("*messages.InclusionStateMsg", msg) }, - onReceiveStateMsg: func(msg *messages.StateMsg) { receiveFailFun("*messages.StateMsg", msg) }, - onReceiveVMResultMsg: func(msg *messages.VMResultMsg) { receiveFailFun("*messages.VMResultMsg", msg) }, - onReceiveAsynchronousCommonSubsetMsg: func(msg *messages.AsynchronousCommonSubsetMsg) { - receiveFailFun("*messages.AsynchronousCommonSubsetMsg", msg) + onSendPeerMsg: func(netID string, msgReceiver byte, msgType byte, msgData []byte) { + t.Fatalf("Sending to peer msg not implemented, netID=%v, receiver=%v, msgType=%v", netID, msgReceiver, msgType) + }, + onStateCandidate: func(state state.VirtualStateAccess, outputID ledgerstate.OutputID) { + t.Fatalf("Receiving state candidate not implemented, outputID=%v", outputID) + }, + onDismissChain: func(reason string) { t.Fatalf("Dismissing chain not implemented, reason=%v", reason) }, + onLedgerState: func(chainOutput *ledgerstate.AliasOutput, timestamp time.Time) { + t.Fatalf("Receiving ledger state not implemented, chain output=%v", chainOutput) }, - onReceiveTimerTick: func(msg messages.TimerTick) { receiveFailFun("messages.TimerTick", msg) }, + onOffLedgerRequest: func(msg *messages.OffLedgerRequestMsgIn) { receiveFailFun("*messages.OffLedgerRequestMsgIn", msg) }, + onRequestAck: func(msg *messages.RequestAckMsgIn) { receiveFailFun("*messages.RequestAckMsgIn", msg) }, + onMissingRequestIDs: func(msg *messages.MissingRequestIDsMsgIn) { receiveFailFun("*messages.MissingRequestIDsMsgIn", msg) }, + onMissingRequest: func(msg *messages.MissingRequestMsg) { receiveFailFun("*messages.MissingRequestMsg", msg) }, + onTimerTick: func(tick int) { t.Fatalf("Receiving timer tick not implemented: index=%v", tick) }, } ret.onEventStateTransition = func(msg *chain.ChainTransitionEventData) { chain.LogStateTransition(msg, nil, log) @@ -103,100 +115,94 @@ func (m *MockedChainCore) GetCommitteeInfo() *chain.CommitteeInfo { panic("implement me") } -func (m *MockedChainCore) ReceiveMessage(msg interface{}) { - switch msgTypecasted := msg.(type) { - case *peering.PeerMessage: - m.onReceivePeerMessage(msgTypecasted) - case *messages.DismissChainMsg: - m.onReceiveDismissChainMsg(msgTypecasted) - case *messages.StateTransitionMsg: - m.onReceiveStateTransitionMsg(msgTypecasted) - case *messages.StateCandidateMsg: - m.onReceiveStateCandidateMsg(msgTypecasted) - case *messages.InclusionStateMsg: - m.onReceiveInclusionStateMsg(msgTypecasted) - case *messages.StateMsg: - m.onReceiveStateMsg(msgTypecasted) - case *messages.VMResultMsg: - m.onReceiveVMResultMsg(msgTypecasted) - case *messages.AsynchronousCommonSubsetMsg: - m.onReceiveAsynchronousCommonSubsetMsg(msgTypecasted) - case messages.TimerTick: - m.onReceiveTimerTick(msgTypecasted) - } +func (m *MockedChainCore) StateCandidateToStateManager(virtualState state.VirtualStateAccess, outputID ledgerstate.OutputID) { + m.onStateCandidate(virtualState, outputID) } -func (m *MockedChainCore) Events() chain.ChainEvents { - return m +func (m *MockedChainCore) EnqueueDismissChain(reason string) { + m.onDismissChain(reason) } -func (m *MockedChainCore) Processors() *processors.Cache { - return m.processors +func (m *MockedChainCore) EnqueueLedgerState(chainOutput *ledgerstate.AliasOutput, timestamp time.Time) { + m.onLedgerState(chainOutput, timestamp) } -func (m *MockedChainCore) RequestProcessed() *events.Event { - return m.eventRequestProcessed +func (m *MockedChainCore) EnqueueOffLedgerRequestMsg(msg *messages.OffLedgerRequestMsgIn) { + m.onOffLedgerRequest(msg) } -func (m *MockedChainCore) ChainTransition() *events.Event { - return m.eventStateTransition +func (m *MockedChainCore) EnqueueRequestAckMsg(msg *messages.RequestAckMsgIn) { + m.onRequestAck(msg) } -func (m *MockedChainCore) OnStateTransition(f func(data *chain.ChainTransitionEventData)) { - m.onEventStateTransition = f +func (m *MockedChainCore) EnqueueMissingRequestIDsMsg(msg *messages.MissingRequestIDsMsgIn) { + m.onMissingRequestIDs(msg) } -func (m *MockedChainCore) OnRequestProcessed(f func(id iscp.RequestID)) { - m.onEventRequestProcessed = f +func (m *MockedChainCore) EnqueueMissingRequestMsg(msg *messages.MissingRequestMsg) { + m.onMissingRequest(msg) } -func (m *MockedChainCore) OnReceivePeerMessage(f func(*peering.PeerMessage)) { - m.onReceivePeerMessage = f +func (m *MockedChainCore) EnqueueTimerTick(tick int) { + m.onTimerTick(tick) } -func (m *MockedChainCore) OnReceiveDismissChainMsg(f func(*messages.DismissChainMsg)) { - m.onReceiveDismissChainMsg = f +func (m *MockedChainCore) Processors() *processors.Cache { + return m.processors } -func (m *MockedChainCore) OnReceiveStateTransitionMsg(f func(*messages.StateTransitionMsg)) { - m.onReceiveStateTransitionMsg = f +func (m *MockedChainCore) TriggerChainTransition(data *chain.ChainTransitionEventData) { + m.eventStateTransition.Trigger(data) } -func (m *MockedChainCore) OnReceiveStateCandidateMsg(f func(*messages.StateCandidateMsg)) { - m.onReceiveStateCandidateMsg = f +func (m *MockedChainCore) OnStateTransition(f func(data *chain.ChainTransitionEventData)) { + m.onEventStateTransition = f } -func (m *MockedChainCore) OnReceiveInclusionStateMsg(f func(*messages.InclusionStateMsg)) { - m.onReceiveInclusionStateMsg = f +func (m *MockedChainCore) OnRequestProcessed(f func(id iscp.RequestID)) { + m.onEventRequestProcessed = f } -func (m *MockedChainCore) OnReceiveStateMsg(f func(*messages.StateMsg)) { - m.onReceiveStateMsg = f +func (m *MockedChainCore) OnGetStateReader(f func() state.OptimisticStateReader) { + m.onGetStateReader = f } -func (m *MockedChainCore) OnReceiveVMResultMsg(f func(*messages.VMResultMsg)) { - m.onReceiveVMResultMsg = f +func (m *MockedChainCore) OnGlobalStateSync(f func() coreutil.ChainStateSync) { + m.onGlobalStateSync = f } -func (m *MockedChainCore) OnReceiveAsynchronousCommonSubsetMsg(f func(*messages.AsynchronousCommonSubsetMsg)) { - m.onReceiveAsynchronousCommonSubsetMsg = f +func (m *MockedChainCore) OnSendPeerMsg(fun func(netID string, msgReceiver byte, msgType byte, msgData []byte)) { + m.onSendPeerMsg = fun } -func (m *MockedChainCore) OnReceiveTimerTick(f func(messages.TimerTick)) { - m.onReceiveTimerTick = f +func (m *MockedChainCore) OnStateCandidate(fun func(state state.VirtualStateAccess, outputID ledgerstate.OutputID)) { + m.onStateCandidate = fun } -func (m *MockedChainCore) OnGetStateReader(f func() state.OptimisticStateReader) { - m.onGetStateReader = f +func (m *MockedChainCore) OnDismissChain(fun func(reason string)) { + m.onDismissChain = fun } -func (m *MockedChainCore) OnGlobalStateSync(f func() coreutil.ChainStateSync) { - m.onGlobalStateSync = f +func (m *MockedChainCore) OnLedgerState(fun func(chainOutput *ledgerstate.AliasOutput, timestamp time.Time)) { + m.onLedgerState = fun +} + +func (m *MockedChainCore) OnOffLedgerRequest(fun func(msg *messages.OffLedgerRequestMsgIn)) { + m.onOffLedgerRequest = fun +} + +func (m *MockedChainCore) OnRequestAck(fun func(msg *messages.RequestAckMsgIn)) { + m.onRequestAck = fun +} + +func (m *MockedChainCore) OnMissingRequestIDs(fun func(msg *messages.MissingRequestIDsMsgIn)) { + m.onMissingRequestIDs = fun } -func (m *MockedChainCore) GlobalSolidIndex() *atomic.Uint32 { - return nil +func (m *MockedChainCore) OnMissingRequest(fun func(msg *messages.MissingRequestMsg)) { + m.onMissingRequest = fun } -func (m *MockedChainCore) ReceiveOffLedgerRequest(_ *request.OffLedger, _ string) { +func (m *MockedChainCore) OnTimerTick(fun func(tick int)) { + m.onTimerTick = fun } diff --git a/packages/testutil/testchain/mock_nodeconn.go b/packages/testutil/testchain/mock_nodeconn.go index f725dd23c3..489d8fdb6e 100644 --- a/packages/testutil/testchain/mock_nodeconn.go +++ b/packages/testutil/testchain/mock_nodeconn.go @@ -2,18 +2,20 @@ package testchain import ( "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/wasp/packages/chain" + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" ) type MockedNodeConn struct { id string - onPullBacklog func(addr *ledgerstate.AliasAddress) - onPullState func(addr *ledgerstate.AliasAddress) - onPullConfirmedTransaction func(addr ledgerstate.Address, txid ledgerstate.TransactionID) - onPullTransactionInclusionState func(addr ledgerstate.Address, txid ledgerstate.TransactionID) - onPullConfirmedOutput func(addr ledgerstate.Address, outputID ledgerstate.OutputID) + onPullState func() + onPullTransactionInclusionState func(txid ledgerstate.TransactionID) + onPullConfirmedOutput func(outputID ledgerstate.OutputID) onPostTransaction func(tx *ledgerstate.Transaction) } +var _ chain.ChainNodeConnection = &MockedNodeConn{} + func NewMockedNodeConnection(id string) *MockedNodeConn { return &MockedNodeConn{id: id} } @@ -22,50 +24,52 @@ func (m *MockedNodeConn) ID() string { return m.id } -func (m *MockedNodeConn) PullBacklog(addr *ledgerstate.AliasAddress) { - m.onPullBacklog(addr) -} - -func (m *MockedNodeConn) PullState(addr *ledgerstate.AliasAddress) { - m.onPullState(addr) -} - -func (m *MockedNodeConn) PullConfirmedTransaction(addr ledgerstate.Address, txid ledgerstate.TransactionID) { - m.onPullConfirmedTransaction(addr, txid) +func (m *MockedNodeConn) PullState() { + m.onPullState() } -func (m *MockedNodeConn) PullTransactionInclusionState(addr ledgerstate.Address, txid ledgerstate.TransactionID) { - m.onPullTransactionInclusionState(addr, txid) +func (m *MockedNodeConn) PullTransactionInclusionState(txid ledgerstate.TransactionID) { + m.onPullTransactionInclusionState(txid) } -func (m *MockedNodeConn) PullConfirmedOutput(addr ledgerstate.Address, outputID ledgerstate.OutputID) { - m.onPullConfirmedOutput(addr, outputID) +func (m *MockedNodeConn) PullConfirmedOutput(outputID ledgerstate.OutputID) { + m.onPullConfirmedOutput(outputID) } func (m *MockedNodeConn) PostTransaction(tx *ledgerstate.Transaction) { m.onPostTransaction(tx) } -func (m *MockedNodeConn) OnPullBacklog(f func(addr *ledgerstate.AliasAddress)) { - m.onPullBacklog = f -} - -func (m *MockedNodeConn) OnPullState(f func(addr *ledgerstate.AliasAddress)) { +func (m *MockedNodeConn) OnPullState(f func()) { m.onPullState = f } -func (m *MockedNodeConn) OnPullConfirmedTransaction(f func(addr ledgerstate.Address, txid ledgerstate.TransactionID)) { - m.onPullConfirmedTransaction = f -} - -func (m *MockedNodeConn) OnPullTransactionInclusionState(f func(addr ledgerstate.Address, txid ledgerstate.TransactionID)) { +func (m *MockedNodeConn) OnPullTransactionInclusionState(f func(txid ledgerstate.TransactionID)) { m.onPullTransactionInclusionState = f } -func (m *MockedNodeConn) OnPullConfirmedOutput(f func(addr ledgerstate.Address, outputID ledgerstate.OutputID)) { +func (m *MockedNodeConn) OnPullConfirmedOutput(f func(outputID ledgerstate.OutputID)) { m.onPullConfirmedOutput = f } func (m *MockedNodeConn) OnPostTransaction(f func(tx *ledgerstate.Transaction)) { m.onPostTransaction = f } + +func (m *MockedNodeConn) AttachToTransactionReceived(chain.NodeConnectionHandleTransactionFun) {} +func (m *MockedNodeConn) AttachToInclusionStateReceived(chain.NodeConnectionHandleInclusionStateFun) { +} +func (m *MockedNodeConn) AttachToOutputReceived(chain.NodeConnectionHandleOutputFun) {} +func (m *MockedNodeConn) AttachToUnspentAliasOutputReceived(chain.NodeConnectionHandleUnspentAliasOutputFun) { +} + +func (m *MockedNodeConn) DetachFromTransactionReceived() {} +func (m *MockedNodeConn) DetachFromInclusionStateReceived() {} +func (m *MockedNodeConn) DetachFromOutputReceived() {} +func (m *MockedNodeConn) DetachFromUnspentAliasOutputReceived() {} + +func (m *MockedNodeConn) Close() {} + +func (m *MockedNodeConn) GetMetrics() nodeconnmetrics.NodeConnectionMessagesMetrics { + return nodeconnmetrics.NewEmptyNodeConnectionMessagesMetrics() +} diff --git a/packages/util/pipe/interface.go b/packages/util/pipe/interface.go new file mode 100644 index 0000000000..11c6f28cfc --- /dev/null +++ b/packages/util/pipe/interface.go @@ -0,0 +1,25 @@ +package pipe + +import "github.com/iotaledger/wasp/packages/hashing" + +// minQueueLen is smallest capacity that queue may have. +const minQueueLen = 16 + +type Hashable interface { + GetHash() hashing.HashValue +} + +type Queue interface { + Length() int + Add(elem interface{}) bool + Peek() interface{} + Get(i int) interface{} + Remove() interface{} +} + +type Pipe interface { + In() chan<- interface{} + Out() <-chan interface{} + Len() int + Close() +} diff --git a/packages/util/pipe/pipe.go b/packages/util/pipe/pipe.go new file mode 100644 index 0000000000..8ddac609a3 --- /dev/null +++ b/packages/util/pipe/pipe.go @@ -0,0 +1,104 @@ +package pipe + +// InfinitePipe provides deserialised sender and receiver: it queues messages +// sent by the sender and returns them to the receiver whenever it is ready, +// without blocking the sender process. Depending on the backing queue, the pipe +// might have other characteristics. +type InfinitePipe struct { + input chan interface{} + output chan interface{} + length chan int + buffer Queue +} + +var _ Pipe = &InfinitePipe{} + +func NewDefaultInfinitePipe() Pipe { + return newInfinitePipe(NewDefaultLimitedPriorityHashQueue()) +} + +func NewPriorityInfinitePipe(priorityFun func(interface{}) bool) Pipe { + return newInfinitePipe(NewPriorityLimitedPriorityHashQueue(priorityFun)) +} + +func NewLimitInfinitePipe(limit int) Pipe { + return newInfinitePipe(NewLimitLimitedPriorityHashQueue(limit)) +} + +func NewLimitPriorityInfinitePipe(priorityFun func(interface{}) bool, limit int) Pipe { + return newInfinitePipe(NewLimitPriorityLimitedPriorityHashQueue(priorityFun, limit)) +} + +func NewHashInfinitePipe() Pipe { + return newInfinitePipe(NewHashLimitedPriorityHashQueue(true)) +} + +func NewPriorityHashInfinitePipe(priorityFun func(interface{}) bool) Pipe { + return newInfinitePipe(NewPriorityHashLimitedPriorityHashQueue(priorityFun, true)) +} + +func NewLimitHashInfinitePipe(limit int) Pipe { + return newInfinitePipe(NewLimitHashLimitedPriorityHashQueue(limit, true)) +} + +func NewInfinitePipe(priorityFun func(interface{}) bool, limit int) Pipe { + return newInfinitePipe(NewLimitedPriorityHashQueue(priorityFun, limit, true)) +} + +func newInfinitePipe(queue Queue) *InfinitePipe { + ch := &InfinitePipe{ + input: make(chan interface{}), + output: make(chan interface{}), + length: make(chan int), + buffer: queue, + } + go ch.infiniteBuffer() + return ch +} + +func (ch *InfinitePipe) In() chan<- interface{} { + return ch.input +} + +func (ch *InfinitePipe) Out() <-chan interface{} { + return ch.output +} + +func (ch *InfinitePipe) Len() int { + return <-ch.length +} + +func (ch *InfinitePipe) Close() { + close(ch.input) +} + +func (ch *InfinitePipe) infiniteBuffer() { + var input, output chan interface{} + var next interface{} + input = ch.input + + for input != nil || output != nil { + select { + case elem, open := <-input: + if open { + ch.buffer.Add(elem) + } else { + input = nil + } + case output <- next: + ch.buffer.Remove() + case ch.length <- ch.buffer.Length(): + } + + if ch.buffer.Length() > 0 { + output = ch.output + next = ch.buffer.Peek() + } else { + output = nil + next = nil + } + } + + close(ch.output) + close(ch.length) +} diff --git a/packages/util/pipe/pipe_test.go b/packages/util/pipe/pipe_test.go new file mode 100644 index 0000000000..9d1fd10255 --- /dev/null +++ b/packages/util/pipe/pipe_test.go @@ -0,0 +1,249 @@ +package pipe + +import ( + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +func TestDefaultInfinitePipeWriteReadLen(t *testing.T) { + testDefaultPipeWriteReadLen(NewDefaultInfinitePipe(), 1000, identityFunInt, t) +} + +func TestPriorityInfinitePipeWriteReadLen(t *testing.T) { + testPriorityPipeWriteReadLen(NewPriorityInfinitePipe, t) +} + +func TestLimitInfinitePipeNoLimitWriteReadLen(t *testing.T) { + testLimitedPipeNoLimitWriteReadLen(NewLimitInfinitePipe, t) +} + +func TestLimitInfinitePipeWriteReadLen(t *testing.T) { + testLimitedPipeWriteReadLen(NewLimitInfinitePipe, t) +} + +func TestLimitPriorityInfinitePipeNoLimitWriteReadLen(t *testing.T) { + testLimitedPriorityPipeNoLimitWriteReadLen(NewLimitPriorityInfinitePipe, t) +} + +func TestLimitPriorityInfinitePipeWriteReadLen(t *testing.T) { + testLimitedPriorityPipeWriteReadLen(NewLimitPriorityInfinitePipe, t) +} + +func TestHashInfinitePipeWriteReadLen(t *testing.T) { + testDefaultPipeWriteReadLen(NewHashInfinitePipe(), 1000, identityFunInt, t) +} + +func TestPriorityHashInfinitePipeWriteReadLen(t *testing.T) { + testPriorityPipeWriteReadLen(NewPriorityHashInfinitePipe, t) +} + +func TestLimitHashInfinitePipeNoLimitWriteReadLen(t *testing.T) { + testLimitedPipeNoLimitWriteReadLen(NewLimitHashInfinitePipe, t) +} + +func TestLimitHashInfinitePipeWriteReadLen(t *testing.T) { + testLimitedPipeWriteReadLen(NewLimitHashInfinitePipe, t) +} + +func TestInfinitePipeNoLimitWriteReadLen(t *testing.T) { + testLimitedPriorityPipeNoLimitWriteReadLen(NewInfinitePipe, t) +} + +func TestInfinitePipeWriteReadLen(t *testing.T) { + testLimitedPriorityPipeWriteReadLen(NewInfinitePipe, t) +} + +func testLimitedPriorityPipeNoLimitWriteReadLen(makeLimitedPriorityPipeFun func(priorityFun func(i interface{}) bool, limit int) Pipe, t *testing.T) { + testPriorityPipeWriteReadLen(func(priorityFun func(i interface{}) bool) Pipe { return makeLimitedPriorityPipeFun(priorityFun, 1200) }, t) +} + +func testLimitedPriorityPipeWriteReadLen(makeLimitedPriorityPipeFun func(priorityFun func(i interface{}) bool, limit int) Pipe, t *testing.T) { + limit := 800 + p := makeLimitedPriorityPipeFun(priorityFunMod3, limit) + result := func(index int) int { + if index <= 333 { + return -3*index + 999 + } + if index%2 == 0 { + return 3*index/2 - 200 + } + return (3*index - 401) / 2 + } + testPipeWriteReadLen(p, 1000, limit, result, t) +} + +func testLimitedPipeNoLimitWriteReadLen(makeLimitedPipeFun func(limit int) Pipe, t *testing.T) { + testDefaultPipeWriteReadLen(makeLimitedPipeFun(1200), 1000, identityFunInt, t) +} + +func testLimitedPipeWriteReadLen(makeLimitedPipeFun func(limit int) Pipe, t *testing.T) { + limit := 800 + elementsToAdd := 1000 + indexDiff := elementsToAdd - limit + result := func(index int) int { + return index + indexDiff + } + testPipeWriteReadLen(makeLimitedPipeFun(limit), elementsToAdd, limit, result, t) +} + +func testPriorityPipeWriteReadLen(makePriorityPipeFun func(func(i interface{}) bool) Pipe, t *testing.T) { + p := makePriorityPipeFun(priorityFunMod3) + result := func(index int) int { + if index <= 333 { + return -3*index + 999 + } + if index%2 == 0 { + return 3*index/2 - 500 + } + return (3*index - 1001) / 2 + } + testDefaultPipeWriteReadLen(p, 1000, result, t) +} + +func testDefaultPipeWriteReadLen(p Pipe, elementsToWrite int, result func(index int) int, t *testing.T) { + testPipeWriteReadLen(p, elementsToWrite, elementsToWrite, result, t) +} + +func testPipeWriteReadLen(p Pipe, elementsToWrite, elementsToRead int, result func(index int) int, t *testing.T) { + for i := 0; i < elementsToWrite; i++ { + p.In() <- SimpleHashable(i) + } + fullLength := p.Len() + require.Equalf(t, elementsToRead, fullLength, "full channel length missmatch") + p.Close() + closedLength := p.Len() + require.Equalf(t, elementsToRead, closedLength, "closed channel length missmatch") + for i := 0; i < elementsToRead; i++ { + val := <-p.Out() + require.Equalf(t, SimpleHashable(result(i)), val.(SimpleHashable), "read %d missmatch", i) + } +} + +//-- + +func TestDefaultInfinitePipeConcurrentWriteReadLen(t *testing.T) { + result := identityFunInt + testDefaultPipeConcurrentWriteReadLen(NewDefaultInfinitePipe(), 1000, &result, t) +} + +func TestPriorityInfinitePipeConcurrentWriteReadLen(t *testing.T) { + testPriorityPipeConcurrentWriteReadLen(NewPriorityInfinitePipe, t) +} + +func TestLimitInfinitePipeNoLimitConcurrentWriteReadLen(t *testing.T) { + testLimitedPipeNoLimitConcurrentWriteReadLen(NewLimitInfinitePipe, t) +} + +func TestLimitInfinitePipeConcurrentWriteReadLen(t *testing.T) { + testLimitedPipeConcurrentWriteReadLen(NewLimitInfinitePipe, t) +} + +func TestLimitPriorityInfinitePipeNoLimitConcurrentWriteReadLen(t *testing.T) { + testLimitedPriorityPipeNoLimitConcurrentWriteReadLen(NewLimitPriorityInfinitePipe, t) +} + +func TestLimitPriorityInfinitePipeConcurrentWriteReadLen(t *testing.T) { + testLimitedPriorityPipeConcurrentWriteReadLen(NewLimitPriorityInfinitePipe, t) +} + +func TestHashInfinitePipeConcurrentWriteReadLen(t *testing.T) { + result := identityFunInt + testDefaultPipeConcurrentWriteReadLen(NewHashInfinitePipe(), 1000, &result, t) +} + +func TestPriorityHashInfinitePipeConcurrentWriteReadLen(t *testing.T) { + testPriorityPipeConcurrentWriteReadLen(NewPriorityHashInfinitePipe, t) +} + +func TestLimitHashInfinitePipeNoLimitConcurrentWriteReadLen(t *testing.T) { + testLimitedPipeNoLimitConcurrentWriteReadLen(NewLimitHashInfinitePipe, t) +} + +func TestLimitHashInfinitePipeConcurrentWriteReadLen(t *testing.T) { + testLimitedPipeConcurrentWriteReadLen(NewLimitHashInfinitePipe, t) +} + +func TestInfinitePipeNoLimitConcurrentWriteReadLen(t *testing.T) { + testLimitedPriorityPipeNoLimitConcurrentWriteReadLen(NewInfinitePipe, t) +} + +func TestInfinitePipeConcurrentWriteReadLen(t *testing.T) { + testLimitedPriorityPipeConcurrentWriteReadLen(NewInfinitePipe, t) +} + +func testLimitedPriorityPipeNoLimitConcurrentWriteReadLen(makeLimitedPriorityPipeFun func(priorityFun func(i interface{}) bool, limit int) Pipe, t *testing.T) { + testPriorityPipeConcurrentWriteReadLen(func(priorityFun func(i interface{}) bool) Pipe { return makeLimitedPriorityPipeFun(priorityFun, 1200) }, t) +} + +func testLimitedPriorityPipeConcurrentWriteReadLen(makeLimitedPriorityPipeFun func(priorityFun func(i interface{}) bool, limit int) Pipe, t *testing.T) { + limit := 800 + ch := makeLimitedPriorityPipeFun(priorityFunMod3, limit) + testPipeConcurrentWriteReadLen(ch, 1000, limit, nil, t) +} + +func testLimitedPipeNoLimitConcurrentWriteReadLen(makeLimitedPipeFun func(limit int) Pipe, t *testing.T) { + result := identityFunInt + testDefaultPipeConcurrentWriteReadLen(makeLimitedPipeFun(1200), 1000, &result, t) +} + +func testLimitedPipeConcurrentWriteReadLen(makeLimitedPipeFun func(limit int) Pipe, t *testing.T) { + testPipeConcurrentWriteReadLen(makeLimitedPipeFun(800), 1000, 800, nil, t) +} + +func testPriorityPipeConcurrentWriteReadLen(makePriorityPipeFun func(func(i interface{}) bool) Pipe, t *testing.T) { + ch := makePriorityPipeFun(priorityFunMod3) + testDefaultPipeConcurrentWriteReadLen(ch, 1000, nil, t) +} + +func testDefaultPipeConcurrentWriteReadLen(p Pipe, elementsToWrite int, result *func(index int) int, t *testing.T) { + testPipeConcurrentWriteReadLen(p, elementsToWrite, elementsToWrite, result, t) +} + +func testPipeConcurrentWriteReadLen(p Pipe, elementsToWrite, elementsToRead int, result *func(index int) int, t *testing.T) { + var wg sync.WaitGroup + written := 0 + read := 0 + stop := make(chan bool) + wg.Add(2) + + go func() { + for i := 0; i < elementsToWrite; i++ { + p.In() <- SimpleHashable(i) + written++ + } + wg.Done() + }() + + go func() { + for i := 0; i < elementsToRead; i++ { + val := <-p.Out() + if result != nil { + require.Equalf(t, SimpleHashable((*result)(i)), val.(SimpleHashable), "concurent read %d missmatch", i) + } + read++ + } + wg.Done() + }() + + go func() { + for { + select { + case <-stop: + return + default: + length := p.Len() + t.Logf("current channel length is %d", length) + // no asserts here - the read/write process is asynchronious + time.Sleep(10 * time.Millisecond) + } + } + }() + + wg.Wait() + stop <- true + require.Equalf(t, elementsToWrite, written, "concurent write elements written missmatch") + require.Equalf(t, elementsToRead, read, "concurent read elements read missmatch") +} diff --git a/packages/util/pipe/queue.go b/packages/util/pipe/queue.go new file mode 100644 index 0000000000..fa4f435f6c --- /dev/null +++ b/packages/util/pipe/queue.go @@ -0,0 +1,265 @@ +package pipe + +import "github.com/iotaledger/wasp/packages/hashing" + +// LimitedPriorityHashQueue is a queue, which can prioritize elements, +// limit its growth and reject already included elements. +type LimitedPriorityHashQueue struct { + buf []interface{} + head int + pend int + tail int + count int + priorityFun func(interface{}) bool + limit int + hashMap *map[hashing.HashValue]bool +} + +var _ Queue = &LimitedPriorityHashQueue{} + +const Infinity = 0 + +func NewDefaultLimitedPriorityHashQueue() Queue { + return NewHashLimitedPriorityHashQueue(false) +} + +func NewPriorityLimitedPriorityHashQueue(priorityFun func(interface{}) bool) Queue { + return NewPriorityHashLimitedPriorityHashQueue(priorityFun, false) +} + +func NewLimitLimitedPriorityHashQueue(limit int) Queue { + return NewLimitHashLimitedPriorityHashQueue(limit, false) +} + +func NewLimitPriorityLimitedPriorityHashQueue(priorityFun func(interface{}) bool, limit int) Queue { + return NewLimitedPriorityHashQueue(priorityFun, limit, false) +} + +func NewHashLimitedPriorityHashQueue(hashNeeded bool) Queue { + return NewLimitHashLimitedPriorityHashQueue(Infinity, hashNeeded) +} + +func NewPriorityHashLimitedPriorityHashQueue(priorityFun func(interface{}) bool, hashNeeded bool) Queue { + return NewLimitedPriorityHashQueue(priorityFun, Infinity, hashNeeded) +} + +func NewLimitHashLimitedPriorityHashQueue(limit int, hashNeeded bool) Queue { + return NewLimitedPriorityHashQueue(func(interface{}) bool { return false }, limit, hashNeeded) +} + +func NewLimitedPriorityHashQueue(priorityFun func(interface{}) bool, limit int, hashNeeded bool) Queue { + var initBufSize int + if (limit != Infinity) && (limit < minQueueLen) { + initBufSize = limit + } else { + initBufSize = minQueueLen + } + var hashMap *map[hashing.HashValue]bool + if hashNeeded { + hMap := make(map[hashing.HashValue]bool) + hashMap = &hMap + } else { + hashMap = nil + } + return &LimitedPriorityHashQueue{ + head: 0, + pend: -1, + tail: 0, + count: 0, + buf: make([]interface{}, initBufSize), + priorityFun: priorityFun, + limit: limit, + hashMap: hashMap, + } +} + +// Length returns the number of elements currently stored in the queue. +func (q *LimitedPriorityHashQueue) Length() int { + return q.count +} + +func (q *LimitedPriorityHashQueue) getIndex(rawIndex int) int { + index := rawIndex % len(q.buf) + if index < 0 { + return index + len(q.buf) + } + return index +} + +// resizes the queue to fit exactly twice its current contents +// this can result in shrinking if the queue is less than half-full +// the size of the resized queue is never smaller than minQueueLen, except +// when the limit is smaller. +func (q *LimitedPriorityHashQueue) resize() { + newSize := q.count << 1 + if newSize < minQueueLen { + newSize = minQueueLen + } + if (q.limit != Infinity) && (newSize > q.limit) { + newSize = q.limit + } + newBuf := make([]interface{}, newSize) + + if q.tail > q.head { + copy(newBuf, q.buf[q.head:q.tail]) + } else { + n := copy(newBuf, q.buf[q.head:]) + copy(newBuf[n:], q.buf[:q.tail]) + } + + if q.pend >= 0 { + q.pend = q.getIndex(q.pend - q.head) + } + q.head = 0 + q.tail = q.count + q.buf = newBuf +} + +// Add puts an element to the start or end of the queue, depending +// on the result of priorityFun. If the limited queue is full it adds a new element +// removing the previously added element, according to the following rules: +// * not prioritized element is chosen for deletion, if possible +// * the chosen for deletion element is always the oldest among its type +// * not prioritized element can not be added if there are no not prioritized +// element to delete +// If it is a hash queue, the element is not added, if it is already in the queue. +// If the add was successful, returns `true`. +func (q *LimitedPriorityHashQueue) Add(elem interface{}) bool { + var elemHashable Hashable + var elemHash hashing.HashValue + var ok bool + if q.hashMap != nil { + elemHashable, ok = elem.(Hashable) + if !ok { + panic("Adding not hashable element") + } + elemHash = elemHashable.GetHash() + contains, ok := (*q.hashMap)[elemHash] + if ok && contains { + // duplicate element; ignoring + return false + } + } + limitReached := false + if q.count == len(q.buf) { + if (q.limit != Infinity) && (q.count >= q.limit) { + limitReached = true + } else { + q.resize() + } + } + priority := q.priorityFun(elem) + if limitReached && !priority && (q.pend == q.getIndex(q.tail-1)) { + // Not possible to add not priority element in queue full of priority elements + return false + } + if limitReached { + var deleteElem interface{} + if q.pend < 0 { + deleteElem = q.buf[q.head] + q.head = q.getIndex(q.head + 1) + } else { + ptail := q.getIndex(q.pend + 1) + if ptail == q.tail { + deleteElem = q.buf[q.pend] + q.tail = q.getIndex(q.tail - 1) + q.pend = q.getIndex(q.pend - 1) + } else { + deleteElem = q.buf[ptail] + if ptail > q.head { + copy(q.buf[q.head+1:ptail+1], q.buf[q.head:ptail]) + } else { + oldHead := q.buf[q.head] + if ptail > 0 { + copy(q.buf[1:ptail+1], q.buf[:ptail]) + } + lastIndex := len(q.buf) - 1 + q.buf[0] = q.buf[lastIndex] + if q.head < lastIndex { + copy(q.buf[q.head+1:], q.buf[q.head:lastIndex]) + } + q.buf[q.getIndex(q.head+1)] = oldHead + } + q.pend = q.getIndex(q.pend + 1) + q.head = q.getIndex(q.head + 1) + } + } + if q.hashMap != nil { + deleteElemHashable, ok := deleteElem.(Hashable) + if !ok { + panic("Deleting not hashable element") + } + delete(*q.hashMap, deleteElemHashable.GetHash()) + } + } + if priority { + q.head = q.getIndex(q.head - 1) + q.buf[q.head] = elem + if q.pend < 0 { + q.pend = q.head + } + } else { + q.buf[q.tail] = elem + // bitwise modulus + q.tail = q.getIndex(q.tail + 1) + } + if !limitReached { + q.count++ + } + if q.hashMap != nil { + (*q.hashMap)[elemHash] = true + } + return true +} + +// Peek returns the element at the head of the queue. This call panics +// if the queue is empty. +func (q *LimitedPriorityHashQueue) Peek() interface{} { + if q.count <= 0 { + panic("queue: Peek() called on empty queue") + } + return q.buf[q.head] +} + +// Get returns the element at index i in the queue. If the index is +// invalid, the call will panic. This method accepts both positive and +// negative index values. Index 0 refers to the first element, and +// index -1 refers to the last. +func (q *LimitedPriorityHashQueue) Get(i int) interface{} { + // If indexing backwards, convert to positive index. + if i < 0 { + i += q.count + } + if i < 0 || i >= q.count { + panic("queue: Get() called with index out of range") + } + // bitwise modulus + return q.buf[q.getIndex(q.head+i)] +} + +// Remove removes and returns the element from the front of the queue. If the +// queue is empty, the call will panic. +func (q *LimitedPriorityHashQueue) Remove() interface{} { + if q.count <= 0 { + panic("queue: Remove() called on empty queue") + } + ret := q.buf[q.head] + q.buf[q.head] = nil + if q.head == q.pend { + q.pend = -1 + } + q.head = q.getIndex(q.head + 1) + q.count-- + // Resize down if buffer 1/4 full. + if (len(q.buf) > minQueueLen) && ((q.count << 2) <= len(q.buf)) { + q.resize() + } + if q.hashMap != nil { + retHashable, ok := ret.(Hashable) + if !ok { + panic("Removing not hashable element") + } + delete(*q.hashMap, retHashable.GetHash()) + } + return ret +} diff --git a/packages/util/pipe/queue_test.go b/packages/util/pipe/queue_test.go new file mode 100644 index 0000000000..12412028d7 --- /dev/null +++ b/packages/util/pipe/queue_test.go @@ -0,0 +1,991 @@ +package pipe + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func testQueueBasicAddLengthPeekRemove(q Queue, elementsToAdd int, add func(index int) int, addResult func(index int) bool, elementsToRemove int, result func(index int) int, t *testing.T) { + for i := 0; i < elementsToAdd; i++ { + value := add(i) + actualAddResult := q.Add(SimpleHashable(value)) + require.Equalf(t, addResult(i), actualAddResult, "add result of element %d value %d missmatch", i, value) + } + fullLength := q.Length() + require.Equalf(t, elementsToRemove, fullLength, "full queue length missmatch") + for i := 0; i < elementsToRemove; i++ { + expected := SimpleHashable(result(i)) + peekResult := q.Peek().(SimpleHashable) + require.Equalf(t, expected, peekResult, "peek %d missmatch", i) + removeResult := q.Remove().(SimpleHashable) + require.Equalf(t, expected, removeResult, "remove %d missmatch", i) + } + emptyLength := q.Length() + require.Equalf(t, 0, emptyLength, "empty queue length missmatch") +} + +//-- + +func TestDefaultLimitedPriorityHashQueueSimple(t *testing.T) { + testDefaultQueueSimple(NewDefaultLimitedPriorityHashQueue(), t) +} + +func TestPriorityLimitedPriorityHashQueueSimple(t *testing.T) { + testPriorityQueueSimple(NewPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueNoLimitSimple(t *testing.T) { + testLimitedQueueNoLimitSimple(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueSimple(t *testing.T) { + testLimitedQueueSimple(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueNoLimitSimple(t *testing.T) { + testLimitedPriorityQueueNoLimitSimple(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueSimple(t *testing.T) { + testLimitedPriorityQueueSimple(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestHashLimitedPriorityHashQueueSimple(t *testing.T) { + testDefaultQueueSimple(NewHashLimitedPriorityHashQueue(true), t) +} + +func TestPriorityHashLimitedPriorityHashQueueSimple(t *testing.T) { + testPriorityQueueSimple(newPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueNoLimitSimple(t *testing.T) { + testLimitedQueueNoLimitSimple(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueSimple(t *testing.T) { + testLimitedQueueSimple(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueNoLimitSimple(t *testing.T) { + testLimitedPriorityQueueNoLimitSimple(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueSimple(t *testing.T) { + testLimitedPriorityQueueSimple(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func testLimitedPriorityQueueNoLimitSimple(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + testPriorityQueueSimple(func(priorityFun func(i interface{}) bool) Queue { return makeLimitedPriorityQueueFun(priorityFun, 15) }, t) +} + +func testLimitedPriorityQueueSimple(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + resultArray := []int{9, 6, 3, 0, 4, 5, 7, 8} + limit := len(resultArray) + q := makeLimitedPriorityQueueFun(priorityFunMod3, limit) + result := func(index int) int { + return resultArray[index] + } + testQueueSimple(q, 10, limit, result, t) +} + +func testLimitedQueueNoLimitSimple(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + testDefaultQueueSimple(makeLimitedQueueFun(15), t) +} + +func testLimitedQueueSimple(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + limit := 8 + elementsToAdd := 10 + indexDiff := elementsToAdd - limit + q := makeLimitedQueueFun(limit) + result := func(index int) int { + return index + indexDiff + } + testQueueSimple(q, elementsToAdd, limit, result, t) +} + +func testPriorityQueueSimple(makePriorityQueueFun func(func(i interface{}) bool) Queue, t *testing.T) { + q := makePriorityQueueFun(priorityFunMod3) + resultArray := []int{9, 6, 3, 0, 1, 2, 4, 5, 7, 8} + result := func(index int) int { + return resultArray[index] + } + elementsToAdd := len(resultArray) + testQueueSimple(q, elementsToAdd, elementsToAdd, result, t) +} + +func testDefaultQueueSimple(q Queue, t *testing.T) { + elementsToAdd := 10 + testQueueSimple(q, elementsToAdd, elementsToAdd, identityFunInt, t) +} + +func testQueueSimple(q Queue, elementsToAdd, elementsToRemove int, result func(index int) int, t *testing.T) { + testQueueBasicAddLengthPeekRemove(q, elementsToAdd, identityFunInt, alwaysTrueFun, elementsToRemove, result, t) +} + +//-- + +func TestDefaultLimitedPriorityHashQueueTwice(t *testing.T) { + testDefaultQueueTwice(NewDefaultLimitedPriorityHashQueue(), t) +} + +func TestPriorityLimitedPriorityHashQueueTwice(t *testing.T) { + testPriorityQueueTwice(NewPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueNoLimitTwice(t *testing.T) { + testDefaultQueueTwice(NewLimitLimitedPriorityHashQueue(150), t) +} + +func TestLimitLimitedPriorityHashQueueTwice(t *testing.T) { + limit := 80 + elementsToAddSingle := 50 + indexDiff := 2*elementsToAddSingle - limit + q := NewLimitLimitedPriorityHashQueue(limit) + resultFun := func(index int) int { + return (index + indexDiff) % elementsToAddSingle + } + testQueueTwice(q, elementsToAddSingle, alwaysTrueFun, limit, resultFun, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueNoLimitTwice(t *testing.T) { + testPriorityQueueTwice(func(priorityFun func(i interface{}) bool) Queue { + return NewLimitPriorityLimitedPriorityHashQueue(priorityFun, 150) + }, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueTwice(t *testing.T) { + limit := 80 + elementsToAddSingle := 50 + q := NewLimitPriorityLimitedPriorityHashQueue(priorityFunMod3, limit) + resultFun := func(index int) int { + if index <= 16 { + return 48 - 3*index + } else if index <= 33 { + return 99 - 3*index + } else if index <= 46 { + if index%2 == 0 { + return 3*index/2 - 20 + } + return (3*index - 41) / 2 + } else { + if index%2 == 1 { + return (3*index - 139) / 2 + } + return 3*index/2 - 70 + } + } + testQueueTwice(q, elementsToAddSingle, alwaysTrueFun, limit, resultFun, t) +} + +func TestHashLimitedPriorityHashQueueTwice(t *testing.T) { + testHashQueueTwice(NewHashLimitedPriorityHashQueue, t) +} + +func TestPriorityHashLimitedPriorityHashQueueTwice(t *testing.T) { + testPriorityHashQueueTwice(NewPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueNoLimitTwice(t *testing.T) { + testHashQueueTwice(func(hashNeeded bool) Queue { return NewLimitHashLimitedPriorityHashQueue(80, hashNeeded) }, t) +} + +func TestLimitHashLimitedPriorityHashQueueTwice(t *testing.T) { + limit := 30 + elementsToAddSingle := 50 + indexDiff := elementsToAddSingle - limit + resultFun := func(index int) int { return index + indexDiff } + q := NewLimitHashLimitedPriorityHashQueue(limit, true) + testQueueTwice(q, elementsToAddSingle, alwaysTrueFun, limit, resultFun, t) +} + +func TestLimitedPriorityHashQueueNoLimitTwice(t *testing.T) { + testPriorityHashQueueTwice(func(priorityFun func(i interface{}) bool, hashNeeded bool) Queue { + return NewLimitedPriorityHashQueue(priorityFun, 80, hashNeeded) + }, t) +} + +func TestLimitedPriorityHashQueueTwice(t *testing.T) { + limit := 30 + elementsToAddSingle := 50 + q := NewLimitedPriorityHashQueue(priorityFunMod3, limit, true) + addResultFun := func(index int) bool { return (index < elementsToAddSingle) || ((index-elementsToAddSingle)%3 != 0) } + resultFun := func(index int) int { + if index <= 16 { + return 48 - 3*index + } + if index%2 == 1 { + return (3*index + 11) / 2 + } + return 3*index/2 + 5 + } + testQueueTwice(q, elementsToAddSingle, addResultFun, limit, resultFun, t) +} + +func testHashQueueTwice(makeHashQueueFun func(hashNeeded bool) Queue, t *testing.T) { + q := makeHashQueueFun(true) + elementsToAddSingle := 50 + addResultFun := func(index int) bool { return index < elementsToAddSingle } + testQueueTwice(q, elementsToAddSingle, addResultFun, elementsToAddSingle, identityFunInt, t) +} + +func testPriorityHashQueueTwice(makePriorityHashQueueFun func(priorityFun func(i interface{}) bool, hashNeeded bool) Queue, t *testing.T) { + q := makePriorityHashQueueFun(priorityFunMod3, true) + elementsToAddSingle := 50 + addResultFun := func(index int) bool { return index < elementsToAddSingle } + resultFun := func(index int) int { + if index <= 16 { + return 48 - 3*index + } + if index%2 == 1 { + return (3*index - 49) / 2 + } + return 3*index/2 - 25 + } + testQueueTwice(q, elementsToAddSingle, addResultFun, elementsToAddSingle, resultFun, t) +} + +func testPriorityQueueTwice(makePriorityQueueFun func(func(i interface{}) bool) Queue, t *testing.T) { + q := makePriorityQueueFun(priorityFunMod3) + elementsToAddSingle := 50 + resultFun := func(index int) int { + if index <= 16 { + return 48 - 3*index + } else if index <= 33 { + return 99 - 3*index + } else if index <= 66 { + if index%2 == 0 { + return 3*index/2 - 50 + } + return (3*index - 101) / 2 + } else { + if index%2 == 1 { + return (3*index - 199) / 2 + } + return 3*index/2 - 100 + } + } + testQueueTwice(q, elementsToAddSingle, alwaysTrueFun, 2*elementsToAddSingle, resultFun, t) +} + +func testDefaultQueueTwice(q Queue, t *testing.T) { + elementsToAddSingle := 50 + resultFun := func(index int) int { return index % elementsToAddSingle } + testQueueTwice(q, elementsToAddSingle, alwaysTrueFun, 2*elementsToAddSingle, resultFun, t) +} + +func testQueueTwice(q Queue, elementsToAddSingle int, addResult func(index int) bool, elementsToRemove int, result func(index int) int, t *testing.T) { + addFun := func(index int) int { + return index % elementsToAddSingle + } + testQueueBasicAddLengthPeekRemove(q, 2*elementsToAddSingle, addFun, addResult, elementsToRemove, result, t) +} + +//-- + +func TestLimitPriorityLimitedPriorityHashQueueOverflow(t *testing.T) { + limit := 30 + elementsToAddSingle := 50 + cutOff := elementsToAddSingle / 2 + cutOffSh := SimpleHashable(cutOff) + q := NewLimitPriorityLimitedPriorityHashQueue(func(i interface{}) bool { + return i.(SimpleHashable) < cutOffSh + }, limit) + addResultFun := func(index int) bool { + return index < elementsToAddSingle+cutOff + } + resultFun := func(index int) int { + if index < 25 { + return 24 - index + } + return 49 - index + } + testQueueTwice(q, elementsToAddSingle, addResultFun, limit, resultFun, t) +} + +func TestLimitedPriorityHashQueueOverflow(t *testing.T) { + limit := 30 + elementsToAddSingle := 50 + cutOffLow := SimpleHashable(20) + cutOffHigh := SimpleHashable(40) + q := NewLimitedPriorityHashQueue(func(i interface{}) bool { + value := i.(SimpleHashable) + return value < cutOffLow || cutOffHigh <= value + }, limit, true) + addResultFun := func(index int) bool { + return index < elementsToAddSingle + } + resultFun := func(index int) int { + if index < 10 { + return 49 - index + } + return 29 - index + } + testQueueTwice(q, elementsToAddSingle, addResultFun, limit, resultFun, t) +} + +//-- + +func TestLimitedPriorityHashQueueDuplicates(t *testing.T) { + limit := 80 + elementsToAddFirstIteration := 50 + q := NewLimitedPriorityHashQueue(priorityFunMod3, limit, true) + addFun := func(index int) int { + if index < elementsToAddFirstIteration { + return 2 * index + } + return index - elementsToAddFirstIteration + } + addResultFun := func(index int) bool { + return (index < elementsToAddFirstIteration) || ((index-elementsToAddFirstIteration)%2 == 1) + } + resultFun := func(index int) int { + if index <= 16 { + return 99 - 6*index + } else if index <= 33 { + return 198 - 6*index + } else if index <= 46 { + if index%2 == 0 { + return 3*index - 40 + } + return 3*index - 41 + } else { + if index%2 == 0 { + return 3*index - 139 + } + return 3*index - 140 + } + } + testQueueBasicAddLengthPeekRemove(q, 3*elementsToAddFirstIteration, addFun, addResultFun, limit, resultFun, t) +} + +//-- + +func TestDefaultLimitedPriorityHashQueueAddRemove(t *testing.T) { + testDefaultQueueAddRemove(NewDefaultLimitedPriorityHashQueue(), t) +} + +func TestPriorityLimitedPriorityHashQueueAddRemove(t *testing.T) { + testPriorityQueueAddRemove(NewPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueNoLimitAddRemove(t *testing.T) { + testLimitedQueueNoLimitAddRemove(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueAddRemove(t *testing.T) { + testLimitedQueueAddRemove(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueNoLimitAddRemove(t *testing.T) { + testLimitedPriorityQueueNoLimitAddRemove(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueAddRemove(t *testing.T) { + testLimitedPriorityQueueAddRemove(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestHashLimitedPriorityHashQueueAddRemove(t *testing.T) { + testDefaultQueueAddRemove(NewHashLimitedPriorityHashQueue(true), t) +} + +func TestPriorityHashLimitedPriorityHashQueueAddRemove(t *testing.T) { + testPriorityQueueAddRemove(newPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueNoLimitAddRemove(t *testing.T) { + testLimitedQueueNoLimitAddRemove(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueAddRemove(t *testing.T) { + testLimitedQueueAddRemove(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueNoLimitAddRemove(t *testing.T) { + testLimitedPriorityQueueNoLimitAddRemove(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueAddRemove(t *testing.T) { + testLimitedPriorityQueueAddRemove(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func testLimitedPriorityQueueNoLimitAddRemove(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + testPriorityQueueAddRemove(func(priorityFun func(i interface{}) bool) Queue { return makeLimitedPriorityQueueFun(priorityFun, 150) }, t) +} + +func testLimitedPriorityQueueAddRemove(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + limit := 80 + q := makeLimitedPriorityQueueFun(priorityFunMod3, limit) + result := func(index int) int { + if index%2 == 0 { + return 3*index/2 + 31 + } + return (3*index + 61) / 2 + } + testQueueAddRemove(q, 100, 50, limit, result, t) +} + +func testLimitedQueueNoLimitAddRemove(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + testDefaultQueueAddRemove(makeLimitedQueueFun(150), t) +} + +func testLimitedQueueAddRemove(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + limit := 80 + elementsToAdd := 100 + elementsToRemoveAdd := 50 + indexDiff := elementsToAdd - limit + elementsToRemoveAdd + q := makeLimitedQueueFun(limit) + result := func(index int) int { + return index + indexDiff + } + testQueueAddRemove(q, elementsToAdd, elementsToRemoveAdd, limit, result, t) +} + +func testPriorityQueueAddRemove(makePriorityQueueFun func(func(i interface{}) bool) Queue, t *testing.T) { + q := makePriorityQueueFun(priorityFunMod3) + result := func(index int) int { + if index%2 == 0 { + return 3*index/2 + 1 + } + return (3*index + 1) / 2 + } + elementsToAdd := 100 + testQueueAddRemove(q, elementsToAdd, 50, elementsToAdd, result, t) +} + +func testDefaultQueueAddRemove(q Queue, t *testing.T) { + elementsToAdd := 100 + elementsToRemoveAdd := 50 + testQueueAddRemove(q, elementsToAdd, elementsToRemoveAdd, elementsToAdd, func(index int) int { return index + elementsToRemoveAdd }, t) +} + +func testQueueAddRemove(q Queue, elementsToAdd, elementsToRemoveAdd, elementsToRemove int, result func(index int) int, t *testing.T) { + for i := 0; i < elementsToAdd; i++ { + require.Truef(t, q.Add(SimpleHashable(i)), "failed to add element %d", i) + } + for i := 0; i < elementsToRemoveAdd; i++ { + q.Remove() + add := elementsToAdd + i + require.Truef(t, q.Add(SimpleHashable(add)), "failed to add element %d", add) + } + fullLength := q.Length() + require.Equalf(t, elementsToRemove, fullLength, "full queue length missmatch") + + for i := 0; i < elementsToRemove; i++ { + expected := SimpleHashable(result(i)) + peekResult := q.Peek().(SimpleHashable) + require.Equalf(t, expected, peekResult, "peek %d missmatch", i) + removeResult := q.Remove().(SimpleHashable) + require.Equalf(t, expected, removeResult, "remove %d missmatch", i) + } + emptyLength := q.Length() + require.Equalf(t, 0, emptyLength, "empty queue length missmatch") +} + +//-- + +func TesDefaultLimitedPriorityHashQueueLength(t *testing.T) { + testDefaultQueueLength(NewDefaultLimitedPriorityHashQueue(), t) +} + +func TestPriorityLimitedPriorityHashQueueLength(t *testing.T) { + testPriorityQueueLength(NewPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueNoLimitLength(t *testing.T) { + testLimitedQueueNoLimitLength(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueLength(t *testing.T) { + testLimitedQueueLength(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueNoLimitLength(t *testing.T) { + testLimitedPriorityQueueNoLimitLength(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueLength(t *testing.T) { + testLimitedPriorityQueueLength(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TesHashLimitedPriorityHashQueueLength(t *testing.T) { + testDefaultQueueLength(NewHashLimitedPriorityHashQueue(true), t) +} + +func TestPriorityHashLimitedPriorityHashQueueLength(t *testing.T) { + testPriorityQueueLength(newPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueNoLimitLength(t *testing.T) { + testLimitedQueueNoLimitLength(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueLength(t *testing.T) { + testLimitedQueueLength(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueNoLimitLength(t *testing.T) { + testLimitedPriorityQueueNoLimitLength(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueLength(t *testing.T) { + testLimitedPriorityQueueLength(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func testLimitedPriorityQueueNoLimitLength(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + testPriorityQueueLength(func(priorityFun func(i interface{}) bool) Queue { + return makeLimitedPriorityQueueFun(priorityFun, 1500) + }, t) +} + +func testLimitedPriorityQueueLength(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + limit := 800 + q := makeLimitedPriorityQueueFun(priorityFunMod3, limit) + testQueueLength(q, 1000, limit, t) +} + +func testLimitedQueueNoLimitLength(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + testDefaultQueueLength(makeLimitedQueueFun(1500), t) +} + +func testLimitedQueueLength(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + limit := 800 + q := makeLimitedQueueFun(limit) + testQueueLength(q, 1000, limit, t) +} + +func testPriorityQueueLength(makePriorityQueueFun func(func(i interface{}) bool) Queue, t *testing.T) { + q := makePriorityQueueFun(priorityFunMod3) + elementsToAdd := 1000 + testQueueLength(q, elementsToAdd, elementsToAdd, t) +} + +func testDefaultQueueLength(q Queue, t *testing.T) { + elementsToAdd := 1000 + testQueueLength(q, elementsToAdd, elementsToAdd, t) +} + +func testQueueLength(q Queue, elementsToRemoveAdd, elementsToRemove int, t *testing.T) { + emptyLength := q.Length() + require.Equalf(t, 0, emptyLength, "empty queue length missmatch") + + for i := 0; i < elementsToRemoveAdd; i++ { + require.Truef(t, q.Add(SimpleHashable(i)), "failed to add element %d", i) + var expected int + if i >= elementsToRemove { + expected = elementsToRemove + } else { + expected = i + 1 + } + currLength := q.Length() + require.Equalf(t, expected, currLength, "adding %d: expected queue length missmatch", i) + } + for i := 0; i < elementsToRemove; i++ { + q.Remove() + currLength := q.Length() + require.Equalf(t, elementsToRemove-i-1, currLength, "removing %d: expected queue length missmatch", i) + } +} + +//-- + +func TestDefaultLimitedPriorityHashQueueGet(t *testing.T) { + testDefaultQueueGet(NewDefaultLimitedPriorityHashQueue(), t) +} + +func TestPriorityLimitedPriorityHashQueueGet(t *testing.T) { + testPriorityQueueGet(NewPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueNoLimitGet(t *testing.T) { + testLimitedQueueNoLimitGet(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueGet(t *testing.T) { + testLimitedQueueGet(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueNoLimitGet(t *testing.T) { + testLimitedPriorityQueueNoLimitGet(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueGet(t *testing.T) { + testLimitedPriorityQueueGet(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestHashLimitedPriorityHashQueueGet(t *testing.T) { + testDefaultQueueGet(NewHashLimitedPriorityHashQueue(true), t) +} + +func TestPriorityHashLimitedPriorityHashQueueGet(t *testing.T) { + testPriorityQueueGet(newPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueNoLimitGet(t *testing.T) { + testLimitedQueueNoLimitGet(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueGet(t *testing.T) { + testLimitedQueueGet(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueNoLimitGet(t *testing.T) { + testLimitedPriorityQueueNoLimitGet(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueGet(t *testing.T) { + testLimitedPriorityQueueGet(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func testLimitedPriorityQueueNoLimitGet(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + testPriorityQueueGet(func(priorityFun func(i interface{}) bool) Queue { + return makeLimitedPriorityQueueFun(priorityFun, 1500) + }, t) +} + +func testLimitedPriorityQueueGet(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + limit := 800 + q := makeLimitedPriorityQueueFun(priorityFunMod2, limit) + result := func(iteration int, index int) int { + if index <= iteration/2 { + return iteration - iteration%2 - 2*index + } + if iteration < limit { + return -iteration + iteration%2 + 2*index - 1 + } + return iteration + iteration%2 + 2*index - 2*limit + 1 + } + testQueueGet(q, 1000, result, t) +} + +func testLimitedQueueNoLimitGet(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + testDefaultQueueGet(makeLimitedQueueFun(1500), t) +} + +func testLimitedQueueGet(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + limit := 800 + q := makeLimitedQueueFun(limit) + result := func(iteration int, index int) int { + if iteration < limit { + return index + } + return index + iteration - limit + 1 + } + testQueueGet(q, 1000, result, t) +} + +func testPriorityQueueGet(makePriorityQueueFun func(func(i interface{}) bool) Queue, t *testing.T) { + q := makePriorityQueueFun(priorityFunMod2) + result := func(iteration int, index int) int { + if index <= iteration/2 { + return iteration - iteration%2 - 2*index + } + return -iteration + iteration%2 + 2*index - 1 + } + testQueueGet(q, 1000, result, t) +} + +func testDefaultQueueGet(q Queue, t *testing.T) { + testQueueGet(q, 1000, func(iteration int, index int) int { return index }, t) +} + +func testQueueGet(q Queue, elementsToAdd int, result func(iteration int, index int) int, t *testing.T) { + if testing.Short() { + t.Skip("skipping Get test in short mode") // although it is not clear, why. Replacing require.Equalf in this code with `if a != b {t.Errorf(...)}` increases this test's performance significantly + } + for i := 0; i < elementsToAdd; i++ { + require.Truef(t, q.Add(SimpleHashable(i)), "failed to add element %d", i) + for j := 0; j < q.Length(); j++ { + require.Equalf(t, SimpleHashable(result(i, j)), q.Get(j).(SimpleHashable), "iteration %d index %d missmatch", i, j) + } + } +} + +//-- + +func TestDefaultLimitedPriorityHashQueueGetNegative(t *testing.T) { + testDefaultQueueGetNegative(NewDefaultLimitedPriorityHashQueue(), t) +} + +func TestPriorityLimitedPriorityHashQueueGetNegative(t *testing.T) { + testPriorityQueueGetNegative(NewPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueNoLimitGetNegative(t *testing.T) { + testLimitedQueueNoLimitGetNegative(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueGetNegative(t *testing.T) { + testLimitedQueueGetNegative(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueNoLimitGetNegative(t *testing.T) { + testLimitedPriorityQueueNoLimitGetNegative(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueGetNegative(t *testing.T) { + testLimitedPriorityQueueGetNegative(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestHashLimitedPriorityHashQueueGetNegative(t *testing.T) { + testDefaultQueueGetNegative(NewHashLimitedPriorityHashQueue(true), t) +} + +func TestPriorityHashLimitedPriorityHashQueueGetNegative(t *testing.T) { + testPriorityQueueGetNegative(newPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueNoLimitGetNegative(t *testing.T) { + testLimitedQueueNoLimitGetNegative(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueGetNegative(t *testing.T) { + testLimitedQueueGetNegative(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueNoLimitGetNegative(t *testing.T) { + testLimitedPriorityQueueNoLimitGetNegative(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueGetNegative(t *testing.T) { + testLimitedPriorityQueueGetNegative(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func testLimitedPriorityQueueNoLimitGetNegative(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + testPriorityQueueGetNegative(func(priorityFun func(i interface{}) bool) Queue { + return makeLimitedPriorityQueueFun(priorityFun, 1500) + }, t) +} + +func testLimitedPriorityQueueGetNegative(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + limit := 800 + q := makeLimitedPriorityQueueFun(priorityFunMod2, limit) + result := func(iteration int, index int) int { + if iteration < limit { + if index >= -(iteration+iteration%2)/2 { + return iteration + iteration%2 + 2*index + 1 + } + return -iteration - iteration%2 - 2*index - 2 + } + if index <= (iteration-iteration%2)/2-limit { + return iteration - iteration%2 - 2*index - 2*limit + } + return iteration + iteration%2 + 2*index + 1 + } + testQueueGetNegative(q, 1000, result, t) +} + +func testLimitedQueueNoLimitGetNegative(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + testDefaultQueueGetNegative(makeLimitedQueueFun(1500), t) +} + +func testLimitedQueueGetNegative(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + testDefaultQueueGetNegative(makeLimitedQueueFun(800), t) +} + +func testPriorityQueueGetNegative(makePriorityQueueFun func(func(i interface{}) bool) Queue, t *testing.T) { + q := makePriorityQueueFun(priorityFunMod2) + result := func(iteration int, index int) int { + if index >= -(iteration+iteration%2)/2 { + return iteration + iteration%2 + 2*index + 1 + } + return -iteration - iteration%2 - 2*index - 2 + } + testQueueGetNegative(q, 1000, result, t) +} + +func testDefaultQueueGetNegative(q Queue, t *testing.T) { + testQueueGetNegative(q, 1000, func(iteration int, index int) int { return iteration + index + 1 }, t) +} + +func testQueueGetNegative(q Queue, elementsToAdd int, result func(iteration int, index int) int, t *testing.T) { + if testing.Short() { + t.Skip("skipping GetNegative test in short mode") // although it is not clear, why. Replacing require.Equalf in this code with `if a != b {t.Errorf(...)}` increases this test's performance significantly + } + for i := 0; i < elementsToAdd; i++ { + require.Truef(t, q.Add(SimpleHashable(i)), "failed to add element %d", i) + for j := -1; j >= -q.Length(); j-- { + require.Equalf(t, SimpleHashable(result(i, j)), q.Get(j).(SimpleHashable), "iteration %d index %d missmatch", i, j) + } + } +} + +//-- + +func TestDefaultLimitedPriorityHashQueueGetOutOfRangePanics(t *testing.T) { + testQueueGetOutOfRangePanics(NewDefaultLimitedPriorityHashQueue(), t) +} + +func TestPriorityLimitedPriorityHashQueueGetOutOfRangePanics(t *testing.T) { + testPriorityQueueGetOutOfRangePanics(NewPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueGetOutOfRangePanics(t *testing.T) { + testLimitedQueueGetOutOfRangePanics(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueGetOutOfRangePanics(t *testing.T) { + testLimitedPriorityQueueGetOutOfRangePanics(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestHashLimitedPriorityHashQueueGetOutOfRangePanics(t *testing.T) { + testQueueGetOutOfRangePanics(NewHashLimitedPriorityHashQueue(true), t) +} + +func TestPriorityHashLimitedPriorityHashQueueGetOutOfRangePanics(t *testing.T) { + testPriorityQueueGetOutOfRangePanics(newPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueGetOutOfRangePanics(t *testing.T) { + testLimitedQueueGetOutOfRangePanics(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueGetOutOfRangePanics(t *testing.T) { + testLimitedPriorityQueueGetOutOfRangePanics(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func testLimitedPriorityQueueGetOutOfRangePanics(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + q := makeLimitedPriorityQueueFun(priorityFunMod2, 800) + testQueueGetOutOfRangePanics(q, t) +} + +func testLimitedQueueGetOutOfRangePanics(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + testQueueGetOutOfRangePanics(makeLimitedQueueFun(800), t) +} + +func testPriorityQueueGetOutOfRangePanics(makePriorityQueueFun func(func(i interface{}) bool) Queue, t *testing.T) { + q := makePriorityQueueFun(priorityFunMod2) + testQueueGetOutOfRangePanics(q, t) +} + +func testQueueGetOutOfRangePanics(q Queue, t *testing.T) { + for i := 0; i < 3; i++ { + require.Truef(t, q.Add(SimpleHashable(i)), "failed to add element %d", i) + } + require.Panicsf(t, func() { q.Get(-4) }, "should panic when too negative index") + require.Panicsf(t, func() { q.Get(4) }, "should panic when index greater than length") +} + +//-- + +func TestDefaultLimitedPriorityHashQueuePeekOutOfRangePanics(t *testing.T) { + testQueuePeekOutOfRangePanics(NewDefaultLimitedPriorityHashQueue(), t) +} + +func TestPriorityLimitedPriorityHashQueuePeekOutOfRangePanics(t *testing.T) { + testPriorityQueuePeekOutOfRangePanics(NewPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueuePeekOutOfRangePanics(t *testing.T) { + testLimitedQueuePeekOutOfRangePanics(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueuePeekOutOfRangePanics(t *testing.T) { + testLimitedPriorityQueuePeekOutOfRangePanics(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestHashtLimitedPriorityHashQueuePeekOutOfRangePanics(t *testing.T) { + testQueuePeekOutOfRangePanics(NewHashLimitedPriorityHashQueue(true), t) +} + +func TestPriorityHashLimitedPriorityHashQueuePeekOutOfRangePanics(t *testing.T) { + testPriorityQueuePeekOutOfRangePanics(newPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueuePeekOutOfRangePanics(t *testing.T) { + testLimitedQueuePeekOutOfRangePanics(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueuePeekOutOfRangePanics(t *testing.T) { + testLimitedPriorityQueuePeekOutOfRangePanics(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func testLimitedPriorityQueuePeekOutOfRangePanics(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + q := makeLimitedPriorityQueueFun(priorityFunMod2, 800) + testQueuePeekOutOfRangePanics(q, t) +} + +func testLimitedQueuePeekOutOfRangePanics(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + testQueuePeekOutOfRangePanics(makeLimitedQueueFun(800), t) +} + +func testPriorityQueuePeekOutOfRangePanics(makePriorityQueueFun func(func(i interface{}) bool) Queue, t *testing.T) { + q := makePriorityQueueFun(priorityFunMod2) + testQueuePeekOutOfRangePanics(q, t) +} + +func testQueuePeekOutOfRangePanics(q Queue, t *testing.T) { + require.Panicsf(t, func() { q.Peek() }, "should panic when peeking empty queue") + require.Truef(t, q.Add(SimpleHashable(0)), "failed to add element 0") + q.Remove() + require.Panicsf(t, func() { q.Peek() }, "should panic when peeking emptied queue") +} + +//-- + +func TestDefaultLimitedPriorityHashQueueRemoveOutOfRangePanics(t *testing.T) { + testQueueRemoveOutOfRangePanics(NewDefaultLimitedPriorityHashQueue(), t) +} + +func TestPriorityLimitedPriorityHashQueueRemoveOutOfRangePanics(t *testing.T) { + testPriorityQueueRemoveOutOfRangePanics(NewPriorityLimitedPriorityHashQueue, t) +} + +func TestLimitLimitedPriorityHashQueueRemoveOutOfRangePanics(t *testing.T) { + testLimitedQueueRemoveOutOfRangePanics(NewLimitLimitedPriorityHashQueue, t) +} + +func TestLimitPriorityLimitedPriorityHashQueueRemoveOutOfRangePanics(t *testing.T) { + testLimitedPriorityQueueRemoveOutOfRangePanics(NewLimitPriorityLimitedPriorityHashQueue, t) +} + +func TestHashLimitedPriorityHashQueueRemoveOutOfRangePanics(t *testing.T) { + testQueueRemoveOutOfRangePanics(NewHashLimitedPriorityHashQueue(true), t) +} + +func TestPriorityHashLimitedPriorityHashQueueRemoveOutOfRangePanics(t *testing.T) { + testPriorityQueueRemoveOutOfRangePanics(newPriorityHashLimitedPriorityHashQueue, t) +} + +func TestLimitHashLimitedPriorityHashQueueRemoveOutOfRangePanics(t *testing.T) { + testLimitedQueueRemoveOutOfRangePanics(newLimitHashLimitedPriorityHashQueue, t) +} + +func TestLimitedPriorityHashQueueRemoveOutOfRangePanics(t *testing.T) { + testLimitedPriorityQueueRemoveOutOfRangePanics(newLimitPriorityHashLimitedPriorityHashQueue, t) +} + +func testLimitedPriorityQueueRemoveOutOfRangePanics(makeLimitedPriorityQueueFun func(priorityFun func(i interface{}) bool, limit int) Queue, t *testing.T) { + q := makeLimitedPriorityQueueFun(priorityFunMod2, 800) + testQueueRemoveOutOfRangePanics(q, t) +} + +func testLimitedQueueRemoveOutOfRangePanics(makeLimitedQueueFun func(limit int) Queue, t *testing.T) { + testQueueRemoveOutOfRangePanics(makeLimitedQueueFun(800), t) +} + +func testPriorityQueueRemoveOutOfRangePanics(makePriorityQueueFun func(func(i interface{}) bool) Queue, t *testing.T) { + q := makePriorityQueueFun(priorityFunMod2) + testQueueRemoveOutOfRangePanics(q, t) +} + +func testQueueRemoveOutOfRangePanics(q Queue, t *testing.T) { + require.Panicsf(t, func() { q.Remove() }, "should panic when removing empty queue") + require.Truef(t, q.Add(SimpleHashable(0)), "failed to add element 0") + q.Remove() + require.Panicsf(t, func() { q.Remove() }, "should panic when removing emptied queue") +} + +//-- + +func newPriorityHashLimitedPriorityHashQueue(priorityFun func(i interface{}) bool) Queue { + return NewPriorityHashLimitedPriorityHashQueue(priorityFun, true) +} + +func newLimitHashLimitedPriorityHashQueue(limit int) Queue { + return NewLimitHashLimitedPriorityHashQueue(limit, true) +} + +func newLimitPriorityHashLimitedPriorityHashQueue(priorityFun func(i interface{}) bool, limit int) Queue { + return NewLimitedPriorityHashQueue(priorityFun, limit, true) +} diff --git a/packages/util/pipe/test_util.go b/packages/util/pipe/test_util.go new file mode 100644 index 0000000000..36ed7efb1b --- /dev/null +++ b/packages/util/pipe/test_util.go @@ -0,0 +1,39 @@ +package pipe + +import ( + "encoding/binary" + + "github.com/iotaledger/wasp/packages/hashing" +) + +type SimpleHashable int + +var _ Hashable = SimpleHashable(0) + +func (sh SimpleHashable) GetHash() hashing.HashValue { + bin := make([]byte, binary.MaxVarintLen64) + binary.PutVarint(bin, int64(sh)) + return hashing.HashData(bin) +} + +//-- + +func identityFunInt(index int) int { + return index +} + +func alwaysTrueFun(index int) bool { + return true +} + +func priorityFunMod2(i interface{}) bool { + return priorityFunMod(i, 2) +} + +func priorityFunMod3(i interface{}) bool { + return priorityFunMod(i, 3) +} + +func priorityFunMod(i interface{}, mod SimpleHashable) bool { + return i.(SimpleHashable)%mod == 0 +} diff --git a/packages/util/rwutil.go b/packages/util/rwutil.go index 5183e88714..1ffcfbc25c 100644 --- a/packages/util/rwutil.go +++ b/packages/util/rwutil.go @@ -29,6 +29,42 @@ func WriteByte(w io.Writer, val byte) error { return err } +//////////////////// uint8 \\\\\\\\\\\\\\\\\\\\ + +func Uint8To1Bytes(val uint8) []byte { + return []byte{val} +} + +func Uint8From1Bytes(b []byte) (uint8, error) { + if len(b) != 1 { + return 0, errors.New("len(b) != 1") + } + return b[0], nil +} + +func MustUint8From1Bytes(b []byte) uint8 { + ret, err := Uint8From1Bytes(b) + if err != nil { + panic(err) + } + return ret +} + +func ReadUint8(r io.Reader, pval *uint8) error { + var tmp2 [1]byte + _, err := r.Read(tmp2[:]) + if err != nil { + return err + } + *pval = tmp2[0] + return nil +} + +func WriteUint8(w io.Writer, val uint8) error { + _, err := w.Write(Uint8To1Bytes(val)) + return err +} + //////////////////// uint16 \\\\\\\\\\\\\\\\\\\\ func Uint16To2Bytes(val uint16) []byte { diff --git a/packages/vm/core/blocklog/blocklog_test.go b/packages/vm/core/blocklog/blocklog_test.go index b8cd3e72cf..3a97b9fbf0 100644 --- a/packages/vm/core/blocklog/blocklog_test.go +++ b/packages/vm/core/blocklog/blocklog_test.go @@ -13,7 +13,7 @@ import ( func TestSerdeRequestLogRecord(t *testing.T) { var txid ledgerstate.TransactionID rand.Read(txid[:]) - req := request.NewOffLedger(iscp.Hn("0"), iscp.Hn("0"), nil) + req := request.NewOffLedger(iscp.RandomChainID(), iscp.Hn("0"), iscp.Hn("0"), nil) rec := &RequestReceipt{ Request: req, Error: "some log data", diff --git a/packages/vm/core/governance/accessnodes.go b/packages/vm/core/governance/accessnodes.go new file mode 100644 index 0000000000..39afeea870 --- /dev/null +++ b/packages/vm/core/governance/accessnodes.go @@ -0,0 +1,208 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package governance + +import ( + "bytes" + + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/hive.go/crypto/ed25519" + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/kv/codec" + "github.com/iotaledger/wasp/packages/kv/collections" + "github.com/iotaledger/wasp/packages/kv/dict" + "github.com/iotaledger/wasp/packages/kv/kvdecoder" + "github.com/iotaledger/wasp/packages/util" + "golang.org/x/xerrors" +) + +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. + Certificate []byte // Proof that Validator owns the Node. + ForCommittee bool // true, if Node should be a candidate to a committee. + AccessAPI string // API URL, if any. +} + +func NewAccessNodeInfoFromBytes(pubKey, value []byte) (*AccessNodeInfo, error) { + var a AccessNodeInfo + var err error + r := bytes.NewReader(value) + a.NodePubKey = pubKey // NodePubKey stored as a map key. + if a.ValidatorAddr, err = util.ReadBytes16(r); err != nil { + return nil, xerrors.Errorf("failed to read AccessNodeInfo.ValidatorAddr: %v", err) + } + if a.Certificate, err = util.ReadBytes16(r); err != nil { + return nil, xerrors.Errorf("failed to read AccessNodeInfo.Certificate: %v", err) + } + if err := util.ReadBoolByte(r, &a.ForCommittee); err != nil { + return nil, xerrors.Errorf("failed to read AccessNodeInfo.ForCommittee: %v", err) + } + if a.AccessAPI, err = util.ReadString16(r); err != nil { + return nil, xerrors.Errorf("failed to read AccessNodeInfo.AccessAPI: %v", err) + } + return &a, nil +} + +func (a *AccessNodeInfo) Bytes() []byte { + w := bytes.Buffer{} + // NodePubKey stored as a map key. + if err := util.WriteBytes16(&w, a.ValidatorAddr); err != nil { + panic(xerrors.Errorf("failed to write AccessNodeInfo.ValidatorAddr: %v", err)) + } + if err := util.WriteBytes16(&w, a.Certificate); err != nil { + panic(xerrors.Errorf("failed to write AccessNodeInfo.Certificate: %v", err)) + } + if err := util.WriteBoolByte(&w, a.ForCommittee); err != nil { + panic(xerrors.Errorf("failed to write AccessNodeInfo.ForCommittee: %v", err)) + } + if err := util.WriteString16(&w, a.AccessAPI); err != nil { + panic(xerrors.Errorf("failed to write AccessNodeInfo.AccessAPI: %v", err)) + } + return w.Bytes() +} + +func NewAccessNodeInfoFromAddCandidateNodeParams(ctx iscp.Sandbox) *AccessNodeInfo { + params := kvdecoder.New(ctx.Params(), ctx.Log()) + ani := AccessNodeInfo{ + NodePubKey: params.MustGetBytes(ParamAccessNodeInfoPubKey), + ValidatorAddr: ctx.Request().SenderAddress().Bytes(), // Not from params, to have it validated. + Certificate: params.MustGetBytes(ParamAccessNodeInfoCertificate), + ForCommittee: params.MustGetBool(ParamAccessNodeInfoForCommittee, false), + AccessAPI: params.MustGetString(ParamAccessNodeInfoAccessAPI, ""), + } + return &ani +} + +func (a *AccessNodeInfo) ToAddCandidateNodeParams() dict.Dict { + d := dict.New() + d.Set(ParamAccessNodeInfoForCommittee, codec.EncodeBool(a.ForCommittee)) + d.Set(ParamAccessNodeInfoPubKey, a.NodePubKey) + d.Set(ParamAccessNodeInfoCertificate, a.Certificate) + d.Set(ParamAccessNodeInfoAccessAPI, codec.EncodeString(a.AccessAPI)) + return d +} + +func NewAccessNodeInfoFromRevokeAccessNodeParams(ctx iscp.Sandbox) *AccessNodeInfo { + params := kvdecoder.New(ctx.Params(), ctx.Log()) + ani := AccessNodeInfo{ + NodePubKey: params.MustGetBytes(ParamAccessNodeInfoPubKey), + ValidatorAddr: ctx.Request().SenderAddress().Bytes(), // Not from params, to have it validated. + Certificate: params.MustGetBytes(ParamAccessNodeInfoCertificate), + } + return &ani +} + +func (a *AccessNodeInfo) ToRevokeAccessNodeParams() dict.Dict { + d := dict.New() + d.Set(ParamAccessNodeInfoPubKey, a.NodePubKey) + d.Set(ParamAccessNodeInfoCertificate, a.Certificate) + 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() + 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) +} + +// +// GetChainNodesRequest +// +type GetChainNodesRequest struct{} + +func (req GetChainNodesRequest) AsDict() dict.Dict { + return dict.New() +} + +// +// GetChainNodesResponse +// +type GetChainNodesResponse struct { + AccessNodeCandidates []*AccessNodeInfo // Application info for the AccessNodes. + AccessNodes []ed25519.PublicKey // Public Keys of Access Nodes. +} + +func NewGetChainNodesResponseFromDict(d dict.Dict) *GetChainNodesResponse { + res := GetChainNodesResponse{ + AccessNodeCandidates: make([]*AccessNodeInfo, 0), + AccessNodes: make([]ed25519.PublicKey, 0), + } + + ac := collections.NewMapReadOnly(d, ParamGetChainNodesAccessNodeCandidates) + ac.MustIterate(func(pubKey, value []byte) bool { + ani, err := NewAccessNodeInfoFromBytes(pubKey, value) + if err != nil { + panic(xerrors.Errorf("unable to decode access node info: %v", err)) + } + res.AccessNodeCandidates = append(res.AccessNodeCandidates, ani) + return true + }) + + an := collections.NewMapReadOnly(d, ParamGetChainNodesAccessNodes) + an.MustIterate(func(pubKeyBin, value []byte) bool { + pubKey, _, err := ed25519.PublicKeyFromBytes(pubKeyBin) + if err != nil { + panic(xerrors.Errorf("failed to decode pub key: %v", err)) + } + res.AccessNodes = append(res.AccessNodes, pubKey) + return true + }) + return &res +} + +// +// ChangeAccessNodesRequest +// + +type ChangeAccessNodeAction byte + +const ( + ChangeAccessNodeActionRemove = ChangeAccessNodeAction(iota) + ChangeAccessNodeActionAccept + ChangeAccessNodeActionDrop +) + +type ChangeAccessNodesRequest struct { + actions map[ed25519.PublicKey]ChangeAccessNodeAction +} + +func NewChangeAccessNodesRequest() *ChangeAccessNodesRequest { + return &ChangeAccessNodesRequest{ + actions: make(map[ed25519.PublicKey]ChangeAccessNodeAction), + } +} + +func (req *ChangeAccessNodesRequest) Remove(pubKey ed25519.PublicKey) *ChangeAccessNodesRequest { + req.actions[pubKey] = ChangeAccessNodeActionRemove + return req +} + +func (req *ChangeAccessNodesRequest) Accept(pubKey ed25519.PublicKey) *ChangeAccessNodesRequest { + req.actions[pubKey] = ChangeAccessNodeActionAccept + return req +} + +func (req *ChangeAccessNodesRequest) Drop(pubKey ed25519.PublicKey) *ChangeAccessNodesRequest { + req.actions[pubKey] = ChangeAccessNodeActionDrop + return req +} + +func (req *ChangeAccessNodesRequest) AsDict() dict.Dict { + d := dict.New() + actionsMap := collections.NewMap(d, ParamChangeAccessNodesActions) + for pubKey, action := range req.actions { + actionsMap.MustSetAt(pubKey.Bytes(), []byte{byte(action)}) + } + return d +} diff --git a/packages/vm/core/governance/chaininfo.go b/packages/vm/core/governance/chaininfo.go index 12a60d40c3..71d7b7642c 100644 --- a/packages/vm/core/governance/chaininfo.go +++ b/packages/vm/core/governance/chaininfo.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package governance import ( diff --git a/packages/vm/core/governance/contractfees.go b/packages/vm/core/governance/contractfees.go index d3a4f67b9d..4663d4205a 100644 --- a/packages/vm/core/governance/contractfees.go +++ b/packages/vm/core/governance/contractfees.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package governance import ( diff --git a/packages/vm/core/governance/governanceimpl/accessnodesImpl.go b/packages/vm/core/governance/governanceimpl/accessnodesImpl.go new file mode 100644 index 0000000000..bded42eb38 --- /dev/null +++ b/packages/vm/core/governance/governanceimpl/accessnodesImpl.go @@ -0,0 +1,120 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// This file provides implementation for the governance SC, the ChainNode +// management functions. +// +// State of the SC (the ChainNodes part): +// +// VarAccessNodeCandidates: map[pubKey] => AccessNodeInfo // A set of Access Node Info. +// VarAccessNodes: map[pubKey] => byte[0] // A set of nodes. +// VarValidatorNodes: pubKey[] // An ordered list of nodes. +// +package governanceimpl + +import ( + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/iscp/assert" + "github.com/iotaledger/wasp/packages/kv/collections" + "github.com/iotaledger/wasp/packages/kv/dict" + "github.com/iotaledger/wasp/packages/vm/core/governance" +) + +// SC Query Function handler. +// +// getChainNodes() => ( +// accessNodeCandidates :: map(pubKey => AccessNodeInfo), +// accessNodes :: map(pubKey => ()) +// ) +// +func getChainNodesFuncHandler(ctx iscp.SandboxView) (dict.Dict, error) { + res := dict.New() + ac := collections.NewMap(res, governance.ParamGetChainNodesAccessNodeCandidates) + an := collections.NewMap(res, governance.ParamGetChainNodesAccessNodes) + collections.NewMapReadOnly(ctx.State(), governance.VarAccessNodeCandidates).MustIterate(func(key, value []byte) bool { + ac.MustSetAt(key, value) + return true + }) + collections.NewMapReadOnly(ctx.State(), governance.VarAccessNodes).MustIterate(func(key, value []byte) bool { + an.MustSetAt(key, value) + return true + }) + return res, nil +} + +// SC Command Function handler. +// Can only be invoked by the access node owner (verified via the Certificate field). +// +// addCandidateNode( +// accessNodeInfo{NodePubKey, Certificate, ForCommittee, AccessAPI} +// ) => () +// +func addCandidateNodeFuncHandler(ctx iscp.Sandbox) (dict.Dict, error) { + a := assert.NewAssert(ctx.Log()) + + ani := governance.NewAccessNodeInfoFromAddCandidateNodeParams(ctx) + a.Require(ani.ValidateCertificate(ctx), "certificate invalid") + + accessNodeCandidates := collections.NewMap(ctx.State(), governance.VarAccessNodeCandidates) + accessNodeCandidates.MustSetAt(ani.NodePubKey, ani.Bytes()) + + return nil, nil +} + +// SC Command Function handler. +// Can only be invoked by the access node owner (verified via the Certificate field). +// +// revokeAccessNode( +// accessNodeInfo{NodePubKey, Certificate} +// ) => () +// +// It is possible that after executing `revokeAccessNode(...)` a node will stay +// in the list of validators, and will be absent in the candidate or an access node set. +// The node is removed from the list of access nodes immediately, but the validator rotation +// must be initiated by the chain owner explicitly. +// +func revokeAccessNodeFuncHandler(ctx iscp.Sandbox) (dict.Dict, error) { + a := assert.NewAssert(ctx.Log()) + + ani := governance.NewAccessNodeInfoFromRevokeAccessNodeParams(ctx) + a.Require(ani.ValidateCertificate(ctx), "certificate invalid") + + accessNodeCandidates := collections.NewMap(ctx.State(), governance.VarAccessNodeCandidates) + accessNodeCandidates.MustDelAt(ani.NodePubKey) + accessNodes := collections.NewMap(ctx.State(), governance.VarAccessNodes) + accessNodes.MustDelAt(ani.NodePubKey) + + return nil, nil +} + +// SC Command Function handler. +// Can only be invoked by the chain owner. +// +// changeAccessNodes( +// actions: map(pubKey => ChangeAccessNodeAction) +// ) => () +// +func changeAccessNodesFuncHandler(ctx iscp.Sandbox) (dict.Dict, error) { + a := assert.NewAssert(ctx.Log()) + a.RequireCaller(ctx, []*iscp.AgentID{ctx.ChainOwnerID()}) + + accessNodeCandidates := collections.NewMap(ctx.State(), governance.VarAccessNodeCandidates) + accessNodes := collections.NewMap(ctx.State(), governance.VarAccessNodes) + paramNodeActions := collections.NewMapReadOnly(ctx.Params(), governance.ParamChangeAccessNodesActions) + paramNodeActions.MustIterate(func(pubKey, actionBin []byte) bool { + a.Require(len(actionBin) == 1, "action should be a single byte") + switch governance.ChangeAccessNodeAction(actionBin[0]) { + case governance.ChangeAccessNodeActionRemove: + accessNodes.MustDelAt(pubKey) + case governance.ChangeAccessNodeActionAccept: + accessNodes.MustSetAt(pubKey, make([]byte, 0)) + case governance.ChangeAccessNodeActionDrop: + accessNodes.MustDelAt(pubKey) + accessNodeCandidates.MustDelAt(pubKey) + default: + a.Require(false, "unexpected action") + } + return true + }) + return nil, nil +} diff --git a/packages/vm/core/governance/governanceimpl/chaininfo.go b/packages/vm/core/governance/governanceimpl/chaininfo.go index a5f696a50e..8b2c8f3a64 100644 --- a/packages/vm/core/governance/governanceimpl/chaininfo.go +++ b/packages/vm/core/governance/governanceimpl/chaininfo.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package governanceimpl import ( diff --git a/packages/vm/core/governance/governanceimpl/chainowner.go b/packages/vm/core/governance/governanceimpl/chainowner.go index 3d1025cd20..b9182c4b17 100644 --- a/packages/vm/core/governance/governanceimpl/chainowner.go +++ b/packages/vm/core/governance/governanceimpl/chainowner.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package governanceimpl import ( diff --git a/packages/vm/core/governance/governanceimpl/fees.go b/packages/vm/core/governance/governanceimpl/fees.go index b50e300acd..c9c2f012ba 100644 --- a/packages/vm/core/governance/governanceimpl/fees.go +++ b/packages/vm/core/governance/governanceimpl/fees.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package governanceimpl import ( diff --git a/packages/vm/core/governance/governanceimpl/impl.go b/packages/vm/core/governance/governanceimpl/impl.go index 89e60ca158..26b260d12c 100644 --- a/packages/vm/core/governance/governanceimpl/impl.go +++ b/packages/vm/core/governance/governanceimpl/impl.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package governanceimpl import ( @@ -29,6 +32,12 @@ var Processor = governance.Contract.Processor(initialize, governance.FuncGetChainInfo.WithHandler(getChainInfo), governance.FuncSetChainInfo.WithHandler(setChainInfo), governance.FuncGetMaxBlobSize.WithHandler(getMaxBlobSize), + + // access nodes. + governance.FuncGetChainNodes.WithHandler(getChainNodesFuncHandler), + governance.FuncAddCandidateNode.WithHandler(addCandidateNodeFuncHandler), + governance.FuncRevokeAccessNode.WithHandler(revokeAccessNodeFuncHandler), + governance.FuncChangeAccessNodes.WithHandler(changeAccessNodesFuncHandler), ) func initialize(ctx iscp.Sandbox) (dict.Dict, error) { @@ -55,5 +64,6 @@ func initialize(ctx iscp.Sandbox) (dict.Dict, error) { if feeColorSet { state.Set(governance.VarFeeColor, codec.EncodeColor(feeColor)) } + return nil, nil } diff --git a/packages/vm/core/governance/governanceimpl/statecontroller.go b/packages/vm/core/governance/governanceimpl/statecontroller.go index 7b6eb46536..88c6e820e0 100644 --- a/packages/vm/core/governance/governanceimpl/statecontroller.go +++ b/packages/vm/core/governance/governanceimpl/statecontroller.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package governanceimpl import ( diff --git a/packages/vm/core/governance/interface.go b/packages/vm/core/governance/interface.go index 621a000092..9dc46f4be9 100644 --- a/packages/vm/core/governance/interface.go +++ b/packages/vm/core/governance/interface.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + // in the blocklog core contract the VM keeps indices of blocks and requests in an optimized way // for fast checking and timestamp access. package governance @@ -37,6 +40,12 @@ var ( FuncSetChainInfo = coreutil.Func("setChainInfo") FuncGetChainInfo = coreutil.ViewFunc("getChainInfo") FuncGetMaxBlobSize = coreutil.ViewFunc("getMaxBlobSize") + + // access nodes + FuncGetChainNodes = coreutil.ViewFunc("getChainNodes") + FuncAddCandidateNode = coreutil.Func("addCandidateNode") + FuncRevokeAccessNode = coreutil.Func("revokeAccessNode") + FuncChangeAccessNodes = coreutil.Func("changeAccessNodes") ) // state variables @@ -63,6 +72,11 @@ const ( VarMaxBlobSize = "mb" VarMaxEventSize = "me" VarMaxEventsPerReq = "mr" + + // access nodes + VarAccessNodes = "an" + VarAccessNodeCandidates = "ac" + VarValidatorNodes = "vn" ) // params @@ -86,4 +100,17 @@ const ( ParamMaxBlobSize = "bs" ParamMaxEventSize = "es" ParamMaxEventsPerRequest = "ne" + + // access nodes: getChainNodes + ParamGetChainNodesAccessNodeCandidates = "c" + ParamGetChainNodesAccessNodes = "a" + + // access nodes: addCandidateNode + ParamAccessNodeInfoForCommittee = "f" + ParamAccessNodeInfoPubKey = "p" + ParamAccessNodeInfoCertificate = "c" + ParamAccessNodeInfoAccessAPI = "a" + + // access nodes: changeAccessNodes + ParamChangeAccessNodesActions = "a" ) diff --git a/packages/vm/core/governance/internal.go b/packages/vm/core/governance/internal.go index bd224a14f7..b35c4a0c06 100644 --- a/packages/vm/core/governance/internal.go +++ b/packages/vm/core/governance/internal.go @@ -1,3 +1,6 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + package governance import ( diff --git a/packages/vm/core/root/rootimpl/impl.go b/packages/vm/core/root/rootimpl/impl.go index a57d23a132..62e39c9b56 100644 --- a/packages/vm/core/root/rootimpl/impl.go +++ b/packages/vm/core/root/rootimpl/impl.go @@ -11,6 +11,7 @@ import ( "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/assert" + "github.com/iotaledger/wasp/packages/kv/codec" "github.com/iotaledger/wasp/packages/kv/collections" "github.com/iotaledger/wasp/packages/kv/dict" "github.com/iotaledger/wasp/packages/kv/kvdecoder" @@ -62,7 +63,7 @@ func initialize(ctx iscp.Sandbox) (dict.Dict, error) { govParams.Set(governance.ParamChainOwner, ctx.Caller().Bytes()) // chain owner is whoever sends init request mustStoreAndInitCoreContract(ctx, governance.Contract, a, govParams) - state.Set(root.VarDeployPermissionsEnabled, []byte{1}) + state.Set(root.VarDeployPermissionsEnabled, codec.EncodeBool(true)) state.Set(root.VarStateInitialized, []byte{0xFF}) ctx.Log().Debugf("root.initialize.success") @@ -185,11 +186,8 @@ func requireDeployPermissions(ctx iscp.Sandbox) (dict.Dict, error) { a := assert.NewAssert(ctx.Log()) a.Require(isChainOwner(a, ctx), "root.revokeDeployPermissions: not authorized") params := kvdecoder.New(ctx.Params()) - permissionsEnabled := params.MustGetBytes(root.ParamDeployPermissionsEnabled)[0] == 1 - val := []byte{0} - if permissionsEnabled { - val = []byte{1} - } - ctx.State().Set(root.VarDeployPermissionsEnabled, val) + a.Require(ctx.Params().MustHas(root.ParamDeployPermissionsEnabled), "root.revokeDeployPermissions: ParamDeployPermissionsEnabled missing") + permissionsEnabled := params.MustGetBool(root.ParamDeployPermissionsEnabled) + ctx.State().Set(root.VarDeployPermissionsEnabled, codec.EncodeBool(permissionsEnabled)) return nil, nil } diff --git a/packages/vm/core/root/rootimpl/internal.go b/packages/vm/core/root/rootimpl/internal.go index ba45fb9950..6fb1824ba3 100644 --- a/packages/vm/core/root/rootimpl/internal.go +++ b/packages/vm/core/root/rootimpl/internal.go @@ -36,7 +36,11 @@ func mustStoreContractRecord(ctx iscp.Sandbox, rec *root.ContractRecord, a asser // isAuthorizedToDeploy checks if caller is authorized to deploy smart contract func isAuthorizedToDeploy(ctx iscp.Sandbox) bool { - if ctx.State().MustGet(root.VarDeployPermissionsEnabled)[0] == 0 { + permissionsEnabled, err := codec.DecodeBool(ctx.State().MustGet(root.VarDeployPermissionsEnabled)) + if err != nil { + return false + } + if !permissionsEnabled { return true } diff --git a/packages/vm/core/testcore/blob_deploy_test.go b/packages/vm/core/testcore/blob_deploy_test.go index f923964c43..a3805063b0 100644 --- a/packages/vm/core/testcore/blob_deploy_test.go +++ b/packages/vm/core/testcore/blob_deploy_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/kv/codec" "github.com/iotaledger/wasp/packages/solo" "github.com/iotaledger/wasp/packages/vm/core" "github.com/iotaledger/wasp/packages/vm/core/blob" @@ -215,7 +216,7 @@ func TestOpenDeploymentToAnyone(t *testing.T) { // enable open deployments req := solo.NewCallParams(root.Contract.Name, root.FuncRequireDeployPermissions.Name, - root.ParamDeployPermissionsEnabled, []byte{0}, + root.ParamDeployPermissionsEnabled, codec.EncodeBool(false), ) _, err = chain.PostRequestSync(req.WithIotas(1), nil) require.NoError(t, err) @@ -226,7 +227,7 @@ func TestOpenDeploymentToAnyone(t *testing.T) { // disable open deployments req = solo.NewCallParams(root.Contract.Name, root.FuncRequireDeployPermissions.Name, - root.ParamDeployPermissionsEnabled, []byte{1}, + root.ParamDeployPermissionsEnabled, codec.EncodeBool(true), ) _, err = chain.PostRequestSync(req.WithIotas(1), nil) require.NoError(t, err) diff --git a/packages/vm/core/testcore/governance_test.go b/packages/vm/core/testcore/governance_test.go index f6e4324a21..99e5c5330e 100644 --- a/packages/vm/core/testcore/governance_test.go +++ b/packages/vm/core/testcore/governance_test.go @@ -4,8 +4,10 @@ import ( "strings" "testing" + "github.com/iotaledger/wasp/packages/kv/dict" "github.com/iotaledger/wasp/packages/solo" "github.com/iotaledger/wasp/packages/vm/core" + "github.com/iotaledger/wasp/packages/vm/core/governance" "github.com/stretchr/testify/require" ) @@ -106,3 +108,100 @@ func TestRotate(t *testing.T) { require.True(t, chain.WaitForRequestsThrough(4)) }) } + +func TestAccessNodes(t *testing.T) { + env := solo.New(t, true, true) + node1KP, _ := env.NewKeyPairWithFunds() + node1OwnerKP, node1OwnerAddr := env.NewKeyPairWithFunds() + chainKP, _ := env.NewKeyPairWithFunds() + chain := env.NewChain(chainKP, "chain1") + defer chain.Log.Sync() + var res dict.Dict + var err error + + // + // Initially the state is empty. + res, err = chain.CallView( + governance.Contract.Name, + governance.FuncGetChainNodes.Name, + governance.GetChainNodesRequest{}.AsDict(), + ) + require.NoError(t, err) + getChainNodesResponse := governance.NewGetChainNodesResponseFromDict(res) + require.Empty(t, getChainNodesResponse.AccessNodeCandidates) + require.Empty(t, getChainNodesResponse.AccessNodes) + + // + // Add a single access node candidate. + _, err = chain.PostRequestSync( + solo.NewCallParamsFromDic( + governance.Contract.Name, + governance.FuncAddCandidateNode.Name, + (&governance.AccessNodeInfo{ + NodePubKey: node1KP.PublicKey.Bytes(), + ForCommittee: false, + AccessAPI: "http://my-api/url", + }).AddCertificate(node1KP.PrivateKey, node1OwnerAddr).ToAddCandidateNodeParams(), + ).WithIotas(1), + node1OwnerKP, // Sender should match data used to create the Cert field value. + ) + require.NoError(t, err) + + res, err = chain.CallView( + governance.Contract.Name, + governance.FuncGetChainNodes.Name, + governance.GetChainNodesRequest{}.AsDict(), + ) + require.NoError(t, err) + getChainNodesResponse = governance.NewGetChainNodesResponseFromDict(res) + require.Equal(t, 1, len(getChainNodesResponse.AccessNodeCandidates)) // Candidate registered. + require.Equal(t, "http://my-api/url", getChainNodesResponse.AccessNodeCandidates[0].AccessAPI) + require.Empty(t, getChainNodesResponse.AccessNodes) + + // + // Accept the node as an access node. + _, err = chain.PostRequestSync( + solo.NewCallParamsFromDic( + governance.Contract.Name, + governance.FuncChangeAccessNodes.Name, + governance.NewChangeAccessNodesRequest().Accept(node1KP.PublicKey).AsDict(), + ).WithIotas(1), + chainKP, + ) + require.NoError(t, err) + + res, err = chain.CallView( + governance.Contract.Name, + governance.FuncGetChainNodes.Name, + governance.GetChainNodesRequest{}.AsDict(), + ) + require.NoError(t, err) + getChainNodesResponse = governance.NewGetChainNodesResponseFromDict(res) + require.Equal(t, 1, len(getChainNodesResponse.AccessNodeCandidates)) // Candidate registered. + require.Equal(t, "http://my-api/url", getChainNodesResponse.AccessNodeCandidates[0].AccessAPI) + require.Equal(t, 1, len(getChainNodesResponse.AccessNodes)) + + // + // Revoke the access node (by the node owner). + _, err = chain.PostRequestSync( + solo.NewCallParamsFromDic( + governance.Contract.Name, + governance.FuncRevokeAccessNode.Name, + (&governance.AccessNodeInfo{ + NodePubKey: node1KP.PublicKey.Bytes(), + }).AddCertificate(node1KP.PrivateKey, node1OwnerAddr).ToAddCandidateNodeParams(), + ).WithIotas(1), + node1OwnerKP, // Sender should match data used to create the Cert field value. + ) + require.NoError(t, err) + + res, err = chain.CallView( + governance.Contract.Name, + governance.FuncGetChainNodes.Name, + governance.GetChainNodesRequest{}.AsDict(), + ) + require.NoError(t, err) + getChainNodesResponse = governance.NewGetChainNodesResponseFromDict(res) + require.Empty(t, getChainNodesResponse.AccessNodeCandidates) + require.Empty(t, getChainNodesResponse.AccessNodes) +} diff --git a/packages/vm/core/testcore/sbtests/concurrency_test.go b/packages/vm/core/testcore/sbtests/concurrency_test.go index 441cc1b453..0e94f6f3fd 100644 --- a/packages/vm/core/testcore/sbtests/concurrency_test.go +++ b/packages/vm/core/testcore/sbtests/concurrency_test.go @@ -57,7 +57,7 @@ func testConcurrency(t *testing.T, w bool) { } }(r, n) } - require.True(t, chain.WaitForRequestsThrough(sum+3+extra, 20*time.Second)) + require.True(t, chain.WaitForRequestsThrough(sum+3+extra, 180*time.Second)) ret, err := chain.CallView(ScName, sbtestsc.FuncGetCounter.Name) require.NoError(t, err) @@ -105,7 +105,7 @@ func testConcurrency2(t *testing.T, w bool) { }(r, n) } - require.True(t, chain.WaitForRequestsThrough(sum+3+extra, 20*time.Second)) + require.True(t, chain.WaitForRequestsThrough(sum+3+extra, 180*time.Second)) ret, err := chain.CallView(ScName, sbtestsc.FuncGetCounter.Name) require.NoError(t, err) diff --git a/packages/vm/core/testcore/sbtests/sbtestsc/testcore_bg.wasm b/packages/vm/core/testcore/sbtests/sbtestsc/testcore_bg.wasm index c7701951f2..e3b2cafe6e 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/runvm/runtask.go b/packages/vm/runvm/runtask.go index 1fab4b550f..63fce8cb5b 100644 --- a/packages/vm/runvm/runtask.go +++ b/packages/vm/runvm/runtask.go @@ -55,7 +55,7 @@ func runTask(task *vm.VMTask) { numOffLedger++ } else { if numOnLedger == vmcontext.MaxBlockInputCount { - break // max number of inputs to be included in state transition reached, do not process more on-ledger requests + continue // max number of inputs to be included in state transition reached, do not process more on-ledger requests } numOnLedger++ } diff --git a/packages/vm/viewcontext/viewcontext.go b/packages/vm/viewcontext/viewcontext.go index 72f712ab47..bcde346567 100644 --- a/packages/vm/viewcontext/viewcontext.go +++ b/packages/vm/viewcontext/viewcontext.go @@ -55,7 +55,7 @@ func (v *Viewcontext) CallView(contractHname, epCode iscp.Hname, params dict.Dic case error: err = err1 default: - err = xerrors.Errorf("viewcontext: panic in VM: %w", err1) + err = xerrors.Errorf("viewcontext: panic in VM: %v", err1) } v.log.Debugf("CallView: %v", err) v.log.Debugf(string(debug.Stack())) diff --git a/packages/vm/vmcontext/runreq.go b/packages/vm/vmcontext/runreq.go index c0ce4dbcfb..6d93ca6d78 100644 --- a/packages/vm/vmcontext/runreq.go +++ b/packages/vm/vmcontext/runreq.go @@ -145,7 +145,7 @@ func (vmctx *VMContext) mustSetUpRequestContext(req iscp.Request, requestIndex u vmctx.remainingAfterFees = vmctx.adjustOffLedgerTransfer() } - targetContract, _ := req.Target() + targetContract := req.Target().Contract var ok bool vmctx.contractRecord, ok = vmctx.findContractByHname(targetContract) if !ok { @@ -304,7 +304,7 @@ func (vmctx *VMContext) mustCallFromRequest() { vmctx.mustUpdateOffledgerRequestMaxAssumedNonce() // calling only non view entry points. Calling the view will trigger error and fallback - _, entryPoint := vmctx.req.Target() + entryPoint := vmctx.req.Target().EntryPoint targetContract := vmctx.contractRecord.Hname() params, _ := vmctx.req.Params() vmctx.lastResult, vmctx.lastError = vmctx.callNonViewByProgramHash( @@ -330,10 +330,9 @@ func (vmctx *VMContext) mustFinalizeRequestCall() { vmctx.virtualState.ApplyStateUpdates(vmctx.currentStateUpdate) vmctx.currentStateUpdate = nil - _, ep := vmctx.req.Target() vmctx.log.Debug("runTheRequest OUT. ", "reqId: ", vmctx.req.ID().Short(), - " entry point: ", ep.String(), + " entry point: ", vmctx.req.Target().EntryPoint.String(), ) } @@ -350,8 +349,8 @@ func (vmctx *VMContext) getChainConfigFromState() { } func (vmctx *VMContext) isInitChainRequest() bool { - targetContract, entryPoint := vmctx.req.Target() - return targetContract == root.Contract.Hname() && entryPoint == iscp.EntryPointInit + target := vmctx.req.Target() + return target.Contract == root.Contract.Hname() && target.EntryPoint == iscp.EntryPointInit } func isRequestTimeLockedNow(req iscp.Request, nowis time.Time) bool { diff --git a/packages/vm/wasmclient/host.go b/packages/vm/wasmclient/host.go index e01ed094f5..aaf31ba17d 100644 --- a/packages/vm/wasmclient/host.go +++ b/packages/vm/wasmclient/host.go @@ -73,8 +73,14 @@ func (w *WasmVMHost) CallFunc(objID, keyID int32, params []byte) []byte { return result } +func (w *WasmVMHost) DelKey(objID, keyID, typeID int32) { + // size -1 means delete + // this removes the need for a separate hostDelete function + hostSetBytes(objID, keyID, typeID, nil, -1) +} + func (w *WasmVMHost) Exists(objID, keyID, typeID int32) bool { - // negative length (-1) means only test for existence + // size -1 means only test for existence // returned size -1 indicates keyID not found (or error) // this removes the need for a separate hostExists function return hostGetBytes(objID, keyID, typeID, nil, -1) >= 0 diff --git a/packages/vm/wasmhost/kvstorehost.go b/packages/vm/wasmhost/kvstorehost.go index 6c6577b98d..98a2cd25da 100644 --- a/packages/vm/wasmhost/kvstorehost.go +++ b/packages/vm/wasmhost/kvstorehost.go @@ -4,8 +4,10 @@ package wasmhost import ( + "encoding/binary" "fmt" + "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/wasp/packages/kv/codec" "github.com/mr-tron/base58" ) @@ -15,23 +17,25 @@ import ( //nolint:revive const ( OBJTYPE_ARRAY int32 = 0x20 - OBJTYPE_ARRAY16 int32 = 0x30 - OBJTYPE_CALL int32 = 0x40 - OBJTYPE_TYPEMASK int32 = 0x0f + OBJTYPE_ARRAY16 int32 = 0x60 + OBJTYPE_CALL int32 = 0x80 + OBJTYPE_TYPEMASK int32 = 0x1f OBJTYPE_ADDRESS int32 = 1 OBJTYPE_AGENT_ID int32 = 2 - OBJTYPE_BYTES int32 = 3 - OBJTYPE_CHAIN_ID int32 = 4 - OBJTYPE_COLOR int32 = 5 - OBJTYPE_HASH int32 = 6 - OBJTYPE_HNAME int32 = 7 - OBJTYPE_INT16 int32 = 8 - OBJTYPE_INT32 int32 = 9 - OBJTYPE_INT64 int32 = 10 - OBJTYPE_MAP int32 = 11 - OBJTYPE_REQUEST_ID int32 = 12 - OBJTYPE_STRING int32 = 13 + OBJTYPE_BOOL int32 = 3 + OBJTYPE_BYTES int32 = 4 + OBJTYPE_CHAIN_ID int32 = 5 + OBJTYPE_COLOR int32 = 6 + OBJTYPE_HASH int32 = 7 + OBJTYPE_HNAME int32 = 8 + OBJTYPE_INT8 int32 = 9 + OBJTYPE_INT16 int32 = 10 + OBJTYPE_INT32 int32 = 11 + OBJTYPE_INT64 int32 = 12 + OBJTYPE_MAP int32 = 13 + OBJTYPE_REQUEST_ID int32 = 14 + OBJTYPE_STRING int32 = 15 OBJID_NULL int32 = 0 OBJID_ROOT int32 = 1 @@ -44,8 +48,11 @@ const ( // this allows us to display better readable tracing information const KeyFromBytes int32 = 0x4000 +var TypeSizes = [...]int{0, 33, 37, 1, 0, 33, 32, 32, 4, 1, 2, 4, 8, 0, 34, 0} + type HostObject interface { CallFunc(keyID int32, params []byte) []byte + DelKey(keyID, typeID int32) Exists(keyID, typeID int32) bool GetBytes(keyID, typeID int32) []byte GetObjectID(keyID, typeID int32) int32 @@ -74,13 +81,17 @@ func (h *KvStoreHost) CallFunc(objID, keyID int32, params []byte) []byte { return h.FindObject(objID).CallFunc(keyID, params) } +func (h *KvStoreHost) DelKey(objID, keyID, typeID int32) { + h.FindObject(objID).DelKey(keyID, typeID) +} + func (h *KvStoreHost) Exists(objID, keyID, typeID int32) bool { return h.FindObject(objID).Exists(keyID, typeID) } func (h *KvStoreHost) FindObject(objID int32) HostObject { if objID < 0 || objID >= int32(len(h.objIDToObj)) { - panic("FindObject: invalid objID") + h.Panicf("FindObject: invalid objID") } return h.objIDToObj[objID] } @@ -93,22 +104,28 @@ func (h *KvStoreHost) GetBytes(objID, keyID, typeID int32) []byte { } bytes := obj.GetBytes(keyID, typeID) switch typeID { + case OBJTYPE_INT8: + val8, err := codec.DecodeInt8(bytes, 0) + if err != nil { + h.Panicf("GetBytes: invalid int8") + } + h.Tracef("GetBytes o%d k%d = %db", objID, keyID, val8) case OBJTYPE_INT16: val16, err := codec.DecodeInt16(bytes, 0) if err != nil { - panic("GetBytes: invalid int16") + h.Panicf("GetBytes: invalid int16") } h.Tracef("GetBytes o%d k%d = %ds", objID, keyID, val16) case OBJTYPE_INT32: val32, err := codec.DecodeInt32(bytes, 0) if err != nil { - panic("GetBytes: invalid int32") + h.Panicf("GetBytes: invalid int32") } h.Tracef("GetBytes o%d k%d = %di", objID, keyID, val32) case OBJTYPE_INT64: val64, err := codec.DecodeInt64(bytes, 0) if err != nil { - panic("GetBytes: invalid int64") + h.Panicf("GetBytes: invalid int64") } h.Tracef("GetBytes o%d k%d = %dl", objID, keyID, val64) case OBJTYPE_STRING: @@ -213,25 +230,37 @@ func (h *KvStoreHost) GetObjectID(objID, keyID, typeID int32) int32 { return subID } +func (h *KvStoreHost) Panicf(format string, args ...interface{}) { + err := fmt.Errorf(format, args...) + h.Tracef(err.Error()) + panic(err) +} + func (h *KvStoreHost) SetBytes(objID, keyID, typeID int32, bytes []byte) { h.FindObject(objID).SetBytes(keyID, typeID, bytes) switch typeID { + case OBJTYPE_INT8: + val8, err := codec.DecodeInt8(bytes, 0) + if err != nil { + h.Panicf("SetBytes: invalid int8") + } + h.Tracef("SetBytes o%d k%d v=%db", objID, keyID, val8) case OBJTYPE_INT16: val16, err := codec.DecodeInt16(bytes, 0) if err != nil { - panic("SetBytes: invalid int16") + h.Panicf("SetBytes: invalid int16") } h.Tracef("SetBytes o%d k%d v=%ds", objID, keyID, val16) case OBJTYPE_INT32: val32, err := codec.DecodeInt32(bytes, 0) if err != nil { - panic("SetBytes: invalid int32") + h.Panicf("SetBytes: invalid int32") } h.Tracef("SetBytes o%d k%d v=%di", objID, keyID, val32) case OBJTYPE_INT64: val64, err := codec.DecodeInt64(bytes, 0) if err != nil { - panic("SetBytes: invalid int64") + h.Panicf("SetBytes: invalid int64") } h.Tracef("SetBytes o%d k%d v=%dl", objID, keyID, val64) case OBJTYPE_STRING: @@ -261,3 +290,32 @@ func (h *KvStoreHost) TrackObject(obj HostObject) int32 { h.objIDToObj = append(h.objIDToObj, obj) return objID } + +func (h *KvStoreHost) TypeCheck(typeID int32, bytes []byte) { + typeSize := TypeSizes[typeID] + if typeSize != 0 && typeSize != len(bytes) { + h.Panicf("TypeCheck: invalid type size") + } + switch typeID { + case OBJTYPE_ADDRESS: + // address bytes must start with valid address type + if ledgerstate.AddressType(bytes[0]) > ledgerstate.AliasAddressType { + h.Panicf("TypeCheck: invalid address type") + } + case OBJTYPE_AGENT_ID: + // address bytes in agent id must start with valid address type + if ledgerstate.AddressType(bytes[0]) > ledgerstate.AliasAddressType { + h.Panicf("TypeCheck: invalid agent id address type") + } + case OBJTYPE_CHAIN_ID: + // chain id must be alias address + if ledgerstate.AddressType(bytes[0]) != ledgerstate.AliasAddressType { + h.Panicf("TypeCheck: invalid chain id address type") + } + case OBJTYPE_REQUEST_ID: + outputIndex := binary.LittleEndian.Uint16(bytes[ledgerstate.TransactionIDLength:]) + if outputIndex > ledgerstate.MaxOutputCount { + h.Panicf("TypeCheck: invalid request id output index") + } + } +} diff --git a/packages/vm/wasmhost/wasmedgevm.go b/packages/vm/wasmhost/wasmedgevm.go new file mode 100644 index 0000000000..d66ca04ba8 --- /dev/null +++ b/packages/vm/wasmhost/wasmedgevm.go @@ -0,0 +1,217 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// +build wasmedge + +package wasmhost + +import ( + "errors" + + "github.com/second-state/WasmEdge-go/wasmedge" +) + +type WasmEdgeVM struct { + WasmVMBase + edge *wasmedge.VM + memory *wasmedge.Memory + module *wasmedge.ImportObject + store *wasmedge.Store + importers []*wasmedge.ImportObject +} + +type HostFunction func(params []interface{}) []interface{} + +const I32 = wasmedge.ValType_I32 + +var i32 = []wasmedge.ValType{I32, I32, I32, I32, I32} + +func NewWasmEdgeVM() WasmVM { + vm := &WasmEdgeVM{} + wasmedge.SetLogErrorLevel() + + vm.edge = wasmedge.NewVM() + + //config := wasmedge.NewConfig() + //config.SetInterruptable(true) + //vm.store = wasmedge.NewStore(wasmedge.NewEngineWithConfig(config)) + //vm.interrupt, _ = vm.store.InterruptHandle() + return vm +} + +func (vm *WasmEdgeVM) NewInstance() WasmVM { + return NewWasmEdgeVM() +} + +//TODO +func (vm *WasmEdgeVM) Interrupt() { + panic("implement me") +} + +func (vm *WasmEdgeVM) importFunc(nrParams int, nrResults int, funcName string, function HostFunction) { + wrapper := func(_data interface{}, _mem *wasmedge.Memory, params []interface{}) ([]interface{}, wasmedge.Result) { + return function(params), wasmedge.Result_Success + } + funcType := wasmedge.NewFunctionType(i32[:nrParams], i32[:nrResults]) + funcWrapper := wasmedge.NewFunction(funcType, wrapper, nil, 0) + vm.module.AddFunction(funcName, funcWrapper) +} + +func (vm *WasmEdgeVM) importModule(name string) { + vm.module = wasmedge.NewImportObject(name) + vm.importers = append(vm.importers, vm.module) +} + +func (vm *WasmEdgeVM) LinkHost(impl WasmVM, host *WasmHost) error { + _ = vm.WasmVMBase.LinkHost(impl, host) + + vm.importModule(ModuleWasmLib) + vm.importFunc(5, 1, FuncHostGetBytes, vm.exportHostGetBytes) + vm.importFunc(2, 1,FuncHostGetKeyID, vm.exportHostGetKeyID) + vm.importFunc(3, 1, FuncHostGetObjectID, vm.exportHostGetObjectID) + vm.importFunc(5, 0, FuncHostSetBytes, vm.exportHostSetBytes) + err := vm.edge.RegisterImport(vm.module) + if err != nil { + return err + } + + // AssemblyScript Wasm versions uses this one to write panic message to console + vm.importModule(ModuleEnv) + vm.importFunc(4, 0, FuncAbort, vm.exportAbort) + err = vm.edge.RegisterImport(vm.module) + if err != nil { + return err + } + + // TinyGo Wasm versions uses these to write panic message to console + vm.importModule(ModuleWasi1) + vm.importFunc(4, 1, FuncFdWrite, vm.exportFdWrite) + err = vm.edge.RegisterImport(vm.module) + if err != nil { + return err + } + vm.importModule(ModuleWasi2) + vm.importFunc(4, 1, FuncFdWrite, vm.exportFdWrite) + return vm.edge.RegisterImport(vm.module) +} + +func (vm *WasmEdgeVM) LoadWasm(wasmData []byte) error { + err := vm.edge.LoadWasmBuffer(wasmData) + if err != nil { + return err + } + err = vm.edge.Validate() + if err != nil { + return err + } + return vm.Instantiate() +} + +func (vm *WasmEdgeVM) Instantiate() error { + err := vm.edge.Instantiate() + if err != nil { + return err + } + vm.memory = vm.edge.GetStore().FindMemory("memory") + if vm.memory == nil { + return errors.New("no memory export") + } + return nil +} + +func (vm *WasmEdgeVM) RunFunction(functionName string, args ...interface{}) error { + return vm.Run(func() (err error) { + _,err = vm.edge.Execute(functionName, args...) + return err + }) +} + +func (vm *WasmEdgeVM) RunScFunction(index int32) error { + frame := vm.PreCall() + defer vm.PostCall(frame) + + return vm.Run(func() (err error) { + _,err = vm.edge.Execute("on_call", index) + return err + }) +} + +func (vm *WasmEdgeVM) UnsafeMemory() []byte { + panic("wasmedge.UnsafeMemory") + return nil +} + +func (vm *WasmEdgeVM) VMGetBytes(offset int32, size int32) []byte { + bytes, err := vm.memory.GetData(uint(offset), uint(size)) + if err != nil { + panic("wasmedge.VMGetBytes: " + err.Error()) + } + return bytes +} + +func (vm *WasmEdgeVM) VMGetSize() int32 { + return int32(vm.memory.GetPageSize() << 16) +} + +func (vm *WasmEdgeVM) VMSetBytes(offset int32, size int32, bytes []byte) int32 { + if size != 0 { + err := vm.memory.SetData(bytes, uint(offset), uint(size)) + if err != nil { + panic("wasmedge.VMSetBytes: " + err.Error()) + } + } + return int32(len(bytes)) +} + +func (vm *WasmEdgeVM) exportAbort(args []interface{}) []interface{} { + errMsg := args[0].(int32) + fileName := args[1].(int32) + line := args[2].(int32) + col := args[3].(int32) + vm.EnvAbort(errMsg, fileName, line, col) + return nil +} + +func (vm *WasmEdgeVM) exportFdWrite(args []interface{}) []interface{} { + fd := args[0].(int32) + iovs := args[1].(int32) + size := args[2].(int32) + written := args[3].(int32) + ret := vm.HostFdWrite(fd, iovs, size, written) + return []interface{}{ret} +} + +func (vm *WasmEdgeVM) exportHostGetBytes(args []interface{}) []interface{} { + objID := args[0].(int32) + keyID := args[1].(int32) + typeID := args[2].(int32) + stringRef := args[3].(int32) + size := args[4].(int32) + ret := vm.HostGetBytes(objID, keyID, typeID, stringRef, size) + return []interface{}{ret} +} + +func (vm *WasmEdgeVM) exportHostGetKeyID(args []interface{}) []interface{} { + keyRef := args[0].(int32) + size := args[1].(int32) + ret := vm.HostGetKeyID(keyRef, size) + return []interface{}{ret} +} + +func (vm *WasmEdgeVM) exportHostGetObjectID(args []interface{}) []interface{} { + objID := args[0].(int32) + keyID := args[1].(int32) + typeID := args[2].(int32) + ret := vm.HostGetObjectID(objID, keyID, typeID) + return []interface{}{ret} +} + +func (vm *WasmEdgeVM) exportHostSetBytes(args []interface{}) []interface{} { + objID := args[0].(int32) + keyID := args[1].(int32) + typeID := args[2].(int32) + stringRef := args[3].(int32) + size := args[4].(int32) + vm.HostSetBytes(objID, keyID, typeID, stringRef, size) + return nil +} diff --git a/packages/vm/wasmhost/wasmervm.go b/packages/vm/wasmhost/wasmervm.go new file mode 100644 index 0000000000..8afb66c419 --- /dev/null +++ b/packages/vm/wasmhost/wasmervm.go @@ -0,0 +1,165 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +// +build wasmer + +package wasmhost + +import ( + "github.com/wasmerio/wasmer-go/wasmer" +) + +type WasmerVM struct { + WasmVMBase + instance *wasmer.Instance + linker *wasmer.ImportObject + memory *wasmer.Memory + module *wasmer.Module + store *wasmer.Store +} + +var i32 = []wasmer.ValueKind{wasmer.I32, wasmer.I32, wasmer.I32, wasmer.I32, wasmer.I32} + +func NewWasmerVM() WasmVM { + vm := &WasmerVM{} + vm.store = wasmer.NewStore(wasmer.NewEngine()) + return vm +} + +func (vm *WasmerVM) NewInstance() WasmVM { + return &WasmerVM{ store: vm.store } +} + +//TODO +func (vm *WasmerVM) Interrupt() { + panic("implement me") +} + +func (vm *WasmerVM) LinkHost(impl WasmVM, host *WasmHost) error { + vm.linker = wasmer.NewImportObject() + _ = vm.WasmVMBase.LinkHost(impl, host) + + funcs := map[string]wasmer.IntoExtern{ + FuncHostGetBytes: vm.importFunc(5, 1, vm.exportHostGetBytes), + FuncHostGetKeyID: vm.importFunc(2, 1, vm.exportHostGetKeyID), + FuncHostGetObjectID: vm.importFunc(3, 1, vm.exportHostGetObjectID), + FuncHostSetBytes: vm.importFunc(5, 0, vm.exportHostSetBytes), + } + vm.linker.Register(ModuleWasmLib, funcs) + + funcs = map[string]wasmer.IntoExtern{ + FuncAbort: vm.importFunc(4, 0, vm.exportAbort), + } + vm.linker.Register(ModuleEnv, funcs) + + // TinyGo Wasm implementation uses this one to write panic message to console + funcs = map[string]wasmer.IntoExtern{ + FuncFdWrite: vm.importFunc(4, 1, vm.exportFdWrite), + } + vm.linker.Register(ModuleWasi1, funcs) + vm.linker.Register(ModuleWasi2, funcs) + return nil +} + +func (vm *WasmerVM) importFunc(nrParams, nrResults int, function func([]wasmer.Value) ([]wasmer.Value, error)) *wasmer.Extern { + params := wasmer.NewValueTypes(i32[:nrParams]...) + results := wasmer.NewValueTypes(i32[:nrResults]...) + funcType := wasmer.NewFunctionType(params, results) + return wasmer.NewFunction(vm.store, funcType, function).IntoExtern() +} + +func (vm *WasmerVM) LoadWasm(wasmData []byte) error { + var err error + vm.module, err = wasmer.NewModule(vm.store, wasmData) + if err != nil { + return err + } + vm.instance, err = wasmer.NewInstance(vm.module, vm.linker) + if err != nil { + return err + } + vm.memory, err = vm.instance.Exports.GetMemory("memory") + return err +} + +func (vm *WasmerVM) RunFunction(functionName string, args ...interface{}) error { + export, err := vm.instance.Exports.GetFunction(functionName) + if err != nil { + return err + } + return vm.Run(func() error { + _, err = export(args...) + return err + }) +} + +func (vm *WasmerVM) RunScFunction(index int32) error { + export, err := vm.instance.Exports.GetFunction("on_call") + if err != nil { + return err + } + frame := vm.PreCall() + err = vm.Run(func() error { + _, err = export(index) + return err + }) + vm.PostCall(frame) + return err +} + +func (vm *WasmerVM) UnsafeMemory() []byte { + return vm.memory.Data() +} + +func (vm *WasmerVM) exportAbort(args []wasmer.Value) ([]wasmer.Value, error) { + errMsg := args[0].I32() + fileName := args[1].I32() + line := args[2].I32() + col := args[3].I32() + vm.EnvAbort(errMsg, fileName, line, col) + return nil, nil +} + +func (vm *WasmerVM) exportFdWrite(args []wasmer.Value) ([]wasmer.Value, error) { + fd := args[0].I32() + iovs := args[1].I32() + size := args[2].I32() + written := args[3].I32() + ret := vm.HostFdWrite(fd, iovs, size, written) + return []wasmer.Value{wasmer.NewI32(ret)}, nil +} + +func (vm *WasmerVM) exportHostGetBytes(args []wasmer.Value) ([]wasmer.Value, error) { + objID := args[0].I32() + keyID := args[1].I32() + typeID := args[2].I32() + stringRef := args[3].I32() + size := args[4].I32() + ret := vm.HostGetBytes(objID, keyID, typeID, stringRef, size) + return []wasmer.Value{wasmer.NewI32(ret)}, nil +} + +func (vm *WasmerVM) exportHostGetKeyID(args []wasmer.Value) ([]wasmer.Value, error) { + keyRef := args[0].I32() + size := args[1].I32() + ret := vm.HostGetKeyID(keyRef, size) + return []wasmer.Value{wasmer.NewI32(ret)}, nil +} + +func (vm *WasmerVM) exportHostGetObjectID(args []wasmer.Value) ([]wasmer.Value, error) { + objID := args[0].I32() + keyID := args[1].I32() + typeID := args[2].I32() + ret := vm.HostGetObjectID(objID, keyID, typeID) + return []wasmer.Value{wasmer.NewI32(ret)}, nil +} + +func (vm *WasmerVM) exportHostSetBytes(args []wasmer.Value) ([]wasmer.Value, error) { + objID := args[0].I32() + keyID := args[1].I32() + typeID := args[2].I32() + stringRef := args[3].I32() + size := args[4].I32() + vm.HostSetBytes(objID, keyID, typeID, stringRef, size) + return nil, nil +} diff --git a/packages/vm/wasmhost/wasmgovm.go b/packages/vm/wasmhost/wasmgovm.go index 29aebccafe..6e0a7e64ab 100644 --- a/packages/vm/wasmhost/wasmgovm.go +++ b/packages/vm/wasmhost/wasmgovm.go @@ -10,20 +10,27 @@ import ( "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" ) +// provide implementation for Wasm-only function +func Connect(h wasmlib.ScHost) wasmlib.ScHost { + return wasmlib.ConnectHost(h) +} + type WasmGoVM struct { WasmVMBase scName string onLoad func() } -var _ WasmVM = &WasmGoVM{} - -func NewWasmGoVM(scName string, onLoad func()) *WasmGoVM { +func NewWasmGoVM(scName string, onLoad func()) WasmVM { return &WasmGoVM{scName: scName, onLoad: onLoad} } -func Connect(h wasmlib.ScHost) wasmlib.ScHost { - return wasmlib.ConnectHost(h) +func (vm *WasmGoVM) NewInstance() WasmVM { + return nil +} + +func (vm *WasmGoVM) Instantiate() error { + return nil } func (vm *WasmGoVM) Interrupt() { @@ -39,16 +46,15 @@ func (vm *WasmGoVM) LoadWasm(wasmData []byte) error { if scName[3:] != vm.scName { return errors.New("WasmGoVM: unknown contract: " + scName) } - vm.onLoad() return nil } func (vm *WasmGoVM) RunFunction(functionName string, args ...interface{}) error { - // already ran on_load in LoadWasm, other functions are not supported - if functionName != "on_load" { - return errors.New("WasmGoVM: cannot run function: " + functionName) + if functionName == "on_load" { + vm.onLoad() + return nil } - return nil + return errors.New("WasmGoVM: cannot run function: " + functionName) } func (vm *WasmGoVM) RunScFunction(index int32) error { diff --git a/packages/vm/wasmhost/wasmhost.go b/packages/vm/wasmhost/wasmhost.go index 8e6296291d..7e5145eacb 100644 --- a/packages/vm/wasmhost/wasmhost.go +++ b/packages/vm/wasmhost/wasmhost.go @@ -57,21 +57,20 @@ func (host *WasmHost) FunctionFromCode(code uint32) string { return host.codeToFunc[code] } +func (host *WasmHost) Instantiate() error { + return host.vm.Instantiate() +} + func (host *WasmHost) IsView(function string) bool { return (host.funcToIndex[function] & 0x8000) != 0 } func (host *WasmHost) LoadWasm(wasmData []byte) error { - err := host.vm.LoadWasm(wasmData) - if err != nil { - return err - } - err = host.RunFunction("on_load") - if err != nil { - return err - } - host.vm.SaveMemory() - return nil + return host.vm.LoadWasm(wasmData) +} + +func (host *WasmHost) NewInstance() WasmVM { + return host.vm.NewInstance() } func (host *WasmHost) RunFunction(functionName string, args ...interface{}) (err error) { diff --git a/packages/vm/wasmhost/wasmtimevm.go b/packages/vm/wasmhost/wasmtimevm.go index 136a489d69..79ee641033 100644 --- a/packages/vm/wasmhost/wasmtimevm.go +++ b/packages/vm/wasmhost/wasmtimevm.go @@ -11,6 +11,7 @@ import ( type WasmTimeVM struct { WasmVMBase + engine *wasmtime.Engine instance *wasmtime.Instance interrupt *wasmtime.InterruptHandle linker *wasmtime.Linker @@ -19,85 +20,77 @@ type WasmTimeVM struct { store *wasmtime.Store } -var _ WasmVM = &WasmTimeVM{} - -func NewWasmTimeVM() *WasmTimeVM { +func NewWasmTimeVM() WasmVM { vm := &WasmTimeVM{} config := wasmtime.NewConfig() config.SetInterruptable(true) - vm.store = wasmtime.NewStore(wasmtime.NewEngineWithConfig(config)) - vm.interrupt, _ = vm.store.InterruptHandle() - vm.linker = wasmtime.NewLinker(vm.store) + vm.engine = wasmtime.NewEngineWithConfig(config) return vm } +func (vm *WasmTimeVM) NewInstance() WasmVM { + return &WasmTimeVM{engine: vm.engine, module: vm.module} +} + func (vm *WasmTimeVM) Interrupt() { vm.interrupt.Interrupt() } -func (vm *WasmTimeVM) LinkHost(impl WasmVM, host *WasmHost) error { +func (vm *WasmTimeVM) LinkHost(impl WasmVM, host *WasmHost) (err error) { + vm.store = wasmtime.NewStore(vm.engine) + vm.interrupt, err = vm.store.InterruptHandle() + if err != nil { + return err + } + + vm.linker = wasmtime.NewLinker(vm.engine) _ = vm.WasmVMBase.LinkHost(impl, host) - err := vm.linker.DefineFunc("WasmLib", "hostGetBytes", - func(objID, keyID, typeID, stringRef, size int32) int32 { - return vm.HostGetBytes(objID, keyID, typeID, stringRef, size) - }) + err = vm.linker.DefineFunc(vm.store, ModuleWasmLib, FuncHostGetBytes, vm.HostGetBytes) if err != nil { return err } - err = vm.linker.DefineFunc("WasmLib", "hostGetKeyID", - func(keyRef, size int32) int32 { - return vm.HostGetKeyID(keyRef, size) - }) + err = vm.linker.DefineFunc(vm.store, ModuleWasmLib, FuncHostGetKeyID, vm.HostGetKeyID) if err != nil { return err } - err = vm.linker.DefineFunc("WasmLib", "hostGetObjectID", - func(objID, keyID, typeID int32) int32 { - return vm.HostGetObjectID(objID, keyID, typeID) - }) + err = vm.linker.DefineFunc(vm.store, ModuleWasmLib, FuncHostGetObjectID, vm.HostGetObjectID) if err != nil { return err } - err = vm.linker.DefineFunc("WasmLib", "hostSetBytes", - func(objID, keyID, typeID, stringRef, size int32) { - vm.HostSetBytes(objID, keyID, typeID, stringRef, size) - }) + err = vm.linker.DefineFunc(vm.store, ModuleWasmLib, FuncHostSetBytes, vm.HostSetBytes) if err != nil { return err } // AssemblyScript Wasm versions uses this one to write panic message to console - err = vm.linker.DefineFunc("env", "abort", - func(p1, p2, p3, p4 int32) { - vm.EnvAbort(p1, p2, p3, p4) - }) + err = vm.linker.DefineFunc(vm.store, ModuleEnv, FuncAbort, vm.HostAbort) if err != nil { return err } // TinyGo Wasm versions uses this one to write panic message to console - fdWrite := func(fd, iovs, size, written int32) int32 { - return vm.HostFdWrite(fd, iovs, size, written) - } - err = vm.linker.DefineFunc("wasi_unstable", "fd_write", fdWrite) + err = vm.linker.DefineFunc(vm.store, ModuleWasi1, FuncFdWrite, vm.HostFdWrite) if err != nil { return err } - return vm.linker.DefineFunc("wasi_snapshot_preview1", "fd_write", fdWrite) + return vm.linker.DefineFunc(vm.store, ModuleWasi2, FuncFdWrite, vm.HostFdWrite) } -func (vm *WasmTimeVM) LoadWasm(wasmData []byte) error { - var err error - vm.module, err = wasmtime.NewModule(vm.store.Engine, wasmData) +func (vm *WasmTimeVM) LoadWasm(wasmData []byte) (err error) { + vm.module, err = wasmtime.NewModule(vm.engine, wasmData) if err != nil { return err } - vm.instance, err = vm.linker.Instantiate(vm.module) + return vm.Instantiate() +} + +func (vm *WasmTimeVM) Instantiate() (err error) { + vm.instance, err = vm.linker.Instantiate(vm.store, vm.module) if err != nil { return err } - memory := vm.instance.GetExport("memory") + memory := vm.instance.GetExport(vm.store, "memory") if memory == nil { return errors.New("no memory export") } @@ -109,31 +102,28 @@ func (vm *WasmTimeVM) LoadWasm(wasmData []byte) error { } func (vm *WasmTimeVM) RunFunction(functionName string, args ...interface{}) error { - export := vm.instance.GetExport(functionName) + export := vm.instance.GetExport(vm.store, functionName) if export == nil { return errors.New("unknown export function: '" + functionName + "'") } return vm.Run(func() (err error) { - _, err = export.Func().Call(args...) - return + _, err = export.Func().Call(vm.store, args...) + return err }) } func (vm *WasmTimeVM) RunScFunction(index int32) error { - export := vm.instance.GetExport("on_call") + export := vm.instance.GetExport(vm.store, "on_call") if export == nil { return errors.New("unknown export function: 'on_call'") } - frame := vm.PreCall() - defer vm.PostCall(frame) - return vm.Run(func() (err error) { - _, err = export.Func().Call(index) - return + _, err = export.Func().Call(vm.store, index) + return err }) } func (vm *WasmTimeVM) UnsafeMemory() []byte { - return vm.memory.UnsafeData() + return vm.memory.UnsafeData(vm.store) } diff --git a/packages/vm/wasmhost/wasmvm.go b/packages/vm/wasmhost/wasmvm.go index 1bee0d4bf4..57055f451a 100644 --- a/packages/vm/wasmhost/wasmvm.go +++ b/packages/vm/wasmhost/wasmvm.go @@ -5,11 +5,24 @@ package wasmhost import ( "encoding/binary" + "errors" "fmt" "time" ) -const defaultTimeout = 5 * time.Second +const ( + defaultTimeout = 5 * time.Second + FuncAbort = "abort" + FuncFdWrite = "fd_write" + FuncHostGetBytes = "hostGetBytes" + FuncHostGetKeyID = "hostGetKeyID" + FuncHostGetObjectID = "hostGetObjectID" + FuncHostSetBytes = "hostSetBytes" + ModuleEnv = "env" + ModuleWasi1 = "wasi_unstable" + ModuleWasi2 = "wasi_snapshot_preview1" + ModuleWasmLib = "WasmLib" +) var ( // DisableWasmTimeout can be used to disable the annoying timeout during debugging @@ -26,64 +39,99 @@ var ( ) type WasmVM interface { + Instantiate() error Interrupt() LinkHost(impl WasmVM, host *WasmHost) error LoadWasm(wasmData []byte) error + NewInstance() WasmVM RunFunction(functionName string, args ...interface{}) error RunScFunction(index int32) error - SaveMemory() UnsafeMemory() []byte VMGetBytes(offset int32, size int32) []byte + VMGetSize() int32 VMSetBytes(offset int32, size int32, bytes []byte) int32 } type WasmVMBase struct { impl WasmVM host *WasmHost - memoryCopy []byte - memoryDirty bool - memoryNonZero int + panicErr error result []byte resultKeyID int32 timeoutStarted bool } -func (vm *WasmVMBase) EnvAbort(errMsg, fileName, line, col int32) { - ptr := vm.impl.UnsafeMemory() +// catchPanicMessage is used in every host function to catch any panic. +// It will save the first panic it encounters in the WasmVMBase so that +// the caller of the Wasm function can retrieve the correct error. +// This is a workaround to WasmTime saving the *last* panic instead of +// the first, thereby reporting the wrong panic error sometimes +func (vm *WasmVMBase) catchPanicMessage() { + panicMsg := recover() + if panicMsg == nil { + return + } + if vm.panicErr == nil { + switch msg := panicMsg.(type) { + case error: + vm.panicErr = msg + default: + vm.panicErr = fmt.Errorf("%v", msg) + } + } + // rethrow and let nature run its course... + panic(panicMsg) +} + +//nolint:unparam +func (vm *WasmVMBase) getKvStore(id int32) *KvStoreHost { + return vm.host.getKvStore(id) +} + +func (vm *WasmVMBase) HostAbort(errMsg, fileName, line, col int32) { + // crude implementation assumes texts to only use ASCII part of UTF-16 + + defer vm.catchPanicMessage() // null-terminated UTF-16 error message str1 := make([]byte, 0) - for i := errMsg; ptr[i] != 0; i += 2 { - str1 = append(str1, ptr[i]) + ptr := vm.impl.VMGetBytes(errMsg, 2) + for i := errMsg; ptr[0] != 0; i += 2 { + str1 = append(str1, ptr[0]) + ptr = vm.impl.VMGetBytes(i, 2) } // null-terminated UTF-16 file name str2 := make([]byte, 0) - for i := fileName; ptr[i] != 0; i += 2 { - str2 = append(str2, ptr[i]) + ptr = vm.impl.VMGetBytes(fileName, 2) + for i := fileName; ptr[0] != 0; i += 2 { + str2 = append(str2, ptr[0]) + ptr = vm.impl.VMGetBytes(i, 2) } panic(fmt.Sprintf("AssemblyScript panic: %s (%s %d:%d)", string(str1), string(str2), line, col)) } -//nolint:unparam -func (vm *WasmVMBase) getKvStore(id int32) *KvStoreHost { - return vm.host.getKvStore(id) -} +func (vm *WasmVMBase) HostFdWrite(_fd, iovs, _size, written int32) int32 { + defer vm.catchPanicMessage() -func (vm *WasmVMBase) HostFdWrite(fd, iovs, size, written int32) int32 { host := vm.getKvStore(0) host.TraceAllf("HostFdWrite(...)") // very basic implementation that expects fd to be stdout and iovs to be only one element - ptr := vm.impl.UnsafeMemory() - txt := binary.LittleEndian.Uint32(ptr[iovs : iovs+4]) - siz := binary.LittleEndian.Uint32(ptr[iovs+4 : iovs+8]) - fmt.Print(string(ptr[txt : txt+siz])) - binary.LittleEndian.PutUint32(ptr[written:written+4], siz) - return int32(siz) + ptr := vm.impl.VMGetBytes(iovs, 8) + text := int32(binary.LittleEndian.Uint32(ptr[0:4])) + size := int32(binary.LittleEndian.Uint32(ptr[4:8])) + msg := vm.impl.VMGetBytes(text, size) + fmt.Print(string(msg)) + ptr = make([]byte, 4) + binary.LittleEndian.PutUint32(ptr, uint32(size)) + vm.impl.VMSetBytes(written, size, ptr) + return size } func (vm *WasmVMBase) HostGetBytes(objID, keyID, typeID, stringRef, size int32) int32 { + defer vm.catchPanicMessage() + host := vm.getKvStore(0) host.TraceAllf("HostGetBytes(o%d,k%d,t%d,r%d,s%d)", objID, keyID, typeID, stringRef, size) @@ -130,6 +178,8 @@ func (vm *WasmVMBase) HostGetBytes(objID, keyID, typeID, stringRef, size int32) } func (vm *WasmVMBase) HostGetKeyID(keyRef, size int32) int32 { + defer vm.catchPanicMessage() + host := vm.getKvStore(0) host.TraceAllf("HostGetKeyID(r%d,s%d)", keyRef, size) // non-negative size means original key was a string @@ -144,18 +194,33 @@ func (vm *WasmVMBase) HostGetKeyID(keyRef, size int32) int32 { } func (vm *WasmVMBase) HostGetObjectID(objID, keyID, typeID int32) int32 { + defer vm.catchPanicMessage() + host := vm.getKvStore(0) host.TraceAllf("HostGetObjectID(o%d,k%d,t%d)", objID, keyID, typeID) return host.GetObjectID(objID, keyID, typeID) } func (vm *WasmVMBase) HostSetBytes(objID, keyID, typeID, stringRef, size int32) { + defer vm.catchPanicMessage() + host := vm.getKvStore(0) host.TraceAllf("HostSetBytes(o%d,k%d,t%d,r%d,s%d)", objID, keyID, typeID, stringRef, size) + + // delete key ? + if size < 0 { + host.DelKey(objID, keyID, typeID) + return + } + bytes := vm.impl.VMGetBytes(stringRef, size) host.SetBytes(objID, keyID, typeID, bytes) } +func (vm *WasmVMBase) Instantiate() error { + return errors.New("cannot be cloned") +} + func (vm *WasmVMBase) LinkHost(impl WasmVM, host *WasmHost) error { // trick vm into thinking it doesn't have to start the timeout timer // useful when debugging to prevent timing out on breakpoints @@ -167,28 +232,28 @@ func (vm *WasmVMBase) LinkHost(impl WasmVM, host *WasmHost) error { return nil } -func (vm *WasmVMBase) PreCall() []byte { - ptr := vm.impl.UnsafeMemory() - frame := make([]byte, len(ptr)) - copy(frame, ptr) - if vm.memoryDirty { - // clear memory and restore initialized data range - copy(ptr, make([]byte, len(ptr))) - copy(ptr[vm.memoryNonZero:], vm.memoryCopy) - } - vm.memoryDirty = true - return frame -} - -func (vm *WasmVMBase) PostCall(frame []byte) { - ptr := vm.impl.UnsafeMemory() - copy(ptr, frame) -} - func (vm *WasmVMBase) Run(runner func() error) (err error) { + defer func() { + r := recover() + if r == nil { + return + } + // could be the wrong panic message due to a WasmTime bug, so we always + // rethrow our intercepted first panic instead of WasmTime's last panic + if vm.panicErr != nil { + panic(vm.panicErr) + } + panic(r) + }() + if vm.timeoutStarted { // no need to wrap nested calls in timeout code - return runner() + err = runner() + if vm.panicErr != nil { + err = vm.panicErr + vm.panicErr = nil + } + return err } timeout := defaultTimeout @@ -215,35 +280,11 @@ func (vm *WasmVMBase) Run(runner func() error) (err error) { err = runner() done <- true vm.timeoutStarted = false - return err -} - -func (vm *WasmVMBase) SaveMemory() { - // find initialized data range in memory - ptr := vm.impl.UnsafeMemory() - if ptr == nil { - // this vm implementation does not communicate via mem pool - return - } - firstNonZero := -1 - lastNonZero := 0 - for i, b := range ptr { - if b != 0 { - if firstNonZero < 0 { - firstNonZero = i - } - lastNonZero = i - } - } - - // save copy of initialized data range - vm.memoryNonZero = len(ptr) - if firstNonZero >= 0 { - vm.memoryNonZero = firstNonZero - size := lastNonZero + 1 - firstNonZero - vm.memoryCopy = make([]byte, size) - copy(vm.memoryCopy, ptr[vm.memoryNonZero:]) + if vm.panicErr != nil { + err = vm.panicErr + vm.panicErr = nil } + return err } func (vm *WasmVMBase) VMGetBytes(offset, size int32) []byte { @@ -253,6 +294,11 @@ func (vm *WasmVMBase) VMGetBytes(offset, size int32) []byte { return bytes } +func (vm *WasmVMBase) VMGetSize() int32 { + ptr := vm.impl.UnsafeMemory() + return int32(len(ptr)) +} + func (vm *WasmVMBase) VMSetBytes(offset, size int32, bytes []byte) int32 { if size != 0 { ptr := vm.impl.UnsafeMemory() diff --git a/packages/vm/wasmlib/go/wasmlib/bytes.go b/packages/vm/wasmlib/go/wasmlib/bytes.go index df90a25487..cb7fd62f4e 100644 --- a/packages/vm/wasmlib/go/wasmlib/bytes.go +++ b/packages/vm/wasmlib/go/wasmlib/bytes.go @@ -8,6 +8,9 @@ type BytesDecoder struct { } func NewBytesDecoder(data []byte) *BytesDecoder { + if len(data) == 0 { + panic("cannot decode empty byte array, use exist()") + } return &BytesDecoder{data: data} } @@ -19,9 +22,13 @@ func (d *BytesDecoder) AgentID() ScAgentID { return NewScAgentIDFromBytes(d.Bytes()) } +func (d *BytesDecoder) Bool() bool { + return d.Uint8() != 0 +} + func (d *BytesDecoder) Bytes() []byte { - size := int(d.Int32()) - if len(d.data) < size { + size := d.Uint32() + if uint32(len(d.data)) < size { panic("insufficient bytes") } value := d.data[:size] @@ -51,6 +58,10 @@ func (d *BytesDecoder) Hname() ScHname { return NewScHnameFromBytes(d.Bytes()) } +func (d *BytesDecoder) Int8() int8 { + return int8(d.Uint8()) +} + func (d *BytesDecoder) Int16() int16 { return int16(d.leb128Decode(16)) } @@ -100,6 +111,27 @@ func (d *BytesDecoder) String() string { return string(d.Bytes()) } +func (d *BytesDecoder) Uint8() uint8 { + if len(d.data) == 0 { + panic("insufficient bytes") + } + value := d.data[0] + d.data = d.data[1:] + return value +} + +func (d *BytesDecoder) Uint16() uint16 { + return uint16(d.Int16()) +} + +func (d *BytesDecoder) Uint32() uint32 { + return uint32(d.Int32()) +} + +func (d *BytesDecoder) Uint64() uint64 { + return uint64(d.Int64()) +} + // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ type BytesEncoder struct { @@ -118,8 +150,15 @@ func (e *BytesEncoder) AgentID(value ScAgentID) *BytesEncoder { return e.Bytes(value.Bytes()) } +func (e *BytesEncoder) Bool(value bool) *BytesEncoder { + if value { + return e.Uint8(1) + } + return e.Uint8(0) +} + func (e *BytesEncoder) Bytes(value []byte) *BytesEncoder { - e.Int32(int32(len(value))) + e.Uint32(uint32(len(value))) e.data = append(e.data, value...) return e } @@ -144,6 +183,10 @@ func (e *BytesEncoder) Hname(value ScHname) *BytesEncoder { return e.Bytes(value.Bytes()) } +func (e *BytesEncoder) Int8(value int8) *BytesEncoder { + return e.Uint8(uint8(value)) +} + func (e *BytesEncoder) Int16(value int16) *BytesEncoder { return e.leb128Encode(int64(value)) } @@ -177,3 +220,20 @@ func (e *BytesEncoder) RequestID(value ScRequestID) *BytesEncoder { func (e *BytesEncoder) String(value string) *BytesEncoder { return e.Bytes([]byte(value)) } + +func (e *BytesEncoder) Uint8(value uint8) *BytesEncoder { + e.data = append(e.data, value) + return e +} + +func (e *BytesEncoder) Uint16(value uint16) *BytesEncoder { + return e.Int16(int16(value)) +} + +func (e *BytesEncoder) Uint32(value uint32) *BytesEncoder { + return e.Int32(int32(value)) +} + +func (e *BytesEncoder) Uint64(value uint64) *BytesEncoder { + return e.Int64(int64(value)) +} diff --git a/packages/vm/wasmlib/go/wasmlib/context.go b/packages/vm/wasmlib/go/wasmlib/context.go index 6cd4cbfb75..01a851af57 100644 --- a/packages/vm/wasmlib/go/wasmlib/context.go +++ b/packages/vm/wasmlib/go/wasmlib/context.go @@ -137,13 +137,6 @@ func (ctx ScUtility) Hname(value string) ScHname { return NewScHnameFromBytes(result) } -// generates a random value from 0 to max (exclusive max) using a deterministic RNG -func (ctx ScUtility) Random(max int64) int64 { - result := ctx.utility.CallFunc(KeyRandom, nil) - rnd := binary.LittleEndian.Uint64(result) - return int64(rnd % uint64(max)) -} - // converts an integer to its string representation func (ctx ScUtility) String(value int64) string { return strconv.FormatInt(value, 10) @@ -264,11 +257,6 @@ func (ctx ScFuncContext) Caller() ScAgentID { return Root.GetAgentID(KeyCaller).Value() } -// calls a smart contract function on the current contract -func (ctx ScFuncContext) CallSelf(hFunction ScHname, params *ScMutableMap, transfer *ScTransfers) ScImmutableMap { - return ctx.Call(ctx.Contract(), hFunction, params, transfer) -} - // deploys a smart contract func (ctx ScFuncContext) Deploy(programHash ScHash, name, description string, params *ScMutableMap) { encode := NewBytesEncoder() @@ -324,8 +312,18 @@ func (ctx ScFuncContext) Post(chainID ScChainID, hContract, hFunction ScHname, p Root.GetBytes(KeyPost).SetValue(encode.Data()) } -func (ctx ScFuncContext) PostSelf(hFunction ScHname, params *ScMutableMap, transfer ScTransfers, delay int32) { - ctx.Post(ctx.ChainID(), ctx.Contract(), hFunction, params, transfer, delay) +// TODO expose Entropy function + +// generates a random value from 0 to max (exclusive max) using a deterministic RNG +func (ctx ScFuncContext) Random(max int64) int64 { + state := ScMutableMap{objID: OBJ_ID_STATE} + rnd := state.GetBytes(KeyRandom) + seed := rnd.Value() + if len(seed) == 0 { + seed = Root.GetBytes(KeyRandom).Value() + } + rnd.SetValue(ctx.Utility().HashSha3(seed).Bytes()) + return int64(binary.LittleEndian.Uint64(seed[:8]) % uint64(max)) } // retrieve the request id of this transaction @@ -370,11 +368,6 @@ func (ctx ScViewContext) Call(contract, function ScHname, params *ScMutableMap) return Root.GetMap(KeyReturn).Immutable() } -// calls a smart contract function on the current contract -func (ctx ScViewContext) CallSelf(function ScHname, params *ScMutableMap) ScImmutableMap { - return ctx.Call(ctx.Contract(), function, params) -} - func (ctx ScViewContext) InitViewCallContext() { } diff --git a/packages/vm/wasmlib/go/wasmlib/coreaccounts/consts.go b/packages/vm/wasmlib/go/wasmlib/coreaccounts/consts.go index 0feb52eb41..08325d7f74 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreaccounts/consts.go +++ b/packages/vm/wasmlib/go/wasmlib/coreaccounts/consts.go @@ -16,12 +16,16 @@ const ( ) const ( - ParamAgentID = wasmlib.Key("a") - ParamWithdrawAmount = wasmlib.Key("m") - ParamWithdrawColor = wasmlib.Key("c") + ParamAgentID = "a" + ParamWithdrawAmount = "m" + ParamWithdrawColor = "c" ) -const ResultAccountNonce = wasmlib.Key("n") +const ( + ResultAccountNonce = "n" + ResultAgents = "this" + ResultBalances = "this" +) const ( FuncDeposit = "deposit" diff --git a/packages/vm/wasmlib/go/wasmlib/coreaccounts/params.go b/packages/vm/wasmlib/go/wasmlib/coreaccounts/params.go index 1ac40981d1..9c17692cec 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreaccounts/params.go +++ b/packages/vm/wasmlib/go/wasmlib/coreaccounts/params.go @@ -14,7 +14,7 @@ type ImmutableDepositParams struct { } func (s ImmutableDepositParams) AgentID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, ParamAgentID.KeyID()) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } type MutableDepositParams struct { @@ -22,7 +22,7 @@ type MutableDepositParams struct { } func (s MutableDepositParams) AgentID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, ParamAgentID.KeyID()) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } type ImmutableHarvestParams struct { @@ -30,11 +30,11 @@ type ImmutableHarvestParams struct { } func (s ImmutableHarvestParams) WithdrawAmount() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ParamWithdrawAmount.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamWithdrawAmount)) } func (s ImmutableHarvestParams) WithdrawColor() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, ParamWithdrawColor.KeyID()) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ParamWithdrawColor)) } type MutableHarvestParams struct { @@ -42,11 +42,11 @@ type MutableHarvestParams struct { } func (s MutableHarvestParams) WithdrawAmount() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ParamWithdrawAmount.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamWithdrawAmount)) } func (s MutableHarvestParams) WithdrawColor() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, ParamWithdrawColor.KeyID()) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ParamWithdrawColor)) } type ImmutableBalanceParams struct { @@ -54,7 +54,7 @@ type ImmutableBalanceParams struct { } func (s ImmutableBalanceParams) AgentID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, ParamAgentID.KeyID()) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } type MutableBalanceParams struct { @@ -62,7 +62,7 @@ type MutableBalanceParams struct { } func (s MutableBalanceParams) AgentID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, ParamAgentID.KeyID()) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } type ImmutableGetAccountNonceParams struct { @@ -70,7 +70,7 @@ type ImmutableGetAccountNonceParams struct { } func (s ImmutableGetAccountNonceParams) AgentID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, ParamAgentID.KeyID()) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } type MutableGetAccountNonceParams struct { @@ -78,5 +78,5 @@ type MutableGetAccountNonceParams struct { } func (s MutableGetAccountNonceParams) AgentID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, ParamAgentID.KeyID()) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamAgentID)) } diff --git a/packages/vm/wasmlib/go/wasmlib/coreaccounts/results.go b/packages/vm/wasmlib/go/wasmlib/coreaccounts/results.go index 075f9e3409..2dd3a316ec 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreaccounts/results.go +++ b/packages/vm/wasmlib/go/wasmlib/coreaccounts/results.go @@ -86,7 +86,7 @@ type ImmutableGetAccountNonceResults struct { } func (s ImmutableGetAccountNonceResults) AccountNonce() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ResultAccountNonce.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultAccountNonce)) } type MutableGetAccountNonceResults struct { @@ -94,7 +94,7 @@ type MutableGetAccountNonceResults struct { } func (s MutableGetAccountNonceResults) AccountNonce() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ResultAccountNonce.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultAccountNonce)) } type ImmutableTotalAssetsResults struct { diff --git a/packages/vm/wasmlib/go/wasmlib/coreblob/consts.go b/packages/vm/wasmlib/go/wasmlib/coreblob/consts.go index 9f2192c17c..34e266cf68 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreblob/consts.go +++ b/packages/vm/wasmlib/go/wasmlib/coreblob/consts.go @@ -16,13 +16,15 @@ const ( ) const ( - ParamField = wasmlib.Key("field") - ParamHash = wasmlib.Key("hash") + ParamBlobs = "this" + ParamField = "field" + ParamHash = "hash" ) const ( - ResultBytes = wasmlib.Key("bytes") - ResultHash = wasmlib.Key("hash") + ResultBlobSizes = "this" + ResultBytes = "bytes" + ResultHash = "hash" ) const ( diff --git a/packages/vm/wasmlib/go/wasmlib/coreblob/params.go b/packages/vm/wasmlib/go/wasmlib/coreblob/params.go index bda5540fe7..4a93f14cdb 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreblob/params.go +++ b/packages/vm/wasmlib/go/wasmlib/coreblob/params.go @@ -50,11 +50,11 @@ type ImmutableGetBlobFieldParams struct { } func (s ImmutableGetBlobFieldParams) Field() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, ParamField.KeyID()) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamField)) } func (s ImmutableGetBlobFieldParams) Hash() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, ParamHash.KeyID()) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamHash)) } type MutableGetBlobFieldParams struct { @@ -62,11 +62,11 @@ type MutableGetBlobFieldParams struct { } func (s MutableGetBlobFieldParams) Field() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, ParamField.KeyID()) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamField)) } func (s MutableGetBlobFieldParams) Hash() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, ParamHash.KeyID()) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamHash)) } type ImmutableGetBlobInfoParams struct { @@ -74,7 +74,7 @@ type ImmutableGetBlobInfoParams struct { } func (s ImmutableGetBlobInfoParams) Hash() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, ParamHash.KeyID()) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamHash)) } type MutableGetBlobInfoParams struct { @@ -82,5 +82,5 @@ type MutableGetBlobInfoParams struct { } func (s MutableGetBlobInfoParams) Hash() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, ParamHash.KeyID()) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamHash)) } diff --git a/packages/vm/wasmlib/go/wasmlib/coreblob/results.go b/packages/vm/wasmlib/go/wasmlib/coreblob/results.go index b9a5976423..8a24de4245 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreblob/results.go +++ b/packages/vm/wasmlib/go/wasmlib/coreblob/results.go @@ -14,7 +14,7 @@ type ImmutableStoreBlobResults struct { } func (s ImmutableStoreBlobResults) Hash() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, ResultHash.KeyID()) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ResultHash)) } type MutableStoreBlobResults struct { @@ -22,7 +22,7 @@ type MutableStoreBlobResults struct { } func (s MutableStoreBlobResults) Hash() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, ResultHash.KeyID()) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ResultHash)) } type ImmutableGetBlobFieldResults struct { @@ -30,7 +30,7 @@ type ImmutableGetBlobFieldResults struct { } func (s ImmutableGetBlobFieldResults) Bytes() wasmlib.ScImmutableBytes { - return wasmlib.NewScImmutableBytes(s.id, ResultBytes.KeyID()) + return wasmlib.NewScImmutableBytes(s.id, wasmlib.KeyID(ResultBytes)) } type MutableGetBlobFieldResults struct { @@ -38,7 +38,7 @@ type MutableGetBlobFieldResults struct { } func (s MutableGetBlobFieldResults) Bytes() wasmlib.ScMutableBytes { - return wasmlib.NewScMutableBytes(s.id, ResultBytes.KeyID()) + return wasmlib.NewScMutableBytes(s.id, wasmlib.KeyID(ResultBytes)) } type MapStringToImmutableInt32 struct { diff --git a/packages/vm/wasmlib/go/wasmlib/coreblocklog/consts.go b/packages/vm/wasmlib/go/wasmlib/coreblocklog/consts.go index f50b04564c..9b38d5f02d 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreblocklog/consts.go +++ b/packages/vm/wasmlib/go/wasmlib/coreblocklog/consts.go @@ -16,23 +16,23 @@ const ( ) const ( - ParamBlockIndex = wasmlib.Key("n") - ParamContractHname = wasmlib.Key("h") - ParamFromBlock = wasmlib.Key("f") - ParamRequestID = wasmlib.Key("u") - ParamToBlock = wasmlib.Key("t") + ParamBlockIndex = "n" + ParamContractHname = "h" + ParamFromBlock = "f" + ParamRequestID = "u" + ParamToBlock = "t" ) const ( - ResultBlockIndex = wasmlib.Key("n") - ResultBlockInfo = wasmlib.Key("i") - ResultEvent = wasmlib.Key("e") - ResultGoverningAddress = wasmlib.Key("g") - ResultRequestID = wasmlib.Key("u") - ResultRequestIndex = wasmlib.Key("r") - ResultRequestProcessed = wasmlib.Key("p") - ResultRequestRecord = wasmlib.Key("d") - ResultStateControllerAddress = wasmlib.Key("s") + ResultBlockIndex = "n" + ResultBlockInfo = "i" + ResultEvent = "e" + ResultGoverningAddress = "g" + ResultRequestID = "u" + ResultRequestIndex = "r" + ResultRequestProcessed = "p" + ResultRequestRecord = "d" + ResultStateControllerAddress = "s" ) const ( diff --git a/packages/vm/wasmlib/go/wasmlib/coreblocklog/params.go b/packages/vm/wasmlib/go/wasmlib/coreblocklog/params.go index 08f7955b9c..b67570e3b1 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreblocklog/params.go +++ b/packages/vm/wasmlib/go/wasmlib/coreblocklog/params.go @@ -14,7 +14,7 @@ type ImmutableGetBlockInfoParams struct { } func (s ImmutableGetBlockInfoParams) BlockIndex() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ParamBlockIndex.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) } type MutableGetBlockInfoParams struct { @@ -22,7 +22,7 @@ type MutableGetBlockInfoParams struct { } func (s MutableGetBlockInfoParams) BlockIndex() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ParamBlockIndex.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) } type ImmutableGetEventsForBlockParams struct { @@ -30,7 +30,7 @@ type ImmutableGetEventsForBlockParams struct { } func (s ImmutableGetEventsForBlockParams) BlockIndex() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ParamBlockIndex.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) } type MutableGetEventsForBlockParams struct { @@ -38,7 +38,7 @@ type MutableGetEventsForBlockParams struct { } func (s MutableGetEventsForBlockParams) BlockIndex() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ParamBlockIndex.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) } type ImmutableGetEventsForContractParams struct { @@ -46,15 +46,15 @@ type ImmutableGetEventsForContractParams struct { } func (s ImmutableGetEventsForContractParams) ContractHname() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, ParamContractHname.KeyID()) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(ParamContractHname)) } func (s ImmutableGetEventsForContractParams) FromBlock() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ParamFromBlock.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamFromBlock)) } func (s ImmutableGetEventsForContractParams) ToBlock() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ParamToBlock.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamToBlock)) } type MutableGetEventsForContractParams struct { @@ -62,15 +62,15 @@ type MutableGetEventsForContractParams struct { } func (s MutableGetEventsForContractParams) ContractHname() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, ParamContractHname.KeyID()) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(ParamContractHname)) } func (s MutableGetEventsForContractParams) FromBlock() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ParamFromBlock.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamFromBlock)) } func (s MutableGetEventsForContractParams) ToBlock() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ParamToBlock.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamToBlock)) } type ImmutableGetEventsForRequestParams struct { @@ -78,7 +78,7 @@ type ImmutableGetEventsForRequestParams struct { } func (s ImmutableGetEventsForRequestParams) RequestID() wasmlib.ScImmutableRequestID { - return wasmlib.NewScImmutableRequestID(s.id, ParamRequestID.KeyID()) + return wasmlib.NewScImmutableRequestID(s.id, wasmlib.KeyID(ParamRequestID)) } type MutableGetEventsForRequestParams struct { @@ -86,7 +86,7 @@ type MutableGetEventsForRequestParams struct { } func (s MutableGetEventsForRequestParams) RequestID() wasmlib.ScMutableRequestID { - return wasmlib.NewScMutableRequestID(s.id, ParamRequestID.KeyID()) + return wasmlib.NewScMutableRequestID(s.id, wasmlib.KeyID(ParamRequestID)) } type ImmutableGetRequestIDsForBlockParams struct { @@ -94,7 +94,7 @@ type ImmutableGetRequestIDsForBlockParams struct { } func (s ImmutableGetRequestIDsForBlockParams) BlockIndex() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ParamBlockIndex.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) } type MutableGetRequestIDsForBlockParams struct { @@ -102,7 +102,7 @@ type MutableGetRequestIDsForBlockParams struct { } func (s MutableGetRequestIDsForBlockParams) BlockIndex() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ParamBlockIndex.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) } type ImmutableGetRequestReceiptParams struct { @@ -110,7 +110,7 @@ type ImmutableGetRequestReceiptParams struct { } func (s ImmutableGetRequestReceiptParams) RequestID() wasmlib.ScImmutableRequestID { - return wasmlib.NewScImmutableRequestID(s.id, ParamRequestID.KeyID()) + return wasmlib.NewScImmutableRequestID(s.id, wasmlib.KeyID(ParamRequestID)) } type MutableGetRequestReceiptParams struct { @@ -118,7 +118,7 @@ type MutableGetRequestReceiptParams struct { } func (s MutableGetRequestReceiptParams) RequestID() wasmlib.ScMutableRequestID { - return wasmlib.NewScMutableRequestID(s.id, ParamRequestID.KeyID()) + return wasmlib.NewScMutableRequestID(s.id, wasmlib.KeyID(ParamRequestID)) } type ImmutableGetRequestReceiptsForBlockParams struct { @@ -126,7 +126,7 @@ type ImmutableGetRequestReceiptsForBlockParams struct { } func (s ImmutableGetRequestReceiptsForBlockParams) BlockIndex() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ParamBlockIndex.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) } type MutableGetRequestReceiptsForBlockParams struct { @@ -134,7 +134,7 @@ type MutableGetRequestReceiptsForBlockParams struct { } func (s MutableGetRequestReceiptsForBlockParams) BlockIndex() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ParamBlockIndex.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamBlockIndex)) } type ImmutableIsRequestProcessedParams struct { @@ -142,7 +142,7 @@ type ImmutableIsRequestProcessedParams struct { } func (s ImmutableIsRequestProcessedParams) RequestID() wasmlib.ScImmutableRequestID { - return wasmlib.NewScImmutableRequestID(s.id, ParamRequestID.KeyID()) + return wasmlib.NewScImmutableRequestID(s.id, wasmlib.KeyID(ParamRequestID)) } type MutableIsRequestProcessedParams struct { @@ -150,5 +150,5 @@ type MutableIsRequestProcessedParams struct { } func (s MutableIsRequestProcessedParams) RequestID() wasmlib.ScMutableRequestID { - return wasmlib.NewScMutableRequestID(s.id, ParamRequestID.KeyID()) + return wasmlib.NewScMutableRequestID(s.id, wasmlib.KeyID(ParamRequestID)) } diff --git a/packages/vm/wasmlib/go/wasmlib/coreblocklog/results.go b/packages/vm/wasmlib/go/wasmlib/coreblocklog/results.go index 153ced4bae..6fee94382e 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreblocklog/results.go +++ b/packages/vm/wasmlib/go/wasmlib/coreblocklog/results.go @@ -14,15 +14,15 @@ type ImmutableControlAddressesResults struct { } func (s ImmutableControlAddressesResults) BlockIndex() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ResultBlockIndex.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ResultBlockIndex)) } func (s ImmutableControlAddressesResults) GoverningAddress() wasmlib.ScImmutableAddress { - return wasmlib.NewScImmutableAddress(s.id, ResultGoverningAddress.KeyID()) + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ResultGoverningAddress)) } func (s ImmutableControlAddressesResults) StateControllerAddress() wasmlib.ScImmutableAddress { - return wasmlib.NewScImmutableAddress(s.id, ResultStateControllerAddress.KeyID()) + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ResultStateControllerAddress)) } type MutableControlAddressesResults struct { @@ -30,15 +30,15 @@ type MutableControlAddressesResults struct { } func (s MutableControlAddressesResults) BlockIndex() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ResultBlockIndex.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ResultBlockIndex)) } func (s MutableControlAddressesResults) GoverningAddress() wasmlib.ScMutableAddress { - return wasmlib.NewScMutableAddress(s.id, ResultGoverningAddress.KeyID()) + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ResultGoverningAddress)) } func (s MutableControlAddressesResults) StateControllerAddress() wasmlib.ScMutableAddress { - return wasmlib.NewScMutableAddress(s.id, ResultStateControllerAddress.KeyID()) + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ResultStateControllerAddress)) } type ImmutableGetBlockInfoResults struct { @@ -46,7 +46,7 @@ type ImmutableGetBlockInfoResults struct { } func (s ImmutableGetBlockInfoResults) BlockInfo() wasmlib.ScImmutableBytes { - return wasmlib.NewScImmutableBytes(s.id, ResultBlockInfo.KeyID()) + return wasmlib.NewScImmutableBytes(s.id, wasmlib.KeyID(ResultBlockInfo)) } type MutableGetBlockInfoResults struct { @@ -54,7 +54,7 @@ type MutableGetBlockInfoResults struct { } func (s MutableGetBlockInfoResults) BlockInfo() wasmlib.ScMutableBytes { - return wasmlib.NewScMutableBytes(s.id, ResultBlockInfo.KeyID()) + return wasmlib.NewScMutableBytes(s.id, wasmlib.KeyID(ResultBlockInfo)) } type ArrayOfImmutableBytes struct { @@ -74,7 +74,7 @@ type ImmutableGetEventsForBlockResults struct { } func (s ImmutableGetEventsForBlockResults) Event() ArrayOfImmutableBytes { - arrID := wasmlib.GetObjectID(s.id, ResultEvent.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) return ArrayOfImmutableBytes{objID: arrID} } @@ -99,7 +99,7 @@ type MutableGetEventsForBlockResults struct { } func (s MutableGetEventsForBlockResults) Event() ArrayOfMutableBytes { - arrID := wasmlib.GetObjectID(s.id, ResultEvent.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) return ArrayOfMutableBytes{objID: arrID} } @@ -108,7 +108,7 @@ type ImmutableGetEventsForContractResults struct { } func (s ImmutableGetEventsForContractResults) Event() ArrayOfImmutableBytes { - arrID := wasmlib.GetObjectID(s.id, ResultEvent.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) return ArrayOfImmutableBytes{objID: arrID} } @@ -117,7 +117,7 @@ type MutableGetEventsForContractResults struct { } func (s MutableGetEventsForContractResults) Event() ArrayOfMutableBytes { - arrID := wasmlib.GetObjectID(s.id, ResultEvent.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) return ArrayOfMutableBytes{objID: arrID} } @@ -126,7 +126,7 @@ type ImmutableGetEventsForRequestResults struct { } func (s ImmutableGetEventsForRequestResults) Event() ArrayOfImmutableBytes { - arrID := wasmlib.GetObjectID(s.id, ResultEvent.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) return ArrayOfImmutableBytes{objID: arrID} } @@ -135,7 +135,7 @@ type MutableGetEventsForRequestResults struct { } func (s MutableGetEventsForRequestResults) Event() ArrayOfMutableBytes { - arrID := wasmlib.GetObjectID(s.id, ResultEvent.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) return ArrayOfMutableBytes{objID: arrID} } @@ -144,11 +144,11 @@ type ImmutableGetLatestBlockInfoResults struct { } func (s ImmutableGetLatestBlockInfoResults) BlockIndex() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ResultBlockIndex.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ResultBlockIndex)) } func (s ImmutableGetLatestBlockInfoResults) BlockInfo() wasmlib.ScImmutableBytes { - return wasmlib.NewScImmutableBytes(s.id, ResultBlockInfo.KeyID()) + return wasmlib.NewScImmutableBytes(s.id, wasmlib.KeyID(ResultBlockInfo)) } type MutableGetLatestBlockInfoResults struct { @@ -156,11 +156,11 @@ type MutableGetLatestBlockInfoResults struct { } func (s MutableGetLatestBlockInfoResults) BlockIndex() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ResultBlockIndex.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ResultBlockIndex)) } func (s MutableGetLatestBlockInfoResults) BlockInfo() wasmlib.ScMutableBytes { - return wasmlib.NewScMutableBytes(s.id, ResultBlockInfo.KeyID()) + return wasmlib.NewScMutableBytes(s.id, wasmlib.KeyID(ResultBlockInfo)) } type ArrayOfImmutableRequestID struct { @@ -180,7 +180,7 @@ type ImmutableGetRequestIDsForBlockResults struct { } func (s ImmutableGetRequestIDsForBlockResults) RequestID() ArrayOfImmutableRequestID { - arrID := wasmlib.GetObjectID(s.id, ResultRequestID.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_REQUEST_ID) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultRequestID), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_REQUEST_ID) return ArrayOfImmutableRequestID{objID: arrID} } @@ -205,7 +205,7 @@ type MutableGetRequestIDsForBlockResults struct { } func (s MutableGetRequestIDsForBlockResults) RequestID() ArrayOfMutableRequestID { - arrID := wasmlib.GetObjectID(s.id, ResultRequestID.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_REQUEST_ID) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultRequestID), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_REQUEST_ID) return ArrayOfMutableRequestID{objID: arrID} } @@ -214,15 +214,15 @@ type ImmutableGetRequestReceiptResults struct { } func (s ImmutableGetRequestReceiptResults) BlockIndex() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ResultBlockIndex.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ResultBlockIndex)) } func (s ImmutableGetRequestReceiptResults) RequestIndex() wasmlib.ScImmutableInt16 { - return wasmlib.NewScImmutableInt16(s.id, ResultRequestIndex.KeyID()) + return wasmlib.NewScImmutableInt16(s.id, wasmlib.KeyID(ResultRequestIndex)) } func (s ImmutableGetRequestReceiptResults) RequestRecord() wasmlib.ScImmutableBytes { - return wasmlib.NewScImmutableBytes(s.id, ResultRequestRecord.KeyID()) + return wasmlib.NewScImmutableBytes(s.id, wasmlib.KeyID(ResultRequestRecord)) } type MutableGetRequestReceiptResults struct { @@ -230,15 +230,15 @@ type MutableGetRequestReceiptResults struct { } func (s MutableGetRequestReceiptResults) BlockIndex() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ResultBlockIndex.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ResultBlockIndex)) } func (s MutableGetRequestReceiptResults) RequestIndex() wasmlib.ScMutableInt16 { - return wasmlib.NewScMutableInt16(s.id, ResultRequestIndex.KeyID()) + return wasmlib.NewScMutableInt16(s.id, wasmlib.KeyID(ResultRequestIndex)) } func (s MutableGetRequestReceiptResults) RequestRecord() wasmlib.ScMutableBytes { - return wasmlib.NewScMutableBytes(s.id, ResultRequestRecord.KeyID()) + return wasmlib.NewScMutableBytes(s.id, wasmlib.KeyID(ResultRequestRecord)) } type ImmutableGetRequestReceiptsForBlockResults struct { @@ -246,7 +246,7 @@ type ImmutableGetRequestReceiptsForBlockResults struct { } func (s ImmutableGetRequestReceiptsForBlockResults) RequestRecord() ArrayOfImmutableBytes { - arrID := wasmlib.GetObjectID(s.id, ResultRequestRecord.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultRequestRecord), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) return ArrayOfImmutableBytes{objID: arrID} } @@ -255,7 +255,7 @@ type MutableGetRequestReceiptsForBlockResults struct { } func (s MutableGetRequestReceiptsForBlockResults) RequestRecord() ArrayOfMutableBytes { - arrID := wasmlib.GetObjectID(s.id, ResultRequestRecord.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultRequestRecord), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) return ArrayOfMutableBytes{objID: arrID} } @@ -264,7 +264,7 @@ type ImmutableIsRequestProcessedResults struct { } func (s ImmutableIsRequestProcessedResults) RequestProcessed() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, ResultRequestProcessed.KeyID()) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultRequestProcessed)) } type MutableIsRequestProcessedResults struct { @@ -272,5 +272,5 @@ type MutableIsRequestProcessedResults struct { } func (s MutableIsRequestProcessedResults) RequestProcessed() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, ResultRequestProcessed.KeyID()) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultRequestProcessed)) } diff --git a/packages/vm/wasmlib/go/wasmlib/coregovernance/consts.go b/packages/vm/wasmlib/go/wasmlib/coregovernance/consts.go index aec160544d..98cb3accc7 100644 --- a/packages/vm/wasmlib/go/wasmlib/coregovernance/consts.go +++ b/packages/vm/wasmlib/go/wasmlib/coregovernance/consts.go @@ -16,30 +16,30 @@ const ( ) const ( - ParamChainOwner = wasmlib.Key("oi") - ParamFeeColor = wasmlib.Key("fc") - ParamHname = wasmlib.Key("hn") - ParamMaxBlobSize = wasmlib.Key("bs") - ParamMaxEventSize = wasmlib.Key("es") - ParamMaxEventsPerReq = wasmlib.Key("ne") - ParamOwnerFee = wasmlib.Key("of") - ParamStateControllerAddress = wasmlib.Key("S") - ParamValidatorFee = wasmlib.Key("vf") + ParamChainOwner = "oi" + ParamFeeColor = "fc" + ParamHname = "hn" + ParamMaxBlobSize = "bs" + ParamMaxEventSize = "es" + ParamMaxEventsPerReq = "ne" + ParamOwnerFee = "of" + ParamStateControllerAddress = "S" + ParamValidatorFee = "vf" ) const ( - ResultAllowedStateControllerAddresses = wasmlib.Key("a") - ResultChainID = wasmlib.Key("c") - ResultChainOwnerID = wasmlib.Key("o") - ResultDefaultOwnerFee = wasmlib.Key("do") - ResultDefaultValidatorFee = wasmlib.Key("dv") - ResultDescription = wasmlib.Key("d") - ResultFeeColor = wasmlib.Key("f") - ResultMaxBlobSize = wasmlib.Key("mb") - ResultMaxEventSize = wasmlib.Key("me") - ResultMaxEventsPerReq = wasmlib.Key("mr") - ResultOwnerFee = wasmlib.Key("of") - ResultValidatorFee = wasmlib.Key("vf") + ResultAllowedStateControllerAddresses = "a" + ResultChainID = "c" + ResultChainOwnerID = "o" + ResultDefaultOwnerFee = "do" + ResultDefaultValidatorFee = "dv" + ResultDescription = "d" + ResultFeeColor = "f" + ResultMaxBlobSize = "mb" + ResultMaxEventSize = "me" + ResultMaxEventsPerReq = "mr" + ResultOwnerFee = "of" + ResultValidatorFee = "vf" ) const ( diff --git a/packages/vm/wasmlib/go/wasmlib/coregovernance/params.go b/packages/vm/wasmlib/go/wasmlib/coregovernance/params.go index 0ae22c402d..41e3e62ea2 100644 --- a/packages/vm/wasmlib/go/wasmlib/coregovernance/params.go +++ b/packages/vm/wasmlib/go/wasmlib/coregovernance/params.go @@ -14,15 +14,15 @@ type ImmutableAddAllowedStateControllerAddressParams struct { } func (s ImmutableAddAllowedStateControllerAddressParams) ChainOwner() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, ParamChainOwner.KeyID()) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamChainOwner)) } func (s ImmutableAddAllowedStateControllerAddressParams) FeeColor() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, ParamFeeColor.KeyID()) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ParamFeeColor)) } func (s ImmutableAddAllowedStateControllerAddressParams) StateControllerAddress() wasmlib.ScImmutableAddress { - return wasmlib.NewScImmutableAddress(s.id, ParamStateControllerAddress.KeyID()) + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ParamStateControllerAddress)) } type MutableAddAllowedStateControllerAddressParams struct { @@ -30,15 +30,15 @@ type MutableAddAllowedStateControllerAddressParams struct { } func (s MutableAddAllowedStateControllerAddressParams) ChainOwner() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, ParamChainOwner.KeyID()) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamChainOwner)) } func (s MutableAddAllowedStateControllerAddressParams) FeeColor() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, ParamFeeColor.KeyID()) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ParamFeeColor)) } func (s MutableAddAllowedStateControllerAddressParams) StateControllerAddress() wasmlib.ScMutableAddress { - return wasmlib.NewScMutableAddress(s.id, ParamStateControllerAddress.KeyID()) + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ParamStateControllerAddress)) } type ImmutableDelegateChainOwnershipParams struct { @@ -46,7 +46,7 @@ type ImmutableDelegateChainOwnershipParams struct { } func (s ImmutableDelegateChainOwnershipParams) ChainOwner() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, ParamChainOwner.KeyID()) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamChainOwner)) } type MutableDelegateChainOwnershipParams struct { @@ -54,7 +54,7 @@ type MutableDelegateChainOwnershipParams struct { } func (s MutableDelegateChainOwnershipParams) ChainOwner() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, ParamChainOwner.KeyID()) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamChainOwner)) } type ImmutableRemoveAllowedStateControllerAddressParams struct { @@ -62,7 +62,7 @@ type ImmutableRemoveAllowedStateControllerAddressParams struct { } func (s ImmutableRemoveAllowedStateControllerAddressParams) StateControllerAddress() wasmlib.ScImmutableAddress { - return wasmlib.NewScImmutableAddress(s.id, ParamStateControllerAddress.KeyID()) + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ParamStateControllerAddress)) } type MutableRemoveAllowedStateControllerAddressParams struct { @@ -70,7 +70,7 @@ type MutableRemoveAllowedStateControllerAddressParams struct { } func (s MutableRemoveAllowedStateControllerAddressParams) StateControllerAddress() wasmlib.ScMutableAddress { - return wasmlib.NewScMutableAddress(s.id, ParamStateControllerAddress.KeyID()) + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ParamStateControllerAddress)) } type ImmutableRotateStateControllerParams struct { @@ -78,7 +78,7 @@ type ImmutableRotateStateControllerParams struct { } func (s ImmutableRotateStateControllerParams) StateControllerAddress() wasmlib.ScImmutableAddress { - return wasmlib.NewScImmutableAddress(s.id, ParamStateControllerAddress.KeyID()) + return wasmlib.NewScImmutableAddress(s.id, wasmlib.KeyID(ParamStateControllerAddress)) } type MutableRotateStateControllerParams struct { @@ -86,7 +86,7 @@ type MutableRotateStateControllerParams struct { } func (s MutableRotateStateControllerParams) StateControllerAddress() wasmlib.ScMutableAddress { - return wasmlib.NewScMutableAddress(s.id, ParamStateControllerAddress.KeyID()) + return wasmlib.NewScMutableAddress(s.id, wasmlib.KeyID(ParamStateControllerAddress)) } type ImmutableSetChainInfoParams struct { @@ -94,23 +94,23 @@ type ImmutableSetChainInfoParams struct { } func (s ImmutableSetChainInfoParams) MaxBlobSize() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ParamMaxBlobSize.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ParamMaxBlobSize)) } func (s ImmutableSetChainInfoParams) MaxEventSize() wasmlib.ScImmutableInt16 { - return wasmlib.NewScImmutableInt16(s.id, ParamMaxEventSize.KeyID()) + return wasmlib.NewScImmutableInt16(s.id, wasmlib.KeyID(ParamMaxEventSize)) } func (s ImmutableSetChainInfoParams) MaxEventsPerReq() wasmlib.ScImmutableInt16 { - return wasmlib.NewScImmutableInt16(s.id, ParamMaxEventsPerReq.KeyID()) + return wasmlib.NewScImmutableInt16(s.id, wasmlib.KeyID(ParamMaxEventsPerReq)) } func (s ImmutableSetChainInfoParams) OwnerFee() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ParamOwnerFee.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamOwnerFee)) } func (s ImmutableSetChainInfoParams) ValidatorFee() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ParamValidatorFee.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamValidatorFee)) } type MutableSetChainInfoParams struct { @@ -118,23 +118,23 @@ type MutableSetChainInfoParams struct { } func (s MutableSetChainInfoParams) MaxBlobSize() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ParamMaxBlobSize.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ParamMaxBlobSize)) } func (s MutableSetChainInfoParams) MaxEventSize() wasmlib.ScMutableInt16 { - return wasmlib.NewScMutableInt16(s.id, ParamMaxEventSize.KeyID()) + return wasmlib.NewScMutableInt16(s.id, wasmlib.KeyID(ParamMaxEventSize)) } func (s MutableSetChainInfoParams) MaxEventsPerReq() wasmlib.ScMutableInt16 { - return wasmlib.NewScMutableInt16(s.id, ParamMaxEventsPerReq.KeyID()) + return wasmlib.NewScMutableInt16(s.id, wasmlib.KeyID(ParamMaxEventsPerReq)) } func (s MutableSetChainInfoParams) OwnerFee() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ParamOwnerFee.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamOwnerFee)) } func (s MutableSetChainInfoParams) ValidatorFee() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ParamValidatorFee.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamValidatorFee)) } type ImmutableSetContractFeeParams struct { @@ -142,15 +142,15 @@ type ImmutableSetContractFeeParams struct { } func (s ImmutableSetContractFeeParams) Hname() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, ParamHname.KeyID()) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(ParamHname)) } func (s ImmutableSetContractFeeParams) OwnerFee() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ParamOwnerFee.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamOwnerFee)) } func (s ImmutableSetContractFeeParams) ValidatorFee() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ParamValidatorFee.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamValidatorFee)) } type MutableSetContractFeeParams struct { @@ -158,15 +158,15 @@ type MutableSetContractFeeParams struct { } func (s MutableSetContractFeeParams) Hname() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, ParamHname.KeyID()) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(ParamHname)) } func (s MutableSetContractFeeParams) OwnerFee() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ParamOwnerFee.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamOwnerFee)) } func (s MutableSetContractFeeParams) ValidatorFee() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ParamValidatorFee.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamValidatorFee)) } type ImmutableSetDefaultFeeParams struct { @@ -174,11 +174,11 @@ type ImmutableSetDefaultFeeParams struct { } func (s ImmutableSetDefaultFeeParams) OwnerFee() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ParamOwnerFee.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamOwnerFee)) } func (s ImmutableSetDefaultFeeParams) ValidatorFee() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ParamValidatorFee.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ParamValidatorFee)) } type MutableSetDefaultFeeParams struct { @@ -186,11 +186,11 @@ type MutableSetDefaultFeeParams struct { } func (s MutableSetDefaultFeeParams) OwnerFee() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ParamOwnerFee.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamOwnerFee)) } func (s MutableSetDefaultFeeParams) ValidatorFee() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ParamValidatorFee.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ParamValidatorFee)) } type ImmutableGetFeeInfoParams struct { @@ -198,7 +198,7 @@ type ImmutableGetFeeInfoParams struct { } func (s ImmutableGetFeeInfoParams) Hname() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, ParamHname.KeyID()) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(ParamHname)) } type MutableGetFeeInfoParams struct { @@ -206,5 +206,5 @@ type MutableGetFeeInfoParams struct { } func (s MutableGetFeeInfoParams) Hname() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, ParamHname.KeyID()) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(ParamHname)) } diff --git a/packages/vm/wasmlib/go/wasmlib/coregovernance/results.go b/packages/vm/wasmlib/go/wasmlib/coregovernance/results.go index 0b2c92f4c5..c322210258 100644 --- a/packages/vm/wasmlib/go/wasmlib/coregovernance/results.go +++ b/packages/vm/wasmlib/go/wasmlib/coregovernance/results.go @@ -26,7 +26,7 @@ type ImmutableGetAllowedStateControllerAddressesResults struct { } func (s ImmutableGetAllowedStateControllerAddressesResults) AllowedStateControllerAddresses() ArrayOfImmutableBytes { - arrID := wasmlib.GetObjectID(s.id, ResultAllowedStateControllerAddresses.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultAllowedStateControllerAddresses), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) return ArrayOfImmutableBytes{objID: arrID} } @@ -51,7 +51,7 @@ type MutableGetAllowedStateControllerAddressesResults struct { } func (s MutableGetAllowedStateControllerAddressesResults) AllowedStateControllerAddresses() ArrayOfMutableBytes { - arrID := wasmlib.GetObjectID(s.id, ResultAllowedStateControllerAddresses.KeyID(), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) + arrID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultAllowedStateControllerAddresses), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES) return ArrayOfMutableBytes{objID: arrID} } @@ -60,39 +60,39 @@ type ImmutableGetChainInfoResults struct { } func (s ImmutableGetChainInfoResults) ChainID() wasmlib.ScImmutableChainID { - return wasmlib.NewScImmutableChainID(s.id, ResultChainID.KeyID()) + return wasmlib.NewScImmutableChainID(s.id, wasmlib.KeyID(ResultChainID)) } func (s ImmutableGetChainInfoResults) ChainOwnerID() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, ResultChainOwnerID.KeyID()) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ResultChainOwnerID)) } func (s ImmutableGetChainInfoResults) DefaultOwnerFee() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ResultDefaultOwnerFee.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultDefaultOwnerFee)) } func (s ImmutableGetChainInfoResults) DefaultValidatorFee() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ResultDefaultValidatorFee.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultDefaultValidatorFee)) } func (s ImmutableGetChainInfoResults) Description() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, ResultDescription.KeyID()) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ResultDescription)) } func (s ImmutableGetChainInfoResults) FeeColor() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, ResultFeeColor.KeyID()) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ResultFeeColor)) } func (s ImmutableGetChainInfoResults) MaxBlobSize() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ResultMaxBlobSize.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ResultMaxBlobSize)) } func (s ImmutableGetChainInfoResults) MaxEventSize() wasmlib.ScImmutableInt16 { - return wasmlib.NewScImmutableInt16(s.id, ResultMaxEventSize.KeyID()) + return wasmlib.NewScImmutableInt16(s.id, wasmlib.KeyID(ResultMaxEventSize)) } func (s ImmutableGetChainInfoResults) MaxEventsPerReq() wasmlib.ScImmutableInt16 { - return wasmlib.NewScImmutableInt16(s.id, ResultMaxEventsPerReq.KeyID()) + return wasmlib.NewScImmutableInt16(s.id, wasmlib.KeyID(ResultMaxEventsPerReq)) } type MutableGetChainInfoResults struct { @@ -100,39 +100,39 @@ type MutableGetChainInfoResults struct { } func (s MutableGetChainInfoResults) ChainID() wasmlib.ScMutableChainID { - return wasmlib.NewScMutableChainID(s.id, ResultChainID.KeyID()) + return wasmlib.NewScMutableChainID(s.id, wasmlib.KeyID(ResultChainID)) } func (s MutableGetChainInfoResults) ChainOwnerID() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, ResultChainOwnerID.KeyID()) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ResultChainOwnerID)) } func (s MutableGetChainInfoResults) DefaultOwnerFee() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ResultDefaultOwnerFee.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultDefaultOwnerFee)) } func (s MutableGetChainInfoResults) DefaultValidatorFee() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ResultDefaultValidatorFee.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultDefaultValidatorFee)) } func (s MutableGetChainInfoResults) Description() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, ResultDescription.KeyID()) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ResultDescription)) } func (s MutableGetChainInfoResults) FeeColor() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, ResultFeeColor.KeyID()) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ResultFeeColor)) } func (s MutableGetChainInfoResults) MaxBlobSize() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ResultMaxBlobSize.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ResultMaxBlobSize)) } func (s MutableGetChainInfoResults) MaxEventSize() wasmlib.ScMutableInt16 { - return wasmlib.NewScMutableInt16(s.id, ResultMaxEventSize.KeyID()) + return wasmlib.NewScMutableInt16(s.id, wasmlib.KeyID(ResultMaxEventSize)) } func (s MutableGetChainInfoResults) MaxEventsPerReq() wasmlib.ScMutableInt16 { - return wasmlib.NewScMutableInt16(s.id, ResultMaxEventsPerReq.KeyID()) + return wasmlib.NewScMutableInt16(s.id, wasmlib.KeyID(ResultMaxEventsPerReq)) } type ImmutableGetFeeInfoResults struct { @@ -140,15 +140,15 @@ type ImmutableGetFeeInfoResults struct { } func (s ImmutableGetFeeInfoResults) FeeColor() wasmlib.ScImmutableColor { - return wasmlib.NewScImmutableColor(s.id, ResultFeeColor.KeyID()) + return wasmlib.NewScImmutableColor(s.id, wasmlib.KeyID(ResultFeeColor)) } func (s ImmutableGetFeeInfoResults) OwnerFee() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ResultOwnerFee.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultOwnerFee)) } func (s ImmutableGetFeeInfoResults) ValidatorFee() wasmlib.ScImmutableInt64 { - return wasmlib.NewScImmutableInt64(s.id, ResultValidatorFee.KeyID()) + return wasmlib.NewScImmutableInt64(s.id, wasmlib.KeyID(ResultValidatorFee)) } type MutableGetFeeInfoResults struct { @@ -156,15 +156,15 @@ type MutableGetFeeInfoResults struct { } func (s MutableGetFeeInfoResults) FeeColor() wasmlib.ScMutableColor { - return wasmlib.NewScMutableColor(s.id, ResultFeeColor.KeyID()) + return wasmlib.NewScMutableColor(s.id, wasmlib.KeyID(ResultFeeColor)) } func (s MutableGetFeeInfoResults) OwnerFee() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ResultOwnerFee.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultOwnerFee)) } func (s MutableGetFeeInfoResults) ValidatorFee() wasmlib.ScMutableInt64 { - return wasmlib.NewScMutableInt64(s.id, ResultValidatorFee.KeyID()) + return wasmlib.NewScMutableInt64(s.id, wasmlib.KeyID(ResultValidatorFee)) } type ImmutableGetMaxBlobSizeResults struct { @@ -172,7 +172,7 @@ type ImmutableGetMaxBlobSizeResults struct { } func (s ImmutableGetMaxBlobSizeResults) MaxBlobSize() wasmlib.ScImmutableInt32 { - return wasmlib.NewScImmutableInt32(s.id, ResultMaxBlobSize.KeyID()) + return wasmlib.NewScImmutableInt32(s.id, wasmlib.KeyID(ResultMaxBlobSize)) } type MutableGetMaxBlobSizeResults struct { @@ -180,5 +180,5 @@ type MutableGetMaxBlobSizeResults struct { } func (s MutableGetMaxBlobSizeResults) MaxBlobSize() wasmlib.ScMutableInt32 { - return wasmlib.NewScMutableInt32(s.id, ResultMaxBlobSize.KeyID()) + return wasmlib.NewScMutableInt32(s.id, wasmlib.KeyID(ResultMaxBlobSize)) } diff --git a/packages/vm/wasmlib/go/wasmlib/coreroot/consts.go b/packages/vm/wasmlib/go/wasmlib/coreroot/consts.go index c607e01f0b..b791ab59f4 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreroot/consts.go +++ b/packages/vm/wasmlib/go/wasmlib/coreroot/consts.go @@ -16,17 +16,17 @@ const ( ) const ( - ParamDeployer = wasmlib.Key("dp") - ParamDescription = wasmlib.Key("ds") - ParamHname = wasmlib.Key("hn") - ParamName = wasmlib.Key("nm") - ParamProgramHash = wasmlib.Key("ph") + ParamDeployer = "dp" + ParamDescription = "ds" + ParamHname = "hn" + ParamName = "nm" + ParamProgramHash = "ph" ) const ( - ResultContractFound = wasmlib.Key("cf") - ResultContractRecData = wasmlib.Key("dt") - ResultContractRegistry = wasmlib.Key("r") + ResultContractFound = "cf" + ResultContractRecData = "dt" + ResultContractRegistry = "r" ) const ( diff --git a/packages/vm/wasmlib/go/wasmlib/coreroot/params.go b/packages/vm/wasmlib/go/wasmlib/coreroot/params.go index 673849677e..f302c05d5c 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreroot/params.go +++ b/packages/vm/wasmlib/go/wasmlib/coreroot/params.go @@ -14,15 +14,15 @@ type ImmutableDeployContractParams struct { } func (s ImmutableDeployContractParams) Description() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, ParamDescription.KeyID()) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamDescription)) } func (s ImmutableDeployContractParams) Name() wasmlib.ScImmutableString { - return wasmlib.NewScImmutableString(s.id, ParamName.KeyID()) + return wasmlib.NewScImmutableString(s.id, wasmlib.KeyID(ParamName)) } func (s ImmutableDeployContractParams) ProgramHash() wasmlib.ScImmutableHash { - return wasmlib.NewScImmutableHash(s.id, ParamProgramHash.KeyID()) + return wasmlib.NewScImmutableHash(s.id, wasmlib.KeyID(ParamProgramHash)) } type MutableDeployContractParams struct { @@ -30,15 +30,15 @@ type MutableDeployContractParams struct { } func (s MutableDeployContractParams) Description() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, ParamDescription.KeyID()) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamDescription)) } func (s MutableDeployContractParams) Name() wasmlib.ScMutableString { - return wasmlib.NewScMutableString(s.id, ParamName.KeyID()) + return wasmlib.NewScMutableString(s.id, wasmlib.KeyID(ParamName)) } func (s MutableDeployContractParams) ProgramHash() wasmlib.ScMutableHash { - return wasmlib.NewScMutableHash(s.id, ParamProgramHash.KeyID()) + return wasmlib.NewScMutableHash(s.id, wasmlib.KeyID(ParamProgramHash)) } type ImmutableGrantDeployPermissionParams struct { @@ -46,7 +46,7 @@ type ImmutableGrantDeployPermissionParams struct { } func (s ImmutableGrantDeployPermissionParams) Deployer() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, ParamDeployer.KeyID()) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamDeployer)) } type MutableGrantDeployPermissionParams struct { @@ -54,7 +54,7 @@ type MutableGrantDeployPermissionParams struct { } func (s MutableGrantDeployPermissionParams) Deployer() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, ParamDeployer.KeyID()) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamDeployer)) } type ImmutableRevokeDeployPermissionParams struct { @@ -62,7 +62,7 @@ type ImmutableRevokeDeployPermissionParams struct { } func (s ImmutableRevokeDeployPermissionParams) Deployer() wasmlib.ScImmutableAgentID { - return wasmlib.NewScImmutableAgentID(s.id, ParamDeployer.KeyID()) + return wasmlib.NewScImmutableAgentID(s.id, wasmlib.KeyID(ParamDeployer)) } type MutableRevokeDeployPermissionParams struct { @@ -70,7 +70,7 @@ type MutableRevokeDeployPermissionParams struct { } func (s MutableRevokeDeployPermissionParams) Deployer() wasmlib.ScMutableAgentID { - return wasmlib.NewScMutableAgentID(s.id, ParamDeployer.KeyID()) + return wasmlib.NewScMutableAgentID(s.id, wasmlib.KeyID(ParamDeployer)) } type ImmutableFindContractParams struct { @@ -78,7 +78,7 @@ type ImmutableFindContractParams struct { } func (s ImmutableFindContractParams) Hname() wasmlib.ScImmutableHname { - return wasmlib.NewScImmutableHname(s.id, ParamHname.KeyID()) + return wasmlib.NewScImmutableHname(s.id, wasmlib.KeyID(ParamHname)) } type MutableFindContractParams struct { @@ -86,5 +86,5 @@ type MutableFindContractParams struct { } func (s MutableFindContractParams) Hname() wasmlib.ScMutableHname { - return wasmlib.NewScMutableHname(s.id, ParamHname.KeyID()) + return wasmlib.NewScMutableHname(s.id, wasmlib.KeyID(ParamHname)) } diff --git a/packages/vm/wasmlib/go/wasmlib/coreroot/results.go b/packages/vm/wasmlib/go/wasmlib/coreroot/results.go index 3ade4f3e44..7108487a19 100644 --- a/packages/vm/wasmlib/go/wasmlib/coreroot/results.go +++ b/packages/vm/wasmlib/go/wasmlib/coreroot/results.go @@ -14,11 +14,11 @@ type ImmutableFindContractResults struct { } func (s ImmutableFindContractResults) ContractFound() wasmlib.ScImmutableBytes { - return wasmlib.NewScImmutableBytes(s.id, ResultContractFound.KeyID()) + return wasmlib.NewScImmutableBytes(s.id, wasmlib.KeyID(ResultContractFound)) } func (s ImmutableFindContractResults) ContractRecData() wasmlib.ScImmutableBytes { - return wasmlib.NewScImmutableBytes(s.id, ResultContractRecData.KeyID()) + return wasmlib.NewScImmutableBytes(s.id, wasmlib.KeyID(ResultContractRecData)) } type MutableFindContractResults struct { @@ -26,11 +26,11 @@ type MutableFindContractResults struct { } func (s MutableFindContractResults) ContractFound() wasmlib.ScMutableBytes { - return wasmlib.NewScMutableBytes(s.id, ResultContractFound.KeyID()) + return wasmlib.NewScMutableBytes(s.id, wasmlib.KeyID(ResultContractFound)) } func (s MutableFindContractResults) ContractRecData() wasmlib.ScMutableBytes { - return wasmlib.NewScMutableBytes(s.id, ResultContractRecData.KeyID()) + return wasmlib.NewScMutableBytes(s.id, wasmlib.KeyID(ResultContractRecData)) } type MapHnameToImmutableBytes struct { @@ -46,7 +46,7 @@ type ImmutableGetContractRecordsResults struct { } func (s ImmutableGetContractRecordsResults) ContractRegistry() MapHnameToImmutableBytes { - mapID := wasmlib.GetObjectID(s.id, ResultContractRegistry.KeyID(), wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultContractRegistry), wasmlib.TYPE_MAP) return MapHnameToImmutableBytes{objID: mapID} } @@ -67,6 +67,6 @@ type MutableGetContractRecordsResults struct { } func (s MutableGetContractRecordsResults) ContractRegistry() MapHnameToMutableBytes { - mapID := wasmlib.GetObjectID(s.id, ResultContractRegistry.KeyID(), wasmlib.TYPE_MAP) + mapID := wasmlib.GetObjectID(s.id, wasmlib.KeyID(ResultContractRegistry), wasmlib.TYPE_MAP) return MapHnameToMutableBytes{objID: mapID} } diff --git a/packages/vm/wasmlib/go/wasmlib/events.go b/packages/vm/wasmlib/go/wasmlib/events.go new file mode 100644 index 0000000000..feabb505c5 --- /dev/null +++ b/packages/vm/wasmlib/go/wasmlib/events.go @@ -0,0 +1,101 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +package wasmlib + +import ( + "strconv" +) + +// encodes separate entities into a byte buffer +type EventEncoder struct { + event string +} + +func NewEventEncoder(eventName string) *EventEncoder { + e := &EventEncoder{event: eventName} + timestamp := Root.GetInt64(KeyTimestamp).Value() + // convert nanoseconds to seconds + return e.Int64(timestamp / 1_000_000_000) +} + +func (e *EventEncoder) Address(value ScAddress) *EventEncoder { + return e.String(value.String()) +} + +func (e *EventEncoder) AgentID(value ScAgentID) *EventEncoder { + return e.String(value.String()) +} + +func (e *EventEncoder) Bool(value bool) *EventEncoder { + if value { + return e.Uint8(1) + } + return e.Uint8(0) +} + +func (e *EventEncoder) Bytes(value []byte) *EventEncoder { + return e.String(base58Encode(value)) +} + +func (e *EventEncoder) ChainID(value ScChainID) *EventEncoder { + return e.String(value.String()) +} + +func (e *EventEncoder) Color(value ScColor) *EventEncoder { + return e.String(value.String()) +} + +func (e *EventEncoder) Emit() { + Root.GetString(KeyEvent).SetValue(e.event) +} + +func (e *EventEncoder) Hash(value ScHash) *EventEncoder { + return e.String(value.String()) +} + +func (e *EventEncoder) Hname(value ScHname) *EventEncoder { + return e.String(value.String()) +} + +func (e *EventEncoder) Int8(value int8) *EventEncoder { + return e.Int64(int64(value)) +} + +func (e *EventEncoder) Int16(value int16) *EventEncoder { + return e.Int64(int64(value)) +} + +func (e *EventEncoder) Int32(value int32) *EventEncoder { + return e.Int64(int64(value)) +} + +func (e *EventEncoder) Int64(value int64) *EventEncoder { + return e.String(strconv.FormatInt(value, 10)) +} + +func (e *EventEncoder) RequestID(value ScRequestID) *EventEncoder { + return e.String(value.String()) +} + +func (e *EventEncoder) String(value string) *EventEncoder { + // TODO encode potential vertical bars that are present in the value string + e.event += "|" + value + return e +} + +func (e *EventEncoder) Uint8(value uint8) *EventEncoder { + return e.Uint64(uint64(value)) +} + +func (e *EventEncoder) Uint16(value uint16) *EventEncoder { + return e.Uint64(uint64(value)) +} + +func (e *EventEncoder) Uint32(value uint32) *EventEncoder { + return e.Uint64(uint64(value)) +} + +func (e *EventEncoder) Uint64(value uint64) *EventEncoder { + return e.String(strconv.FormatUint(value, 10)) +} diff --git a/packages/vm/wasmlib/go/wasmlib/hashtypes.go b/packages/vm/wasmlib/go/wasmlib/hashtypes.go index 05c8500f16..70b0904930 100644 --- a/packages/vm/wasmlib/go/wasmlib/hashtypes.go +++ b/packages/vm/wasmlib/go/wasmlib/hashtypes.go @@ -5,7 +5,6 @@ package wasmlib import ( "encoding/binary" - "strconv" ) // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ @@ -35,7 +34,7 @@ func (o ScAddress) Bytes() []byte { } func (o ScAddress) KeyID() Key32 { - return GetKeyIDFromBytes(o.Bytes()) + return GetKeyIDFromBytes(o.id[:]) } func (o ScAddress) String() string { @@ -79,7 +78,7 @@ func (o ScAgentID) Hname() ScHname { } func (o ScAgentID) KeyID() Key32 { - return GetKeyIDFromBytes(o.Bytes()) + return GetKeyIDFromBytes(o.id[:]) } func (o ScAgentID) IsAddress() bool { @@ -116,7 +115,7 @@ func (o ScChainID) Bytes() []byte { } func (o ScChainID) KeyID() Key32 { - return GetKeyIDFromBytes(o.Bytes()) + return GetKeyIDFromBytes(o.id[:]) } func (o ScChainID) String() string { @@ -160,7 +159,7 @@ func (o ScColor) Bytes() []byte { } func (o ScColor) KeyID() Key32 { - return GetKeyIDFromBytes(o.Bytes()) + return GetKeyIDFromBytes(o.id[:]) } func (o ScColor) String() string { @@ -187,7 +186,7 @@ func (o ScHash) Bytes() []byte { } func (o ScHash) KeyID() Key32 { - return GetKeyIDFromBytes(o.Bytes()) + return GetKeyIDFromBytes(o.id[:]) } func (o ScHash) String() string { @@ -217,7 +216,14 @@ func (hn ScHname) KeyID() Key32 { } func (hn ScHname) String() string { - return strconv.FormatInt(int64(hn), 10) + const hex = "0123456789abcdef" + res := make([]byte, 8) + val := hn + for i := 0; i < 8; i++ { + res[7-i] = hex[val&0x0f] + val >>= 4 + } + return string(res) } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ @@ -240,7 +246,7 @@ func (o ScRequestID) Bytes() []byte { } func (o ScRequestID) KeyID() Key32 { - return GetKeyIDFromBytes(o.Bytes()) + return GetKeyIDFromBytes(o.id[:]) } func (o ScRequestID) String() string { diff --git a/packages/vm/wasmlib/go/wasmlib/host.go b/packages/vm/wasmlib/go/wasmlib/host.go index 899305216f..8955e1401a 100644 --- a/packages/vm/wasmlib/go/wasmlib/host.go +++ b/packages/vm/wasmlib/go/wasmlib/host.go @@ -9,22 +9,25 @@ import "encoding/binary" const ( // all TYPE_* values should exactly match the counterpart OBJTYPE_* values on the host! TYPE_ARRAY int32 = 0x20 - TYPE_ARRAY16 int32 = 0x30 - TYPE_CALL int32 = 0x40 + TYPE_ARRAY16 int32 = 0x60 + TYPE_CALL int32 = 0x80 + TYPE_MASK int32 = 0x1f TYPE_ADDRESS int32 = 1 TYPE_AGENT_ID int32 = 2 - TYPE_BYTES int32 = 3 - TYPE_CHAIN_ID int32 = 4 - TYPE_COLOR int32 = 5 - TYPE_HASH int32 = 6 - TYPE_HNAME int32 = 7 - TYPE_INT16 int32 = 8 - TYPE_INT32 int32 = 9 - TYPE_INT64 int32 = 10 - TYPE_MAP int32 = 11 - TYPE_REQUEST_ID int32 = 12 - TYPE_STRING int32 = 13 + 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 OBJ_ID_NULL int32 = 0 OBJ_ID_ROOT int32 = 1 @@ -33,7 +36,7 @@ const ( OBJ_ID_RESULTS int32 = 4 ) -var TypeSizes = [...]uint8{0, 33, 37, 0, 33, 32, 32, 4, 2, 4, 8, 0, 34, 0} +var TypeSizes = [...]uint8{0, 33, 37, 1, 0, 33, 32, 32, 4, 1, 2, 4, 8, 0, 34, 0} type ( ScFuncContextFunction func(ScFuncContext) @@ -43,6 +46,7 @@ type ( AddFunc(f ScFuncContextFunction) []ScFuncContextFunction AddView(v ScViewContextFunction) []ScViewContextFunction CallFunc(objID, keyID int32, params []byte) []byte + DelKey(objID, keyID, typeID int32) Exists(objID, keyID, typeID int32) bool GetBytes(objID, keyID, typeID int32) []byte GetKeyIDFromBytes(bytes []byte) int32 @@ -78,6 +82,10 @@ func Clear(objID int32) { SetBytes(objID, KeyLength, TYPE_INT32, zero[:]) } +func DelKey(objID int32, keyID Key32, typeID int32) { + host.DelKey(objID, int32(keyID), typeID) +} + func Exists(objID int32, keyID Key32, typeID int32) bool { return host.Exists(objID, int32(keyID), typeID) } @@ -98,6 +106,12 @@ func GetKeyIDFromString(key string) Key32 { return Key32(host.GetKeyIDFromString(key)) } +func GetKeyIDFromUint64(value uint64, nrOfBytes int) Key32 { + bytes := make([]byte, 8) + binary.LittleEndian.PutUint64(bytes, value) + return GetKeyIDFromBytes(bytes[:nrOfBytes]) +} + func GetLength(objID int32) int32 { bytes := GetBytes(objID, KeyLength, TYPE_INT32) return int32(binary.LittleEndian.Uint32(bytes)) diff --git a/packages/vm/wasmlib/go/wasmlib/immutable.go b/packages/vm/wasmlib/go/wasmlib/immutable.go index e1b5b4f446..2dbc8ea7de 100644 --- a/packages/vm/wasmlib/go/wasmlib/immutable.go +++ b/packages/vm/wasmlib/go/wasmlib/immutable.go @@ -82,6 +82,47 @@ func (o ScImmutableAgentIDArray) Length() int32 { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ +type ScImmutableBool struct { + objID int32 + keyID Key32 +} + +func NewScImmutableBool(objID int32, keyID Key32) ScImmutableBool { + return ScImmutableBool{objID: objID, keyID: keyID} +} + +func (o ScImmutableBool) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_BOOL) +} + +func (o ScImmutableBool) String() string { + if o.Value() { + return "1" + } + return "0" +} + +func (o ScImmutableBool) Value() bool { + bytes := GetBytes(o.objID, o.keyID, TYPE_BOOL) + return bytes[0] != 0 +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScImmutableBoolArray struct { + objID int32 +} + +func (o ScImmutableBoolArray) GetBool(index int32) ScImmutableBool { + return ScImmutableBool{objID: o.objID, keyID: Key32(index)} +} + +func (o ScImmutableBoolArray) Length() int32 { + return GetLength(o.objID) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + type ScImmutableBytes struct { objID int32 keyID Key32 @@ -267,6 +308,44 @@ func (o ScImmutableHnameArray) Length() int32 { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ +type ScImmutableInt8 struct { + objID int32 + keyID Key32 +} + +func NewScImmutableInt8(objID int32, keyID Key32) ScImmutableInt8 { + return ScImmutableInt8{objID: objID, keyID: keyID} +} + +func (o ScImmutableInt8) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_INT8) +} + +func (o ScImmutableInt8) String() string { + return strconv.FormatInt(int64(o.Value()), 10) +} + +func (o ScImmutableInt8) Value() int8 { + bytes := GetBytes(o.objID, o.keyID, TYPE_INT8) + return int8(bytes[0]) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScImmutableInt8Array struct { + objID int32 +} + +func (o ScImmutableInt8Array) GetInt8(index int32) ScImmutableInt8 { + return ScImmutableInt8{objID: o.objID, keyID: Key32(index)} +} + +func (o ScImmutableInt8Array) Length() int32 { + return GetLength(o.objID) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + type ScImmutableInt16 struct { objID int32 keyID Key32 @@ -407,6 +486,15 @@ func (o ScImmutableMap) GetAgentIDArray(key MapKey) ScImmutableAgentIDArray { return ScImmutableAgentIDArray{objID: arrID} } +func (o ScImmutableMap) GetBool(key MapKey) ScImmutableBool { + return ScImmutableBool{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScImmutableMap) GetBoolArray(key MapKey) ScImmutableBoolArray { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_BOOL|TYPE_ARRAY) + return ScImmutableBoolArray{objID: arrID} +} + func (o ScImmutableMap) GetBytes(key MapKey) ScImmutableBytes { return ScImmutableBytes{objID: o.objID, keyID: key.KeyID()} } @@ -452,6 +540,15 @@ func (o ScImmutableMap) GetHnameArray(key MapKey) ScImmutableHnameArray { return ScImmutableHnameArray{objID: arrID} } +func (o ScImmutableMap) GetInt8(key MapKey) ScImmutableInt8 { + return ScImmutableInt8{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScImmutableMap) GetInt8Array(key MapKey) ScImmutableInt8Array { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_INT8|TYPE_ARRAY) + return ScImmutableInt8Array{objID: arrID} +} + func (o ScImmutableMap) GetInt16(key MapKey) ScImmutableInt16 { return ScImmutableInt16{objID: o.objID, keyID: key.KeyID()} } @@ -507,6 +604,42 @@ func (o ScImmutableMap) GetStringArray(key MapKey) ScImmutableStringArray { return ScImmutableStringArray{objID: arrID} } +func (o ScImmutableMap) GetUint8(key MapKey) ScImmutableUint8 { + return ScImmutableUint8{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScImmutableMap) GetUint8Array(key MapKey) ScImmutableUint8Array { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_INT8|TYPE_ARRAY) + return ScImmutableUint8Array{objID: arrID} +} + +func (o ScImmutableMap) GetUint16(key MapKey) ScImmutableUint16 { + return ScImmutableUint16{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScImmutableMap) GetUint16Array(key MapKey) ScImmutableUint16Array { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_INT16|TYPE_ARRAY) + return ScImmutableUint16Array{objID: arrID} +} + +func (o ScImmutableMap) GetUint32(key MapKey) ScImmutableUint32 { + return ScImmutableUint32{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScImmutableMap) GetUint32Array(key MapKey) ScImmutableUint32Array { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_INT32|TYPE_ARRAY) + return ScImmutableUint32Array{objID: arrID} +} + +func (o ScImmutableMap) GetUint64(key MapKey) ScImmutableUint64 { + return ScImmutableUint64{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScImmutableMap) GetUint64Array(key MapKey) ScImmutableUint64Array { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_INT64|TYPE_ARRAY) + return ScImmutableUint64Array{objID: arrID} +} + func (o ScImmutableMap) MapID() int32 { return o.objID } @@ -603,3 +736,155 @@ func (o ScImmutableStringArray) GetString(index int32) ScImmutableString { func (o ScImmutableStringArray) Length() int32 { return GetLength(o.objID) } + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScImmutableUint8 struct { + objID int32 + keyID Key32 +} + +func NewScImmutableUint8(objID int32, keyID Key32) ScImmutableUint8 { + return ScImmutableUint8{objID: objID, keyID: keyID} +} + +func (o ScImmutableUint8) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_INT8) +} + +func (o ScImmutableUint8) String() string { + return strconv.FormatUint(uint64(o.Value()), 10) +} + +func (o ScImmutableUint8) Value() uint8 { + bytes := GetBytes(o.objID, o.keyID, TYPE_INT8) + return bytes[0] +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScImmutableUint8Array struct { + objID int32 +} + +func (o ScImmutableUint8Array) GetUint8(index int32) ScImmutableUint8 { + return ScImmutableUint8{objID: o.objID, keyID: Key32(index)} +} + +func (o ScImmutableUint8Array) Length() int32 { + return GetLength(o.objID) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScImmutableUint16 struct { + objID int32 + keyID Key32 +} + +func NewScImmutableUint16(objID int32, keyID Key32) ScImmutableUint16 { + return ScImmutableUint16{objID: objID, keyID: keyID} +} + +func (o ScImmutableUint16) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_INT16) +} + +func (o ScImmutableUint16) String() string { + return strconv.FormatUint(uint64(o.Value()), 10) +} + +func (o ScImmutableUint16) Value() uint16 { + bytes := GetBytes(o.objID, o.keyID, TYPE_INT16) + return binary.LittleEndian.Uint16(bytes) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScImmutableUint16Array struct { + objID int32 +} + +func (o ScImmutableUint16Array) GetUint16(index int32) ScImmutableUint16 { + return ScImmutableUint16{objID: o.objID, keyID: Key32(index)} +} + +func (o ScImmutableUint16Array) Length() int32 { + return GetLength(o.objID) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScImmutableUint32 struct { + objID int32 + keyID Key32 +} + +func NewScImmutableUint32(objID int32, keyID Key32) ScImmutableUint32 { + return ScImmutableUint32{objID: objID, keyID: keyID} +} + +func (o ScImmutableUint32) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_INT32) +} + +func (o ScImmutableUint32) String() string { + return strconv.FormatUint(uint64(o.Value()), 10) +} + +func (o ScImmutableUint32) Value() uint32 { + bytes := GetBytes(o.objID, o.keyID, TYPE_INT32) + return binary.LittleEndian.Uint32(bytes) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScImmutableUint32Array struct { + objID int32 +} + +func (o ScImmutableUint32Array) GetUint32(index int32) ScImmutableUint32 { + return ScImmutableUint32{objID: o.objID, keyID: Key32(index)} +} + +func (o ScImmutableUint32Array) Length() int32 { + return GetLength(o.objID) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScImmutableUint64 struct { + objID int32 + keyID Key32 +} + +func NewScImmutableUint64(objID int32, keyID Key32) ScImmutableUint64 { + return ScImmutableUint64{objID: objID, keyID: keyID} +} + +func (o ScImmutableUint64) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_INT64) +} + +func (o ScImmutableUint64) String() string { + return strconv.FormatUint(o.Value(), 10) +} + +func (o ScImmutableUint64) Value() uint64 { + bytes := GetBytes(o.objID, o.keyID, TYPE_INT64) + return binary.LittleEndian.Uint64(bytes) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScImmutableUint64Array struct { + objID int32 +} + +func (o ScImmutableUint64Array) GetUint64(index int32) ScImmutableUint64 { + return ScImmutableUint64{objID: o.objID, keyID: Key32(index)} +} + +func (o ScImmutableUint64Array) Length() int32 { + return GetLength(o.objID) +} diff --git a/packages/vm/wasmlib/go/wasmlib/inithost.go b/packages/vm/wasmlib/go/wasmlib/inithost.go index 5dd36b5856..8b34c0b1fa 100644 --- a/packages/vm/wasmlib/go/wasmlib/inithost.go +++ b/packages/vm/wasmlib/go/wasmlib/inithost.go @@ -34,6 +34,10 @@ func (h InitHost) CallFunc(objID, keyID int32, params []byte) []byte { return nil } +func (h InitHost) DelKey(objID, keyID, typeID int32) { + Panic("InitHost::DelKey") +} + func (h InitHost) Exists(objID, keyID, typeID int32) bool { if objID == int32(KeyParams) { _, exists := h.params[keyID] diff --git a/packages/vm/wasmlib/go/wasmlib/keys.go b/packages/vm/wasmlib/go/wasmlib/keys.go index 7015419481..62c5ccbba0 100644 --- a/packages/vm/wasmlib/go/wasmlib/keys.go +++ b/packages/vm/wasmlib/go/wasmlib/keys.go @@ -13,6 +13,10 @@ func (key Key) KeyID() Key32 { return GetKeyIDFromString(string(key)) } +func KeyID(key string) Key32 { + return Key(key).KeyID() +} + type Key32 int32 func (key Key32) KeyID() Key32 { diff --git a/packages/vm/wasmlib/go/wasmlib/mutable.go b/packages/vm/wasmlib/go/wasmlib/mutable.go index b7ae157c6b..e9c8f909e2 100644 --- a/packages/vm/wasmlib/go/wasmlib/mutable.go +++ b/packages/vm/wasmlib/go/wasmlib/mutable.go @@ -8,7 +8,7 @@ import ( "strconv" ) -var Root = ScMutableMap{objID: 1} +var Root = ScMutableMap{objID: OBJ_ID_ROOT} // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ @@ -21,6 +21,10 @@ func NewScMutableAddress(objID int32, keyID Key32) ScMutableAddress { return ScMutableAddress{objID: objID, keyID: keyID} } +func (o ScMutableAddress) Delete() { + DelKey(o.objID, o.keyID, TYPE_ADDRESS) +} + func (o ScMutableAddress) Exists() bool { return Exists(o.objID, o.keyID, TYPE_ADDRESS) } @@ -70,6 +74,10 @@ func NewScMutableAgentID(objID int32, keyID Key32) ScMutableAgentID { return ScMutableAgentID{objID: objID, keyID: keyID} } +func (o ScMutableAgentID) Delete() { + DelKey(o.objID, o.keyID, TYPE_AGENT_ID) +} + func (o ScMutableAgentID) Exists() bool { return Exists(o.objID, o.keyID, TYPE_AGENT_ID) } @@ -110,6 +118,67 @@ func (o ScMutableAgentIDArray) Length() int32 { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ +type ScMutableBool struct { + objID int32 + keyID Key32 +} + +func NewScMutableBool(objID int32, keyID Key32) ScMutableBool { + return ScMutableBool{objID: objID, keyID: keyID} +} + +func (o ScMutableBool) Delete() { + DelKey(o.objID, o.keyID, TYPE_BOOL) +} + +func (o ScMutableBool) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_BOOL) +} + +func (o ScMutableBool) SetValue(value bool) { + bytes := make([]byte, 1) + if value { + bytes[0] = 1 + } + SetBytes(o.objID, o.keyID, TYPE_BOOL, bytes) +} + +func (o ScMutableBool) String() string { + if o.Value() { + return "1" + } + return "0" +} + +func (o ScMutableBool) Value() bool { + bytes := GetBytes(o.objID, o.keyID, TYPE_BOOL) + return bytes[0] != 0 +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScMutableBoolArray struct { + objID int32 +} + +func (o ScMutableBoolArray) Clear() { + Clear(o.objID) +} + +func (o ScMutableBoolArray) GetBool(index int32) ScMutableBool { + return ScMutableBool{objID: o.objID, keyID: Key32(index)} +} + +func (o ScMutableBoolArray) Immutable() ScImmutableBoolArray { + return ScImmutableBoolArray(o) +} + +func (o ScMutableBoolArray) Length() int32 { + return GetLength(o.objID) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + type ScMutableBytes struct { objID int32 keyID Key32 @@ -119,6 +188,10 @@ func NewScMutableBytes(objID int32, keyID Key32) ScMutableBytes { return ScMutableBytes{objID: objID, keyID: keyID} } +func (o ScMutableBytes) Delete() { + DelKey(o.objID, o.keyID, TYPE_BYTES) +} + func (o ScMutableBytes) Exists() bool { return Exists(o.objID, o.keyID, TYPE_BYTES) } @@ -168,6 +241,10 @@ func NewScMutableChainID(objID int32, keyID Key32) ScMutableChainID { return ScMutableChainID{objID: objID, keyID: keyID} } +func (o ScMutableChainID) Delete() { + DelKey(o.objID, o.keyID, TYPE_CHAIN_ID) +} + func (o ScMutableChainID) Exists() bool { return Exists(o.objID, o.keyID, TYPE_CHAIN_ID) } @@ -217,6 +294,10 @@ func NewScMutableColor(objID int32, keyID Key32) ScMutableColor { return ScMutableColor{objID: objID, keyID: keyID} } +func (o ScMutableColor) Delete() { + DelKey(o.objID, o.keyID, TYPE_COLOR) +} + func (o ScMutableColor) Exists() bool { return Exists(o.objID, o.keyID, TYPE_COLOR) } @@ -266,6 +347,10 @@ func NewScMutableHash(objID int32, keyID Key32) ScMutableHash { return ScMutableHash{objID: objID, keyID: keyID} } +func (o ScMutableHash) Delete() { + DelKey(o.objID, o.keyID, TYPE_HASH) +} + func (o ScMutableHash) Exists() bool { return Exists(o.objID, o.keyID, TYPE_HASH) } @@ -315,6 +400,10 @@ func NewScMutableHname(objID int32, keyID Key32) ScMutableHname { return ScMutableHname{objID: objID, keyID: keyID} } +func (o ScMutableHname) Delete() { + DelKey(o.objID, o.keyID, TYPE_HNAME) +} + func (o ScMutableHname) Exists() bool { return Exists(o.objID, o.keyID, TYPE_HNAME) } @@ -355,6 +444,62 @@ func (o ScMutableHnameArray) Length() int32 { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ +type ScMutableInt8 struct { + objID int32 + keyID Key32 +} + +func NewScMutableInt8(objID int32, keyID Key32) ScMutableInt8 { + return ScMutableInt8{objID: objID, keyID: keyID} +} + +func (o ScMutableInt8) Delete() { + DelKey(o.objID, o.keyID, TYPE_INT8) +} + +func (o ScMutableInt8) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_INT8) +} + +func (o ScMutableInt8) SetValue(value int8) { + bytes := make([]byte, 1) + bytes[0] = byte(value) + SetBytes(o.objID, o.keyID, TYPE_INT8, bytes) +} + +func (o ScMutableInt8) String() string { + return strconv.FormatInt(int64(o.Value()), 10) +} + +func (o ScMutableInt8) Value() int8 { + bytes := GetBytes(o.objID, o.keyID, TYPE_INT8) + return int8(bytes[0]) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScMutableInt8Array struct { + objID int32 +} + +func (o ScMutableInt8Array) Clear() { + Clear(o.objID) +} + +func (o ScMutableInt8Array) GetInt8(index int32) ScMutableInt8 { + return ScMutableInt8{objID: o.objID, keyID: Key32(index)} +} + +func (o ScMutableInt8Array) Immutable() ScImmutableInt8Array { + return ScImmutableInt8Array(o) +} + +func (o ScMutableInt8Array) Length() int32 { + return GetLength(o.objID) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + type ScMutableInt16 struct { objID int32 keyID Key32 @@ -364,6 +509,10 @@ func NewScMutableInt16(objID int32, keyID Key32) ScMutableInt16 { return ScMutableInt16{objID: objID, keyID: keyID} } +func (o ScMutableInt16) Delete() { + DelKey(o.objID, o.keyID, TYPE_INT16) +} + func (o ScMutableInt16) Exists() bool { return Exists(o.objID, o.keyID, TYPE_INT16) } @@ -416,6 +565,10 @@ func NewScMutableInt32(objID int32, keyID Key32) ScMutableInt32 { return ScMutableInt32{objID: objID, keyID: keyID} } +func (o ScMutableInt32) Delete() { + DelKey(o.objID, o.keyID, TYPE_INT32) +} + func (o ScMutableInt32) Exists() bool { return Exists(o.objID, o.keyID, TYPE_INT32) } @@ -468,6 +621,10 @@ func NewScMutableInt64(objID int32, keyID Key32) ScMutableInt64 { return ScMutableInt64{objID: objID, keyID: keyID} } +func (o ScMutableInt64) Delete() { + DelKey(o.objID, o.keyID, TYPE_INT64) +} + func (o ScMutableInt64) Exists() bool { return Exists(o.objID, o.keyID, TYPE_INT64) } @@ -546,6 +703,15 @@ func (o ScMutableMap) GetAgentIDArray(key MapKey) ScMutableAgentIDArray { return ScMutableAgentIDArray{objID: arrID} } +func (o ScMutableMap) GetBool(key MapKey) ScMutableBool { + return ScMutableBool{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScMutableMap) GetBoolArray(key MapKey) ScMutableBoolArray { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_BOOL|TYPE_ARRAY) + return ScMutableBoolArray{objID: arrID} +} + func (o ScMutableMap) GetBytes(key MapKey) ScMutableBytes { return ScMutableBytes{objID: o.objID, keyID: key.KeyID()} } @@ -591,6 +757,15 @@ func (o ScMutableMap) GetHnameArray(key MapKey) ScMutableHnameArray { return ScMutableHnameArray{objID: arrID} } +func (o ScMutableMap) GetInt8(key MapKey) ScMutableInt8 { + return ScMutableInt8{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScMutableMap) GetInt8Array(key MapKey) ScMutableInt8Array { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_INT8|TYPE_ARRAY) + return ScMutableInt8Array{objID: arrID} +} + func (o ScMutableMap) GetInt16(key MapKey) ScMutableInt16 { return ScMutableInt16{objID: o.objID, keyID: key.KeyID()} } @@ -646,6 +821,42 @@ func (o ScMutableMap) GetStringArray(key MapKey) ScMutableStringArray { return ScMutableStringArray{objID: arrID} } +func (o ScMutableMap) GetUint8(key MapKey) ScMutableUint8 { + return ScMutableUint8{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScMutableMap) GetUint8Array(key MapKey) ScMutableUint8Array { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_INT8|TYPE_ARRAY) + return ScMutableUint8Array{objID: arrID} +} + +func (o ScMutableMap) GetUint16(key MapKey) ScMutableUint16 { + return ScMutableUint16{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScMutableMap) GetUint16Array(key MapKey) ScMutableUint16Array { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_INT16|TYPE_ARRAY) + return ScMutableUint16Array{objID: arrID} +} + +func (o ScMutableMap) GetUint32(key MapKey) ScMutableUint32 { + return ScMutableUint32{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScMutableMap) GetUint32Array(key MapKey) ScMutableUint32Array { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_INT32|TYPE_ARRAY) + return ScMutableUint32Array{objID: arrID} +} + +func (o ScMutableMap) GetUint64(key MapKey) ScMutableUint64 { + return ScMutableUint64{objID: o.objID, keyID: key.KeyID()} +} + +func (o ScMutableMap) GetUint64Array(key MapKey) ScMutableUint64Array { + arrID := GetObjectID(o.objID, key.KeyID(), TYPE_INT64|TYPE_ARRAY) + return ScMutableUint64Array{objID: arrID} +} + func (o ScMutableMap) Immutable() ScImmutableMap { return ScImmutableMap(o) } @@ -688,6 +899,10 @@ func NewScMutableRequestID(objID int32, keyID Key32) ScMutableRequestID { return ScMutableRequestID{objID: objID, keyID: keyID} } +func (o ScMutableRequestID) Delete() { + DelKey(o.objID, o.keyID, TYPE_REQUEST_ID) +} + func (o ScMutableRequestID) Exists() bool { return Exists(o.objID, o.keyID, TYPE_REQUEST_ID) } @@ -737,6 +952,10 @@ func NewScMutableString(objID int32, keyID Key32) ScMutableString { return ScMutableString{objID: objID, keyID: keyID} } +func (o ScMutableString) Delete() { + DelKey(o.objID, o.keyID, TYPE_STRING) +} + func (o ScMutableString) Exists() bool { return Exists(o.objID, o.keyID, TYPE_STRING) } @@ -778,3 +997,227 @@ func (o ScMutableStringArray) Immutable() ScImmutableStringArray { func (o ScMutableStringArray) Length() int32 { return GetLength(o.objID) } + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScMutableUint8 struct { + objID int32 + keyID Key32 +} + +func NewScMutableUint8(objID int32, keyID Key32) ScMutableUint8 { + return ScMutableUint8{objID: objID, keyID: keyID} +} + +func (o ScMutableUint8) Delete() { + DelKey(o.objID, o.keyID, TYPE_INT8) +} + +func (o ScMutableUint8) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_INT8) +} + +func (o ScMutableUint8) SetValue(value uint8) { + bytes := make([]byte, 1) + bytes[0] = value + SetBytes(o.objID, o.keyID, TYPE_INT8, bytes) +} + +func (o ScMutableUint8) String() string { + return strconv.FormatUint(uint64(o.Value()), 10) +} + +func (o ScMutableUint8) Value() uint8 { + bytes := GetBytes(o.objID, o.keyID, TYPE_INT8) + return bytes[0] +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScMutableUint8Array struct { + objID int32 +} + +func (o ScMutableUint8Array) Clear() { + Clear(o.objID) +} + +func (o ScMutableUint8Array) GetUint8(index int32) ScMutableUint8 { + return ScMutableUint8{objID: o.objID, keyID: Key32(index)} +} + +func (o ScMutableUint8Array) Immutable() ScImmutableUint8Array { + return ScImmutableUint8Array(o) +} + +func (o ScMutableUint8Array) Length() int32 { + return GetLength(o.objID) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScMutableUint16 struct { + objID int32 + keyID Key32 +} + +func NewScMutableUint16(objID int32, keyID Key32) ScMutableUint16 { + return ScMutableUint16{objID: objID, keyID: keyID} +} + +func (o ScMutableUint16) Delete() { + DelKey(o.objID, o.keyID, TYPE_INT16) +} + +func (o ScMutableUint16) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_INT16) +} + +func (o ScMutableUint16) SetValue(value uint16) { + bytes := make([]byte, 2) + binary.LittleEndian.PutUint16(bytes, value) + SetBytes(o.objID, o.keyID, TYPE_INT16, bytes) +} + +func (o ScMutableUint16) String() string { + return strconv.FormatUint(uint64(o.Value()), 10) +} + +func (o ScMutableUint16) Value() uint16 { + bytes := GetBytes(o.objID, o.keyID, TYPE_INT16) + return binary.LittleEndian.Uint16(bytes) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScMutableUint16Array struct { + objID int32 +} + +func (o ScMutableUint16Array) Clear() { + Clear(o.objID) +} + +func (o ScMutableUint16Array) GetUint16(index int32) ScMutableUint16 { + return ScMutableUint16{objID: o.objID, keyID: Key32(index)} +} + +func (o ScMutableUint16Array) Immutable() ScImmutableUint16Array { + return ScImmutableUint16Array(o) +} + +func (o ScMutableUint16Array) Length() int32 { + return GetLength(o.objID) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScMutableUint32 struct { + objID int32 + keyID Key32 +} + +func NewScMutableUint32(objID int32, keyID Key32) ScMutableUint32 { + return ScMutableUint32{objID: objID, keyID: keyID} +} + +func (o ScMutableUint32) Delete() { + DelKey(o.objID, o.keyID, TYPE_INT32) +} + +func (o ScMutableUint32) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_INT32) +} + +func (o ScMutableUint32) SetValue(value uint32) { + bytes := make([]byte, 4) + binary.LittleEndian.PutUint32(bytes, value) + SetBytes(o.objID, o.keyID, TYPE_INT32, bytes) +} + +func (o ScMutableUint32) String() string { + return strconv.FormatUint(uint64(o.Value()), 10) +} + +func (o ScMutableUint32) Value() uint32 { + bytes := GetBytes(o.objID, o.keyID, TYPE_INT32) + return binary.LittleEndian.Uint32(bytes) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScMutableUint32Array struct { + objID int32 +} + +func (o ScMutableUint32Array) Clear() { + Clear(o.objID) +} + +func (o ScMutableUint32Array) GetUint32(index int32) ScMutableUint32 { + return ScMutableUint32{objID: o.objID, keyID: Key32(index)} +} + +func (o ScMutableUint32Array) Immutable() ScImmutableUint32Array { + return ScImmutableUint32Array(o) +} + +func (o ScMutableUint32Array) Length() int32 { + return GetLength(o.objID) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScMutableUint64 struct { + objID int32 + keyID Key32 +} + +func NewScMutableUint64(objID int32, keyID Key32) ScMutableUint64 { + return ScMutableUint64{objID: objID, keyID: keyID} +} + +func (o ScMutableUint64) Delete() { + DelKey(o.objID, o.keyID, TYPE_INT64) +} + +func (o ScMutableUint64) Exists() bool { + return Exists(o.objID, o.keyID, TYPE_INT64) +} + +func (o ScMutableUint64) SetValue(value uint64) { + bytes := make([]byte, 8) + binary.LittleEndian.PutUint64(bytes, value) + SetBytes(o.objID, o.keyID, TYPE_INT64, bytes) +} + +func (o ScMutableUint64) String() string { + return strconv.FormatUint(o.Value(), 10) +} + +func (o ScMutableUint64) Value() uint64 { + bytes := GetBytes(o.objID, o.keyID, TYPE_INT64) + return binary.LittleEndian.Uint64(bytes) +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +type ScMutableUint64Array struct { + objID int32 +} + +func (o ScMutableUint64Array) Clear() { + Clear(o.objID) +} + +func (o ScMutableUint64Array) GetUint64(index int32) ScMutableUint64 { + return ScMutableUint64{objID: o.objID, keyID: Key32(index)} +} + +func (o ScMutableUint64Array) Immutable() ScImmutableUint64Array { + return ScImmutableUint64Array(o) +} + +func (o ScMutableUint64Array) Length() int32 { + return GetLength(o.objID) +} diff --git a/packages/vm/wasmlib/src/bytes.rs b/packages/vm/wasmlib/src/bytes.rs index 9e7a969d66..e93f11ee54 100644 --- a/packages/vm/wasmlib/src/bytes.rs +++ b/packages/vm/wasmlib/src/bytes.rs @@ -12,6 +12,9 @@ pub struct BytesDecoder<'a> { impl BytesDecoder<'_> { // constructs a decoder pub fn new(data: &[u8]) -> BytesDecoder { + if data.len() == 0 { + panic("cannot decode empty byte array, use exist()"); + } BytesDecoder { buf: data } } @@ -25,9 +28,14 @@ impl BytesDecoder<'_> { ScAgentID::from_bytes(self.bytes()) } + // decodes a bool from the byte buffer + pub fn bool(&mut self) -> bool { + self.uint8() != 0 + } + // decodes the next substring of bytes from the byte buffer pub fn bytes(&mut self) -> &[u8] { - let size = self.int32() as usize; + let size = self.uint32() as usize; if self.buf.len() < size { panic("insufficient bytes"); } @@ -56,6 +64,11 @@ impl BytesDecoder<'_> { ScHname::from_bytes(self.bytes()) } + // decodes an int8 from the byte buffer + pub fn int8(&mut self) -> i8 { + self.uint8() as i8 + } + // decodes an int16 from the byte buffer // note that these are encoded using leb128 encoding to conserve space pub fn int16(&mut self) -> i16 { @@ -114,6 +127,34 @@ impl BytesDecoder<'_> { pub fn string(&mut self) -> String { String::from_utf8_lossy(self.bytes()).to_string() } + + // decodes an uint8 from the byte buffer + pub fn uint8(&mut self) -> u8 { + if self.buf.len() == 0 { + panic("insufficient bytes"); + } + let val = self.buf[0]; + self.buf = &self.buf[1..]; + val + } + + // decodes an uint16 from the byte buffer + // note that these are encoded using leb128 encoding to conserve space + pub fn uint16(&mut self) -> u16 { + self.int16() as u16 + } + + // decodes an uint32 from the byte buffer + // note that these are encoded using leb128 encoding to conserve space + pub fn uint32(&mut self) -> u32 { + self.int32() as u32 + } + + // decodes an uint64 from the byte buffer + // note that these are encoded using leb128 encoding to conserve space + pub fn uint64(&mut self) -> u64 { + self.int64() as u64 + } } impl Drop for BytesDecoder<'_> { @@ -139,33 +180,34 @@ impl BytesEncoder { // encodes an ScAddress into the byte buffer pub fn address(&mut self, value: &ScAddress) -> &BytesEncoder { - self.bytes(value.to_bytes()); - self + self.bytes(value.to_bytes()) } // encodes an ScAgentID into the byte buffer pub fn agent_id(&mut self, value: &ScAgentID) -> &BytesEncoder { - self.bytes(value.to_bytes()); - self + self.bytes(value.to_bytes()) + } + + // encodes a bool into the byte buffer + pub fn bool(&mut self, val: bool) -> &BytesEncoder { + self.uint8(val as u8) } // encodes a substring of bytes into the byte buffer pub fn bytes(&mut self, value: &[u8]) -> &BytesEncoder { - self.int32(value.len() as i32); + self.uint32(value.len() as u32); self.buf.extend_from_slice(value); self } // encodes an ScChainID into the byte buffer pub fn chain_id(&mut self, value: &ScChainID) -> &BytesEncoder { - self.bytes(value.to_bytes()); - self + self.bytes(value.to_bytes()) } // encodes an ScColor into the byte buffer pub fn color(&mut self, value: &ScColor) -> &BytesEncoder { - self.bytes(value.to_bytes()); - self + self.bytes(value.to_bytes()) } // retrieve the encoded byte buffer @@ -175,14 +217,17 @@ impl BytesEncoder { // encodes an ScHash into the byte buffer pub fn hash(&mut self, value: &ScHash) -> &BytesEncoder { - self.bytes(value.to_bytes()); - self + self.bytes(value.to_bytes()) } // encodes an ScHname into the byte buffer - pub fn hname(&mut self, value: &ScHname) -> &BytesEncoder { - self.bytes(&value.to_bytes()); - self + pub fn hname(&mut self, value: ScHname) -> &BytesEncoder { + self.bytes(&value.to_bytes()) + } + + // encodes an int8 into the byte buffer + pub fn int8(&mut self, val: i8) -> &BytesEncoder { + self.uint8(val as u8) } // encodes an int16 into the byte buffer @@ -219,13 +264,35 @@ impl BytesEncoder { // encodes an ScRequestID into the byte buffer pub fn request_id(&mut self, value: &ScRequestID) -> &BytesEncoder { - self.bytes(value.to_bytes()); - self + self.bytes(value.to_bytes()) } // encodes an UTF-8 text string into the byte buffer pub fn string(&mut self, value: &str) -> &BytesEncoder { - self.bytes(value.as_bytes()); + self.bytes(value.as_bytes()) + } + + // encodes an uint8 into the byte buffer + pub fn uint8(&mut self, val: u8) -> &BytesEncoder { + self.buf.push(val); self } + + // encodes an uint16 into the byte buffer + // note that these are encoded using leb128 encoding to conserve space + pub fn uint16(&mut self, val: u16) -> &BytesEncoder { + self.int16(val as i16) + } + + // encodes an uint32 into the byte buffer + // note that these are encoded using leb128 encoding to conserve space + pub fn uint32(&mut self, val: u32) -> &BytesEncoder { + self.int32(val as i32) + } + + // encodes an uint64 into the byte buffer + // note that these are encoded using leb128 encoding to conserve space + pub fn uint64(&mut self, val: u64) -> &BytesEncoder { + self.int64(val as i64) + } } diff --git a/packages/vm/wasmlib/src/context.rs b/packages/vm/wasmlib/src/context.rs index 7a024fc9de..9077472418 100644 --- a/packages/vm/wasmlib/src/context.rs +++ b/packages/vm/wasmlib/src/context.rs @@ -14,7 +14,7 @@ use crate::keys::*; use crate::mutable::*; // all access to the objects in host's object tree starts here -pub(crate) static ROOT: ScMutableMap = ScMutableMap { obj_id: 1 }; +pub(crate) static ROOT: ScMutableMap = ScMutableMap { obj_id: OBJ_ID_ROOT }; // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ @@ -163,13 +163,6 @@ impl ScUtility { let result = self.utility.call_func(KEY_HNAME, value.as_bytes()); ScHname::from_bytes(&result) } - - // generates a random value from 0 to max (exclusive max) using a deterministic RNG - pub fn random(&self, max: i64) -> i64 { - let result = self.utility.call_func(KEY_RANDOM, &vec![0_u8; 0]); - let rnd = i64::from_le_bytes(result.try_into().expect("invalid i64 length")); - (rnd as u64 % max as u64) as i64 - } } // wrapper function for simplified internal access to base58 encoding @@ -281,8 +274,8 @@ impl ScFuncContext { // passing the provided parameters and token transfers to it pub fn call(&self, hcontract: ScHname, hfunction: ScHname, params: Option, transfer: Option) -> ScImmutableMap { let mut encode = BytesEncoder::new(); - encode.hname(&hcontract); - encode.hname(&hfunction); + encode.hname(hcontract); + encode.hname(hfunction); if let Some(params) = params { encode.int32(params.map_id()); } else { @@ -297,11 +290,6 @@ impl ScFuncContext { ROOT.get_map(&KEY_RETURN).immutable() } - // shorthand to synchronously call a smart contract function of the current contract - pub fn call_self(&self, hfunction: ScHname, params: Option, transfers: Option) -> ScImmutableMap { - self.call(self.contract(), hfunction, params, transfers) - } - // retrieve the agent id of the caller of the smart contract pub fn caller(&self) -> ScAgentID { ROOT.get_agent_id(&KEY_CALLER).value() @@ -343,9 +331,9 @@ impl ScFuncContext { pub fn post(&self, chain_id: &ScChainID, hcontract: ScHname, hfunction: ScHname, params: Option, transfer: ScTransfers, delay: i32) { let mut encode = BytesEncoder::new(); encode.chain_id(chain_id); - encode.hname(&hcontract); - encode.hname(&hfunction); - if let Some(params) = ¶ms { + encode.hname(hcontract); + encode.hname(hfunction); + if let Some(params) = params { encode.int32(params.map_id()); } else { encode.int32(0); @@ -355,9 +343,18 @@ impl ScFuncContext { ROOT.get_bytes(&KEY_POST).set_value(&encode.data()); } - // shorthand to asynchronously call a smart contract function of the current contract - pub fn post_self(&self, hfunction: ScHname, params: Option, transfer: ScTransfers, delay: i32) { - self.post(&self.chain_id(), self.contract(), hfunction, params, transfer, delay); + // generates a random value from 0 to max (exclusive max) using a deterministic RNG + pub fn random(&self, max: i64) -> i64 { + let state = ScMutableMap { obj_id: OBJ_ID_STATE }; + let rnd = state.get_bytes(&KEY_RANDOM); + let mut seed = rnd.value(); + if seed.is_empty() { + // get initial entropy from sandbox + seed = ROOT.get_bytes(&KEY_RANDOM).value(); + } + rnd.set_value(&self.utility().hash_sha3(&seed).to_bytes()); + let rnd = i64::from_le_bytes(seed[0..8].try_into().expect("invalid i64 length")); + (rnd as u64 % max as u64) as i64 } // retrieve the request id of this transaction @@ -399,8 +396,8 @@ impl ScViewContext { // passing the provided parameters to it pub fn call(&self, hcontract: ScHname, hfunction: ScHname, params: Option) -> ScImmutableMap { let mut encode = BytesEncoder::new(); - encode.hname(&hcontract); - encode.hname(&hfunction); + encode.hname(hcontract); + encode.hname(hfunction); if let Some(params) = params { encode.int32(params.map_id()); } else { @@ -411,11 +408,6 @@ impl ScViewContext { ROOT.get_map(&KEY_RETURN).immutable() } - // shorthand to synchronously call a smart contract view of the current contract - pub fn call_self(&self, hfunction: ScHname, params: Option) -> ScImmutableMap { - self.call(self.contract(), hfunction, params) - } - // access immutable state storage on the host pub fn state(&self) -> ScImmutableMap { ROOT.get_map(&KEY_STATE).immutable() diff --git a/packages/vm/wasmlib/src/contract.rs b/packages/vm/wasmlib/src/contract.rs index 9f99d8bbab..66b349ffa4 100644 --- a/packages/vm/wasmlib/src/contract.rs +++ b/packages/vm/wasmlib/src/contract.rs @@ -57,8 +57,8 @@ impl ScView { fn call_with_transfer(&self, transfer_id: i32) { let mut encode = BytesEncoder::new(); - encode.hname(&self.h_contract); - encode.hname(&self.h_function); + encode.hname(self.h_contract); + encode.hname(self.h_function); encode.int32(self.id(self.params_id)); encode.int32(transfer_id); ROOT.get_bytes(&KEY_CALL).set_value(&encode.data()); @@ -163,8 +163,8 @@ impl ScFunc { pub fn post_to_chain(&self, chain_id: ScChainID) { let mut encode = BytesEncoder::new(); encode.chain_id(&chain_id); - encode.hname(&self.view.h_contract); - encode.hname(&self.view.h_function); + encode.hname(self.view.h_contract); + encode.hname(self.view.h_function); encode.int32(self.view.id(self.view.params_id)); encode.int32(self.transfer_id); encode.int32(self.delay); diff --git a/packages/vm/wasmlib/src/coreaccounts/consts.rs b/packages/vm/wasmlib/src/coreaccounts/consts.rs index 94eb13b03c..08e1dd53ce 100644 --- a/packages/vm/wasmlib/src/coreaccounts/consts.rs +++ b/packages/vm/wasmlib/src/coreaccounts/consts.rs @@ -5,36 +5,34 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use crate::*; -pub const SC_NAME: &str = "accounts"; -pub const SC_DESCRIPTION: &str = "Core chain account ledger contract"; -pub const HSC_NAME: ScHname = ScHname(0x3c4b5e02); - -pub(crate) const PARAM_AGENT_ID: &str = "a"; -pub(crate) const PARAM_WITHDRAW_AMOUNT: &str = "m"; -pub(crate) const PARAM_WITHDRAW_COLOR: &str = "c"; - -pub(crate) const RESULT_ACCOUNT_NONCE: &str = "n"; - -pub(crate) const FUNC_DEPOSIT: &str = "deposit"; -pub(crate) const FUNC_HARVEST: &str = "harvest"; -pub(crate) const FUNC_WITHDRAW: &str = "withdraw"; -pub(crate) const VIEW_ACCOUNTS: &str = "accounts"; -pub(crate) const VIEW_BALANCE: &str = "balance"; -pub(crate) const VIEW_GET_ACCOUNT_NONCE: &str = "getAccountNonce"; -pub(crate) const VIEW_TOTAL_ASSETS: &str = "totalAssets"; - -pub(crate) const HFUNC_DEPOSIT: ScHname = ScHname(0xbdc9102d); -pub(crate) const HFUNC_HARVEST: ScHname = ScHname(0x7b40efbd); -pub(crate) const HFUNC_WITHDRAW: ScHname = ScHname(0x9dcc0f41); -pub(crate) const HVIEW_ACCOUNTS: ScHname = ScHname(0x3c4b5e02); -pub(crate) const HVIEW_BALANCE: ScHname = ScHname(0x84168cb4); -pub(crate) const HVIEW_GET_ACCOUNT_NONCE: ScHname = ScHname(0x529d7df9); -pub(crate) const HVIEW_TOTAL_ASSETS: ScHname = ScHname(0xfab0f8d2); - -// @formatter:on +pub const SC_NAME : &str = "accounts"; +pub const SC_DESCRIPTION : &str = "Core chain account ledger contract"; +pub const HSC_NAME : ScHname = ScHname(0x3c4b5e02); + +pub(crate) const PARAM_AGENT_ID : &str = "a"; +pub(crate) const PARAM_WITHDRAW_AMOUNT : &str = "m"; +pub(crate) const PARAM_WITHDRAW_COLOR : &str = "c"; + +pub(crate) const RESULT_ACCOUNT_NONCE : &str = "n"; +pub(crate) const RESULT_AGENTS : &str = "this"; +pub(crate) const RESULT_BALANCES : &str = "this"; + +pub(crate) const FUNC_DEPOSIT : &str = "deposit"; +pub(crate) const FUNC_HARVEST : &str = "harvest"; +pub(crate) const FUNC_WITHDRAW : &str = "withdraw"; +pub(crate) const VIEW_ACCOUNTS : &str = "accounts"; +pub(crate) const VIEW_BALANCE : &str = "balance"; +pub(crate) const VIEW_GET_ACCOUNT_NONCE : &str = "getAccountNonce"; +pub(crate) const VIEW_TOTAL_ASSETS : &str = "totalAssets"; + +pub(crate) const HFUNC_DEPOSIT : ScHname = ScHname(0xbdc9102d); +pub(crate) const HFUNC_HARVEST : ScHname = ScHname(0x7b40efbd); +pub(crate) const HFUNC_WITHDRAW : ScHname = ScHname(0x9dcc0f41); +pub(crate) const HVIEW_ACCOUNTS : ScHname = ScHname(0x3c4b5e02); +pub(crate) const HVIEW_BALANCE : ScHname = ScHname(0x84168cb4); +pub(crate) const HVIEW_GET_ACCOUNT_NONCE : ScHname = ScHname(0x529d7df9); +pub(crate) const HVIEW_TOTAL_ASSETS : ScHname = ScHname(0xfab0f8d2); diff --git a/packages/vm/wasmlib/src/coreaccounts/contract.rs b/packages/vm/wasmlib/src/coreaccounts/contract.rs index b52b701ecb..8b6e25016e 100644 --- a/packages/vm/wasmlib/src/coreaccounts/contract.rs +++ b/packages/vm/wasmlib/src/coreaccounts/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -15,39 +13,39 @@ use crate::*; use crate::coreaccounts::*; pub struct DepositCall { - pub func: ScFunc, - pub params: MutableDepositParams, + pub func: ScFunc, + pub params: MutableDepositParams, } pub struct HarvestCall { - pub func: ScFunc, - pub params: MutableHarvestParams, + pub func: ScFunc, + pub params: MutableHarvestParams, } pub struct WithdrawCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct AccountsCall { - pub func: ScView, - pub results: ImmutableAccountsResults, + pub func: ScView, + pub results: ImmutableAccountsResults, } pub struct BalanceCall { - pub func: ScView, - pub params: MutableBalanceParams, - pub results: ImmutableBalanceResults, + pub func: ScView, + pub params: MutableBalanceParams, + pub results: ImmutableBalanceResults, } pub struct GetAccountNonceCall { - pub func: ScView, - pub params: MutableGetAccountNonceParams, - pub results: ImmutableGetAccountNonceResults, + pub func: ScView, + pub params: MutableGetAccountNonceParams, + pub results: ImmutableGetAccountNonceResults, } pub struct TotalAssetsCall { - pub func: ScView, - pub results: ImmutableTotalAssetsResults, + pub func: ScView, + pub results: ImmutableTotalAssetsResults, } pub struct ScFuncs { @@ -56,59 +54,63 @@ pub struct ScFuncs { impl ScFuncs { pub fn deposit(_ctx: & dyn ScFuncCallContext) -> DepositCall { let mut f = DepositCall { - func: ScFunc::new(HSC_NAME, HFUNC_DEPOSIT), + func: ScFunc::new(HSC_NAME, HFUNC_DEPOSIT), params: MutableDepositParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn harvest(_ctx: & dyn ScFuncCallContext) -> HarvestCall { let mut f = HarvestCall { - func: ScFunc::new(HSC_NAME, HFUNC_HARVEST), + func: ScFunc::new(HSC_NAME, HFUNC_HARVEST), params: MutableHarvestParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn withdraw(_ctx: & dyn ScFuncCallContext) -> WithdrawCall { WithdrawCall { func: ScFunc::new(HSC_NAME, HFUNC_WITHDRAW), } } + pub fn accounts(_ctx: & dyn ScViewCallContext) -> AccountsCall { let mut f = AccountsCall { - func: ScView::new(HSC_NAME, HVIEW_ACCOUNTS), + func: ScView::new(HSC_NAME, HVIEW_ACCOUNTS), results: ImmutableAccountsResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn balance(_ctx: & dyn ScViewCallContext) -> BalanceCall { let mut f = BalanceCall { - func: ScView::new(HSC_NAME, HVIEW_BALANCE), - params: MutableBalanceParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_BALANCE), + params: MutableBalanceParams { id: 0 }, results: ImmutableBalanceResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_account_nonce(_ctx: & dyn ScViewCallContext) -> GetAccountNonceCall { let mut f = GetAccountNonceCall { - func: ScView::new(HSC_NAME, HVIEW_GET_ACCOUNT_NONCE), - params: MutableGetAccountNonceParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_ACCOUNT_NONCE), + params: MutableGetAccountNonceParams { id: 0 }, results: ImmutableGetAccountNonceResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn total_assets(_ctx: & dyn ScViewCallContext) -> TotalAssetsCall { let mut f = TotalAssetsCall { - func: ScView::new(HSC_NAME, HVIEW_TOTAL_ASSETS), + func: ScView::new(HSC_NAME, HVIEW_TOTAL_ASSETS), results: ImmutableTotalAssetsResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/packages/vm/wasmlib/src/coreaccounts/params.rs b/packages/vm/wasmlib/src/coreaccounts/params.rs index dca6f1eca3..5c61b19e05 100644 --- a/packages/vm/wasmlib/src/coreaccounts/params.rs +++ b/packages/vm/wasmlib/src/coreaccounts/params.rs @@ -19,8 +19,8 @@ pub struct ImmutableDepositParams { impl ImmutableDepositParams { pub fn agent_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) - } + ScImmutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) + } } #[derive(Clone, Copy)] @@ -30,8 +30,8 @@ pub struct MutableDepositParams { impl MutableDepositParams { pub fn agent_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) - } + ScMutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) + } } #[derive(Clone, Copy)] @@ -41,12 +41,12 @@ pub struct ImmutableHarvestParams { impl ImmutableHarvestParams { pub fn withdraw_amount(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, PARAM_WITHDRAW_AMOUNT.get_key_id()) - } + ScImmutableInt64::new(self.id, PARAM_WITHDRAW_AMOUNT.get_key_id()) + } pub fn withdraw_color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, PARAM_WITHDRAW_COLOR.get_key_id()) - } + ScImmutableColor::new(self.id, PARAM_WITHDRAW_COLOR.get_key_id()) + } } #[derive(Clone, Copy)] @@ -56,12 +56,12 @@ pub struct MutableHarvestParams { impl MutableHarvestParams { pub fn withdraw_amount(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, PARAM_WITHDRAW_AMOUNT.get_key_id()) - } + ScMutableInt64::new(self.id, PARAM_WITHDRAW_AMOUNT.get_key_id()) + } pub fn withdraw_color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, PARAM_WITHDRAW_COLOR.get_key_id()) - } + ScMutableColor::new(self.id, PARAM_WITHDRAW_COLOR.get_key_id()) + } } #[derive(Clone, Copy)] @@ -71,8 +71,8 @@ pub struct ImmutableBalanceParams { impl ImmutableBalanceParams { pub fn agent_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) - } + ScImmutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) + } } #[derive(Clone, Copy)] @@ -82,8 +82,8 @@ pub struct MutableBalanceParams { impl MutableBalanceParams { pub fn agent_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) - } + ScMutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) + } } #[derive(Clone, Copy)] @@ -93,8 +93,8 @@ pub struct ImmutableGetAccountNonceParams { impl ImmutableGetAccountNonceParams { pub fn agent_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) - } + ScImmutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) + } } #[derive(Clone, Copy)] @@ -104,6 +104,6 @@ pub struct MutableGetAccountNonceParams { impl MutableGetAccountNonceParams { pub fn agent_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) - } + ScMutableAgentID::new(self.id, PARAM_AGENT_ID.get_key_id()) + } } diff --git a/packages/vm/wasmlib/src/coreaccounts/results.rs b/packages/vm/wasmlib/src/coreaccounts/results.rs index 21a3fae179..918522561e 100644 --- a/packages/vm/wasmlib/src/coreaccounts/results.rs +++ b/packages/vm/wasmlib/src/coreaccounts/results.rs @@ -13,7 +13,7 @@ use crate::coreaccounts::*; use crate::host::*; pub struct MapAgentIDToImmutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapAgentIDToImmutableBytes { @@ -29,17 +29,17 @@ pub struct ImmutableAccountsResults { impl ImmutableAccountsResults { pub fn agents(&self) -> MapAgentIDToImmutableBytes { - MapAgentIDToImmutableBytes { obj_id: self.id } - } + MapAgentIDToImmutableBytes { obj_id: self.id } + } } pub struct MapAgentIDToMutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapAgentIDToMutableBytes { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_bytes(&self, key: &ScAgentID) -> ScMutableBytes { @@ -54,12 +54,12 @@ pub struct MutableAccountsResults { impl MutableAccountsResults { pub fn agents(&self) -> MapAgentIDToMutableBytes { - MapAgentIDToMutableBytes { obj_id: self.id } - } + MapAgentIDToMutableBytes { obj_id: self.id } + } } pub struct MapColorToImmutableInt64 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapColorToImmutableInt64 { @@ -75,17 +75,17 @@ pub struct ImmutableBalanceResults { impl ImmutableBalanceResults { pub fn balances(&self) -> MapColorToImmutableInt64 { - MapColorToImmutableInt64 { obj_id: self.id } - } + MapColorToImmutableInt64 { obj_id: self.id } + } } pub struct MapColorToMutableInt64 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapColorToMutableInt64 { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_int64(&self, key: &ScColor) -> ScMutableInt64 { @@ -100,8 +100,8 @@ pub struct MutableBalanceResults { impl MutableBalanceResults { pub fn balances(&self) -> MapColorToMutableInt64 { - MapColorToMutableInt64 { obj_id: self.id } - } + MapColorToMutableInt64 { obj_id: self.id } + } } #[derive(Clone, Copy)] @@ -111,8 +111,8 @@ pub struct ImmutableGetAccountNonceResults { impl ImmutableGetAccountNonceResults { pub fn account_nonce(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, RESULT_ACCOUNT_NONCE.get_key_id()) - } + ScImmutableInt64::new(self.id, RESULT_ACCOUNT_NONCE.get_key_id()) + } } #[derive(Clone, Copy)] @@ -122,8 +122,8 @@ pub struct MutableGetAccountNonceResults { impl MutableGetAccountNonceResults { pub fn account_nonce(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, RESULT_ACCOUNT_NONCE.get_key_id()) - } + ScMutableInt64::new(self.id, RESULT_ACCOUNT_NONCE.get_key_id()) + } } #[derive(Clone, Copy)] @@ -133,8 +133,8 @@ pub struct ImmutableTotalAssetsResults { impl ImmutableTotalAssetsResults { pub fn balances(&self) -> MapColorToImmutableInt64 { - MapColorToImmutableInt64 { obj_id: self.id } - } + MapColorToImmutableInt64 { obj_id: self.id } + } } #[derive(Clone, Copy)] @@ -144,6 +144,6 @@ pub struct MutableTotalAssetsResults { impl MutableTotalAssetsResults { pub fn balances(&self) -> MapColorToMutableInt64 { - MapColorToMutableInt64 { obj_id: self.id } - } + MapColorToMutableInt64 { obj_id: self.id } + } } diff --git a/packages/vm/wasmlib/src/coreblob/consts.rs b/packages/vm/wasmlib/src/coreblob/consts.rs index d586e7153e..83221ab5df 100644 --- a/packages/vm/wasmlib/src/coreblob/consts.rs +++ b/packages/vm/wasmlib/src/coreblob/consts.rs @@ -5,30 +5,28 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use crate::*; -pub const SC_NAME: &str = "blob"; -pub const SC_DESCRIPTION: &str = "Core blob contract"; -pub const HSC_NAME: ScHname = ScHname(0xfd91bc63); - -pub(crate) const PARAM_FIELD: &str = "field"; -pub(crate) const PARAM_HASH: &str = "hash"; +pub const SC_NAME : &str = "blob"; +pub const SC_DESCRIPTION : &str = "Core blob contract"; +pub const HSC_NAME : ScHname = ScHname(0xfd91bc63); -pub(crate) const RESULT_BYTES: &str = "bytes"; -pub(crate) const RESULT_HASH: &str = "hash"; +pub(crate) const PARAM_BLOBS : &str = "this"; +pub(crate) const PARAM_FIELD : &str = "field"; +pub(crate) const PARAM_HASH : &str = "hash"; -pub(crate) const FUNC_STORE_BLOB: &str = "storeBlob"; -pub(crate) const VIEW_GET_BLOB_FIELD: &str = "getBlobField"; -pub(crate) const VIEW_GET_BLOB_INFO: &str = "getBlobInfo"; -pub(crate) const VIEW_LIST_BLOBS: &str = "listBlobs"; +pub(crate) const RESULT_BLOB_SIZES : &str = "this"; +pub(crate) const RESULT_BYTES : &str = "bytes"; +pub(crate) const RESULT_HASH : &str = "hash"; -pub(crate) const HFUNC_STORE_BLOB: ScHname = ScHname(0xddd4c281); -pub(crate) const HVIEW_GET_BLOB_FIELD: ScHname = ScHname(0x1f448130); -pub(crate) const HVIEW_GET_BLOB_INFO: ScHname = ScHname(0xfde4ab46); -pub(crate) const HVIEW_LIST_BLOBS: ScHname = ScHname(0x62ca7990); +pub(crate) const FUNC_STORE_BLOB : &str = "storeBlob"; +pub(crate) const VIEW_GET_BLOB_FIELD : &str = "getBlobField"; +pub(crate) const VIEW_GET_BLOB_INFO : &str = "getBlobInfo"; +pub(crate) const VIEW_LIST_BLOBS : &str = "listBlobs"; -// @formatter:on +pub(crate) const HFUNC_STORE_BLOB : ScHname = ScHname(0xddd4c281); +pub(crate) const HVIEW_GET_BLOB_FIELD : ScHname = ScHname(0x1f448130); +pub(crate) const HVIEW_GET_BLOB_INFO : ScHname = ScHname(0xfde4ab46); +pub(crate) const HVIEW_LIST_BLOBS : ScHname = ScHname(0x62ca7990); diff --git a/packages/vm/wasmlib/src/coreblob/contract.rs b/packages/vm/wasmlib/src/coreblob/contract.rs index fc3969aa76..0f080a4c02 100644 --- a/packages/vm/wasmlib/src/coreblob/contract.rs +++ b/packages/vm/wasmlib/src/coreblob/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -15,26 +13,26 @@ use crate::*; use crate::coreblob::*; pub struct StoreBlobCall { - pub func: ScFunc, - pub params: MutableStoreBlobParams, - pub results: ImmutableStoreBlobResults, + pub func: ScFunc, + pub params: MutableStoreBlobParams, + pub results: ImmutableStoreBlobResults, } pub struct GetBlobFieldCall { - pub func: ScView, - pub params: MutableGetBlobFieldParams, - pub results: ImmutableGetBlobFieldResults, + pub func: ScView, + pub params: MutableGetBlobFieldParams, + pub results: ImmutableGetBlobFieldResults, } pub struct GetBlobInfoCall { - pub func: ScView, - pub params: MutableGetBlobInfoParams, - pub results: ImmutableGetBlobInfoResults, + pub func: ScView, + pub params: MutableGetBlobInfoParams, + pub results: ImmutableGetBlobInfoResults, } pub struct ListBlobsCall { - pub func: ScView, - pub results: ImmutableListBlobsResults, + pub func: ScView, + pub results: ImmutableListBlobsResults, } pub struct ScFuncs { @@ -43,39 +41,40 @@ pub struct ScFuncs { impl ScFuncs { pub fn store_blob(_ctx: & dyn ScFuncCallContext) -> StoreBlobCall { let mut f = StoreBlobCall { - func: ScFunc::new(HSC_NAME, HFUNC_STORE_BLOB), - params: MutableStoreBlobParams { id: 0 }, + func: ScFunc::new(HSC_NAME, HFUNC_STORE_BLOB), + params: MutableStoreBlobParams { id: 0 }, results: ImmutableStoreBlobResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_blob_field(_ctx: & dyn ScViewCallContext) -> GetBlobFieldCall { let mut f = GetBlobFieldCall { - func: ScView::new(HSC_NAME, HVIEW_GET_BLOB_FIELD), - params: MutableGetBlobFieldParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_BLOB_FIELD), + params: MutableGetBlobFieldParams { id: 0 }, results: ImmutableGetBlobFieldResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_blob_info(_ctx: & dyn ScViewCallContext) -> GetBlobInfoCall { let mut f = GetBlobInfoCall { - func: ScView::new(HSC_NAME, HVIEW_GET_BLOB_INFO), - params: MutableGetBlobInfoParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_BLOB_INFO), + params: MutableGetBlobInfoParams { id: 0 }, results: ImmutableGetBlobInfoResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn list_blobs(_ctx: & dyn ScViewCallContext) -> ListBlobsCall { let mut f = ListBlobsCall { - func: ScView::new(HSC_NAME, HVIEW_LIST_BLOBS), + func: ScView::new(HSC_NAME, HVIEW_LIST_BLOBS), results: ImmutableListBlobsResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/packages/vm/wasmlib/src/coreblob/params.rs b/packages/vm/wasmlib/src/coreblob/params.rs index e2ecd927fa..54c0d9bebe 100644 --- a/packages/vm/wasmlib/src/coreblob/params.rs +++ b/packages/vm/wasmlib/src/coreblob/params.rs @@ -13,7 +13,7 @@ use crate::coreblob::*; use crate::host::*; pub struct MapStringToImmutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToImmutableBytes { @@ -29,17 +29,17 @@ pub struct ImmutableStoreBlobParams { impl ImmutableStoreBlobParams { pub fn blobs(&self) -> MapStringToImmutableBytes { - MapStringToImmutableBytes { obj_id: self.id } - } + MapStringToImmutableBytes { obj_id: self.id } + } } pub struct MapStringToMutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToMutableBytes { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_bytes(&self, key: &str) -> ScMutableBytes { @@ -54,8 +54,8 @@ pub struct MutableStoreBlobParams { impl MutableStoreBlobParams { pub fn blobs(&self) -> MapStringToMutableBytes { - MapStringToMutableBytes { obj_id: self.id } - } + MapStringToMutableBytes { obj_id: self.id } + } } #[derive(Clone, Copy)] @@ -65,12 +65,12 @@ pub struct ImmutableGetBlobFieldParams { impl ImmutableGetBlobFieldParams { pub fn field(&self) -> ScImmutableString { - ScImmutableString::new(self.id, PARAM_FIELD.get_key_id()) - } + ScImmutableString::new(self.id, PARAM_FIELD.get_key_id()) + } pub fn hash(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, PARAM_HASH.get_key_id()) - } + ScImmutableHash::new(self.id, PARAM_HASH.get_key_id()) + } } #[derive(Clone, Copy)] @@ -80,12 +80,12 @@ pub struct MutableGetBlobFieldParams { impl MutableGetBlobFieldParams { pub fn field(&self) -> ScMutableString { - ScMutableString::new(self.id, PARAM_FIELD.get_key_id()) - } + ScMutableString::new(self.id, PARAM_FIELD.get_key_id()) + } pub fn hash(&self) -> ScMutableHash { - ScMutableHash::new(self.id, PARAM_HASH.get_key_id()) - } + ScMutableHash::new(self.id, PARAM_HASH.get_key_id()) + } } #[derive(Clone, Copy)] @@ -95,8 +95,8 @@ pub struct ImmutableGetBlobInfoParams { impl ImmutableGetBlobInfoParams { pub fn hash(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, PARAM_HASH.get_key_id()) - } + ScImmutableHash::new(self.id, PARAM_HASH.get_key_id()) + } } #[derive(Clone, Copy)] @@ -106,6 +106,6 @@ pub struct MutableGetBlobInfoParams { impl MutableGetBlobInfoParams { pub fn hash(&self) -> ScMutableHash { - ScMutableHash::new(self.id, PARAM_HASH.get_key_id()) - } + ScMutableHash::new(self.id, PARAM_HASH.get_key_id()) + } } diff --git a/packages/vm/wasmlib/src/coreblob/results.rs b/packages/vm/wasmlib/src/coreblob/results.rs index a4e6be96a6..dd06064b2e 100644 --- a/packages/vm/wasmlib/src/coreblob/results.rs +++ b/packages/vm/wasmlib/src/coreblob/results.rs @@ -19,8 +19,8 @@ pub struct ImmutableStoreBlobResults { impl ImmutableStoreBlobResults { pub fn hash(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, RESULT_HASH.get_key_id()) - } + ScImmutableHash::new(self.id, RESULT_HASH.get_key_id()) + } } #[derive(Clone, Copy)] @@ -30,8 +30,8 @@ pub struct MutableStoreBlobResults { impl MutableStoreBlobResults { pub fn hash(&self) -> ScMutableHash { - ScMutableHash::new(self.id, RESULT_HASH.get_key_id()) - } + ScMutableHash::new(self.id, RESULT_HASH.get_key_id()) + } } #[derive(Clone, Copy)] @@ -41,8 +41,8 @@ pub struct ImmutableGetBlobFieldResults { impl ImmutableGetBlobFieldResults { pub fn bytes(&self) -> ScImmutableBytes { - ScImmutableBytes::new(self.id, RESULT_BYTES.get_key_id()) - } + ScImmutableBytes::new(self.id, RESULT_BYTES.get_key_id()) + } } #[derive(Clone, Copy)] @@ -52,12 +52,12 @@ pub struct MutableGetBlobFieldResults { impl MutableGetBlobFieldResults { pub fn bytes(&self) -> ScMutableBytes { - ScMutableBytes::new(self.id, RESULT_BYTES.get_key_id()) - } + ScMutableBytes::new(self.id, RESULT_BYTES.get_key_id()) + } } pub struct MapStringToImmutableInt32 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToImmutableInt32 { @@ -73,17 +73,17 @@ pub struct ImmutableGetBlobInfoResults { impl ImmutableGetBlobInfoResults { pub fn blob_sizes(&self) -> MapStringToImmutableInt32 { - MapStringToImmutableInt32 { obj_id: self.id } - } + MapStringToImmutableInt32 { obj_id: self.id } + } } pub struct MapStringToMutableInt32 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapStringToMutableInt32 { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_int32(&self, key: &str) -> ScMutableInt32 { @@ -98,12 +98,12 @@ pub struct MutableGetBlobInfoResults { impl MutableGetBlobInfoResults { pub fn blob_sizes(&self) -> MapStringToMutableInt32 { - MapStringToMutableInt32 { obj_id: self.id } - } + MapStringToMutableInt32 { obj_id: self.id } + } } pub struct MapHashToImmutableInt32 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapHashToImmutableInt32 { @@ -119,17 +119,17 @@ pub struct ImmutableListBlobsResults { impl ImmutableListBlobsResults { pub fn blob_sizes(&self) -> MapHashToImmutableInt32 { - MapHashToImmutableInt32 { obj_id: self.id } - } + MapHashToImmutableInt32 { obj_id: self.id } + } } pub struct MapHashToMutableInt32 { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapHashToMutableInt32 { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } pub fn get_int32(&self, key: &ScHash) -> ScMutableInt32 { @@ -144,6 +144,6 @@ pub struct MutableListBlobsResults { impl MutableListBlobsResults { pub fn blob_sizes(&self) -> MapHashToMutableInt32 { - MapHashToMutableInt32 { obj_id: self.id } - } + MapHashToMutableInt32 { obj_id: self.id } + } } diff --git a/packages/vm/wasmlib/src/coreblocklog/consts.rs b/packages/vm/wasmlib/src/coreblocklog/consts.rs index b198f19cc2..11051412bb 100644 --- a/packages/vm/wasmlib/src/coreblocklog/consts.rs +++ b/packages/vm/wasmlib/src/coreblocklog/consts.rs @@ -5,52 +5,48 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use crate::*; -pub const SC_NAME: &str = "blocklog"; -pub const SC_DESCRIPTION: &str = "Core block log contract"; -pub const HSC_NAME: ScHname = ScHname(0xf538ef2b); - -pub(crate) const PARAM_BLOCK_INDEX: &str = "n"; -pub(crate) const PARAM_CONTRACT_HNAME: &str = "h"; -pub(crate) const PARAM_FROM_BLOCK: &str = "f"; -pub(crate) const PARAM_REQUEST_ID: &str = "u"; -pub(crate) const PARAM_TO_BLOCK: &str = "t"; - -pub(crate) const RESULT_BLOCK_INDEX: &str = "n"; -pub(crate) const RESULT_BLOCK_INFO: &str = "i"; -pub(crate) const RESULT_EVENT: &str = "e"; -pub(crate) const RESULT_GOVERNING_ADDRESS: &str = "g"; -pub(crate) const RESULT_REQUEST_ID: &str = "u"; -pub(crate) const RESULT_REQUEST_INDEX: &str = "r"; -pub(crate) const RESULT_REQUEST_PROCESSED: &str = "p"; -pub(crate) const RESULT_REQUEST_RECORD: &str = "d"; -pub(crate) const RESULT_STATE_CONTROLLER_ADDRESS: &str = "s"; - -pub(crate) const VIEW_CONTROL_ADDRESSES: &str = "controlAddresses"; -pub(crate) const VIEW_GET_BLOCK_INFO: &str = "getBlockInfo"; -pub(crate) const VIEW_GET_EVENTS_FOR_BLOCK: &str = "getEventsForBlock"; -pub(crate) const VIEW_GET_EVENTS_FOR_CONTRACT: &str = "getEventsForContract"; -pub(crate) const VIEW_GET_EVENTS_FOR_REQUEST: &str = "getEventsForRequest"; -pub(crate) const VIEW_GET_LATEST_BLOCK_INFO: &str = "getLatestBlockInfo"; -pub(crate) const VIEW_GET_REQUEST_I_DS_FOR_BLOCK: &str = "getRequestIDsForBlock"; -pub(crate) const VIEW_GET_REQUEST_RECEIPT: &str = "getRequestReceipt"; -pub(crate) const VIEW_GET_REQUEST_RECEIPTS_FOR_BLOCK: &str = "getRequestReceiptsForBlock"; -pub(crate) const VIEW_IS_REQUEST_PROCESSED: &str = "isRequestProcessed"; - -pub(crate) const HVIEW_CONTROL_ADDRESSES: ScHname = ScHname(0x796bd223); -pub(crate) const HVIEW_GET_BLOCK_INFO: ScHname = ScHname(0xbe89f9b3); -pub(crate) const HVIEW_GET_EVENTS_FOR_BLOCK: ScHname = ScHname(0x36232798); -pub(crate) const HVIEW_GET_EVENTS_FOR_CONTRACT: ScHname = ScHname(0x682a1922); -pub(crate) const HVIEW_GET_EVENTS_FOR_REQUEST: ScHname = ScHname(0x4f8d68e4); -pub(crate) const HVIEW_GET_LATEST_BLOCK_INFO: ScHname = ScHname(0x084a1760); -pub(crate) const HVIEW_GET_REQUEST_I_DS_FOR_BLOCK: ScHname = ScHname(0x5a20327a); -pub(crate) const HVIEW_GET_REQUEST_RECEIPT: ScHname = ScHname(0xb7f9534f); -pub(crate) const HVIEW_GET_REQUEST_RECEIPTS_FOR_BLOCK: ScHname = ScHname(0x77e3beef); -pub(crate) const HVIEW_IS_REQUEST_PROCESSED: ScHname = ScHname(0xd57d50a9); - -// @formatter:on +pub const SC_NAME : &str = "blocklog"; +pub const SC_DESCRIPTION : &str = "Core block log contract"; +pub const HSC_NAME : ScHname = ScHname(0xf538ef2b); + +pub(crate) const PARAM_BLOCK_INDEX : &str = "n"; +pub(crate) const PARAM_CONTRACT_HNAME : &str = "h"; +pub(crate) const PARAM_FROM_BLOCK : &str = "f"; +pub(crate) const PARAM_REQUEST_ID : &str = "u"; +pub(crate) const PARAM_TO_BLOCK : &str = "t"; + +pub(crate) const RESULT_BLOCK_INDEX : &str = "n"; +pub(crate) const RESULT_BLOCK_INFO : &str = "i"; +pub(crate) const RESULT_EVENT : &str = "e"; +pub(crate) const RESULT_GOVERNING_ADDRESS : &str = "g"; +pub(crate) const RESULT_REQUEST_ID : &str = "u"; +pub(crate) const RESULT_REQUEST_INDEX : &str = "r"; +pub(crate) const RESULT_REQUEST_PROCESSED : &str = "p"; +pub(crate) const RESULT_REQUEST_RECORD : &str = "d"; +pub(crate) const RESULT_STATE_CONTROLLER_ADDRESS : &str = "s"; + +pub(crate) const VIEW_CONTROL_ADDRESSES : &str = "controlAddresses"; +pub(crate) const VIEW_GET_BLOCK_INFO : &str = "getBlockInfo"; +pub(crate) const VIEW_GET_EVENTS_FOR_BLOCK : &str = "getEventsForBlock"; +pub(crate) const VIEW_GET_EVENTS_FOR_CONTRACT : &str = "getEventsForContract"; +pub(crate) const VIEW_GET_EVENTS_FOR_REQUEST : &str = "getEventsForRequest"; +pub(crate) const VIEW_GET_LATEST_BLOCK_INFO : &str = "getLatestBlockInfo"; +pub(crate) const VIEW_GET_REQUEST_I_DS_FOR_BLOCK : &str = "getRequestIDsForBlock"; +pub(crate) const VIEW_GET_REQUEST_RECEIPT : &str = "getRequestReceipt"; +pub(crate) const VIEW_GET_REQUEST_RECEIPTS_FOR_BLOCK : &str = "getRequestReceiptsForBlock"; +pub(crate) const VIEW_IS_REQUEST_PROCESSED : &str = "isRequestProcessed"; + +pub(crate) const HVIEW_CONTROL_ADDRESSES : ScHname = ScHname(0x796bd223); +pub(crate) const HVIEW_GET_BLOCK_INFO : ScHname = ScHname(0xbe89f9b3); +pub(crate) const HVIEW_GET_EVENTS_FOR_BLOCK : ScHname = ScHname(0x36232798); +pub(crate) const HVIEW_GET_EVENTS_FOR_CONTRACT : ScHname = ScHname(0x682a1922); +pub(crate) const HVIEW_GET_EVENTS_FOR_REQUEST : ScHname = ScHname(0x4f8d68e4); +pub(crate) const HVIEW_GET_LATEST_BLOCK_INFO : ScHname = ScHname(0x084a1760); +pub(crate) const HVIEW_GET_REQUEST_I_DS_FOR_BLOCK : ScHname = ScHname(0x5a20327a); +pub(crate) const HVIEW_GET_REQUEST_RECEIPT : ScHname = ScHname(0xb7f9534f); +pub(crate) const HVIEW_GET_REQUEST_RECEIPTS_FOR_BLOCK : ScHname = ScHname(0x77e3beef); +pub(crate) const HVIEW_IS_REQUEST_PROCESSED : ScHname = ScHname(0xd57d50a9); diff --git a/packages/vm/wasmlib/src/coreblocklog/contract.rs b/packages/vm/wasmlib/src/coreblocklog/contract.rs index fa165bdf10..e8bad48177 100644 --- a/packages/vm/wasmlib/src/coreblocklog/contract.rs +++ b/packages/vm/wasmlib/src/coreblocklog/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -15,61 +13,61 @@ use crate::*; use crate::coreblocklog::*; pub struct ControlAddressesCall { - pub func: ScView, - pub results: ImmutableControlAddressesResults, + pub func: ScView, + pub results: ImmutableControlAddressesResults, } pub struct GetBlockInfoCall { - pub func: ScView, - pub params: MutableGetBlockInfoParams, - pub results: ImmutableGetBlockInfoResults, + pub func: ScView, + pub params: MutableGetBlockInfoParams, + pub results: ImmutableGetBlockInfoResults, } pub struct GetEventsForBlockCall { - pub func: ScView, - pub params: MutableGetEventsForBlockParams, - pub results: ImmutableGetEventsForBlockResults, + pub func: ScView, + pub params: MutableGetEventsForBlockParams, + pub results: ImmutableGetEventsForBlockResults, } pub struct GetEventsForContractCall { - pub func: ScView, - pub params: MutableGetEventsForContractParams, - pub results: ImmutableGetEventsForContractResults, + pub func: ScView, + pub params: MutableGetEventsForContractParams, + pub results: ImmutableGetEventsForContractResults, } pub struct GetEventsForRequestCall { - pub func: ScView, - pub params: MutableGetEventsForRequestParams, - pub results: ImmutableGetEventsForRequestResults, + pub func: ScView, + pub params: MutableGetEventsForRequestParams, + pub results: ImmutableGetEventsForRequestResults, } pub struct GetLatestBlockInfoCall { - pub func: ScView, - pub results: ImmutableGetLatestBlockInfoResults, + pub func: ScView, + pub results: ImmutableGetLatestBlockInfoResults, } pub struct GetRequestIDsForBlockCall { - pub func: ScView, - pub params: MutableGetRequestIDsForBlockParams, - pub results: ImmutableGetRequestIDsForBlockResults, + pub func: ScView, + pub params: MutableGetRequestIDsForBlockParams, + pub results: ImmutableGetRequestIDsForBlockResults, } pub struct GetRequestReceiptCall { - pub func: ScView, - pub params: MutableGetRequestReceiptParams, - pub results: ImmutableGetRequestReceiptResults, + pub func: ScView, + pub params: MutableGetRequestReceiptParams, + pub results: ImmutableGetRequestReceiptResults, } pub struct GetRequestReceiptsForBlockCall { - pub func: ScView, - pub params: MutableGetRequestReceiptsForBlockParams, - pub results: ImmutableGetRequestReceiptsForBlockResults, + pub func: ScView, + pub params: MutableGetRequestReceiptsForBlockParams, + pub results: ImmutableGetRequestReceiptsForBlockResults, } pub struct IsRequestProcessedCall { - pub func: ScView, - pub params: MutableIsRequestProcessedParams, - pub results: ImmutableIsRequestProcessedResults, + pub func: ScView, + pub params: MutableIsRequestProcessedParams, + pub results: ImmutableIsRequestProcessedResults, } pub struct ScFuncs { @@ -78,92 +76,99 @@ pub struct ScFuncs { impl ScFuncs { pub fn control_addresses(_ctx: & dyn ScViewCallContext) -> ControlAddressesCall { let mut f = ControlAddressesCall { - func: ScView::new(HSC_NAME, HVIEW_CONTROL_ADDRESSES), + func: ScView::new(HSC_NAME, HVIEW_CONTROL_ADDRESSES), results: ImmutableControlAddressesResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn get_block_info(_ctx: & dyn ScViewCallContext) -> GetBlockInfoCall { let mut f = GetBlockInfoCall { - func: ScView::new(HSC_NAME, HVIEW_GET_BLOCK_INFO), - params: MutableGetBlockInfoParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_BLOCK_INFO), + params: MutableGetBlockInfoParams { id: 0 }, results: ImmutableGetBlockInfoResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_events_for_block(_ctx: & dyn ScViewCallContext) -> GetEventsForBlockCall { let mut f = GetEventsForBlockCall { - func: ScView::new(HSC_NAME, HVIEW_GET_EVENTS_FOR_BLOCK), - params: MutableGetEventsForBlockParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_EVENTS_FOR_BLOCK), + params: MutableGetEventsForBlockParams { id: 0 }, results: ImmutableGetEventsForBlockResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_events_for_contract(_ctx: & dyn ScViewCallContext) -> GetEventsForContractCall { let mut f = GetEventsForContractCall { - func: ScView::new(HSC_NAME, HVIEW_GET_EVENTS_FOR_CONTRACT), - params: MutableGetEventsForContractParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_EVENTS_FOR_CONTRACT), + params: MutableGetEventsForContractParams { id: 0 }, results: ImmutableGetEventsForContractResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_events_for_request(_ctx: & dyn ScViewCallContext) -> GetEventsForRequestCall { let mut f = GetEventsForRequestCall { - func: ScView::new(HSC_NAME, HVIEW_GET_EVENTS_FOR_REQUEST), - params: MutableGetEventsForRequestParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_EVENTS_FOR_REQUEST), + params: MutableGetEventsForRequestParams { id: 0 }, results: ImmutableGetEventsForRequestResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_latest_block_info(_ctx: & dyn ScViewCallContext) -> GetLatestBlockInfoCall { let mut f = GetLatestBlockInfoCall { - func: ScView::new(HSC_NAME, HVIEW_GET_LATEST_BLOCK_INFO), + func: ScView::new(HSC_NAME, HVIEW_GET_LATEST_BLOCK_INFO), results: ImmutableGetLatestBlockInfoResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn get_request_i_ds_for_block(_ctx: & dyn ScViewCallContext) -> GetRequestIDsForBlockCall { let mut f = GetRequestIDsForBlockCall { - func: ScView::new(HSC_NAME, HVIEW_GET_REQUEST_I_DS_FOR_BLOCK), - params: MutableGetRequestIDsForBlockParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_REQUEST_I_DS_FOR_BLOCK), + params: MutableGetRequestIDsForBlockParams { id: 0 }, results: ImmutableGetRequestIDsForBlockResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_request_receipt(_ctx: & dyn ScViewCallContext) -> GetRequestReceiptCall { let mut f = GetRequestReceiptCall { - func: ScView::new(HSC_NAME, HVIEW_GET_REQUEST_RECEIPT), - params: MutableGetRequestReceiptParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_REQUEST_RECEIPT), + params: MutableGetRequestReceiptParams { id: 0 }, results: ImmutableGetRequestReceiptResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_request_receipts_for_block(_ctx: & dyn ScViewCallContext) -> GetRequestReceiptsForBlockCall { let mut f = GetRequestReceiptsForBlockCall { - func: ScView::new(HSC_NAME, HVIEW_GET_REQUEST_RECEIPTS_FOR_BLOCK), - params: MutableGetRequestReceiptsForBlockParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_REQUEST_RECEIPTS_FOR_BLOCK), + params: MutableGetRequestReceiptsForBlockParams { id: 0 }, results: ImmutableGetRequestReceiptsForBlockResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn is_request_processed(_ctx: & dyn ScViewCallContext) -> IsRequestProcessedCall { let mut f = IsRequestProcessedCall { - func: ScView::new(HSC_NAME, HVIEW_IS_REQUEST_PROCESSED), - params: MutableIsRequestProcessedParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_IS_REQUEST_PROCESSED), + params: MutableIsRequestProcessedParams { id: 0 }, results: ImmutableIsRequestProcessedResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } } - -// @formatter:on diff --git a/packages/vm/wasmlib/src/coreblocklog/params.rs b/packages/vm/wasmlib/src/coreblocklog/params.rs index 3f7adb0e83..01b87611c2 100644 --- a/packages/vm/wasmlib/src/coreblocklog/params.rs +++ b/packages/vm/wasmlib/src/coreblocklog/params.rs @@ -19,8 +19,8 @@ pub struct ImmutableGetBlockInfoParams { impl ImmutableGetBlockInfoParams { pub fn block_index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) - } + ScImmutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) + } } #[derive(Clone, Copy)] @@ -30,8 +30,8 @@ pub struct MutableGetBlockInfoParams { impl MutableGetBlockInfoParams { pub fn block_index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) - } + ScMutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) + } } #[derive(Clone, Copy)] @@ -41,8 +41,8 @@ pub struct ImmutableGetEventsForBlockParams { impl ImmutableGetEventsForBlockParams { pub fn block_index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) - } + ScImmutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) + } } #[derive(Clone, Copy)] @@ -52,8 +52,8 @@ pub struct MutableGetEventsForBlockParams { impl MutableGetEventsForBlockParams { pub fn block_index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) - } + ScMutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) + } } #[derive(Clone, Copy)] @@ -63,16 +63,16 @@ pub struct ImmutableGetEventsForContractParams { impl ImmutableGetEventsForContractParams { pub fn contract_hname(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, PARAM_CONTRACT_HNAME.get_key_id()) - } + ScImmutableHname::new(self.id, PARAM_CONTRACT_HNAME.get_key_id()) + } pub fn from_block(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, PARAM_FROM_BLOCK.get_key_id()) - } + ScImmutableInt32::new(self.id, PARAM_FROM_BLOCK.get_key_id()) + } pub fn to_block(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, PARAM_TO_BLOCK.get_key_id()) - } + ScImmutableInt32::new(self.id, PARAM_TO_BLOCK.get_key_id()) + } } #[derive(Clone, Copy)] @@ -82,16 +82,16 @@ pub struct MutableGetEventsForContractParams { impl MutableGetEventsForContractParams { pub fn contract_hname(&self) -> ScMutableHname { - ScMutableHname::new(self.id, PARAM_CONTRACT_HNAME.get_key_id()) - } + ScMutableHname::new(self.id, PARAM_CONTRACT_HNAME.get_key_id()) + } pub fn from_block(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, PARAM_FROM_BLOCK.get_key_id()) - } + ScMutableInt32::new(self.id, PARAM_FROM_BLOCK.get_key_id()) + } pub fn to_block(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, PARAM_TO_BLOCK.get_key_id()) - } + ScMutableInt32::new(self.id, PARAM_TO_BLOCK.get_key_id()) + } } #[derive(Clone, Copy)] @@ -101,8 +101,8 @@ pub struct ImmutableGetEventsForRequestParams { impl ImmutableGetEventsForRequestParams { pub fn request_id(&self) -> ScImmutableRequestID { - ScImmutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) - } + ScImmutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) + } } #[derive(Clone, Copy)] @@ -112,8 +112,8 @@ pub struct MutableGetEventsForRequestParams { impl MutableGetEventsForRequestParams { pub fn request_id(&self) -> ScMutableRequestID { - ScMutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) - } + ScMutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) + } } #[derive(Clone, Copy)] @@ -123,8 +123,8 @@ pub struct ImmutableGetRequestIDsForBlockParams { impl ImmutableGetRequestIDsForBlockParams { pub fn block_index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) - } + ScImmutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) + } } #[derive(Clone, Copy)] @@ -134,8 +134,8 @@ pub struct MutableGetRequestIDsForBlockParams { impl MutableGetRequestIDsForBlockParams { pub fn block_index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) - } + ScMutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) + } } #[derive(Clone, Copy)] @@ -145,8 +145,8 @@ pub struct ImmutableGetRequestReceiptParams { impl ImmutableGetRequestReceiptParams { pub fn request_id(&self) -> ScImmutableRequestID { - ScImmutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) - } + ScImmutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) + } } #[derive(Clone, Copy)] @@ -156,8 +156,8 @@ pub struct MutableGetRequestReceiptParams { impl MutableGetRequestReceiptParams { pub fn request_id(&self) -> ScMutableRequestID { - ScMutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) - } + ScMutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) + } } #[derive(Clone, Copy)] @@ -167,8 +167,8 @@ pub struct ImmutableGetRequestReceiptsForBlockParams { impl ImmutableGetRequestReceiptsForBlockParams { pub fn block_index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) - } + ScImmutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) + } } #[derive(Clone, Copy)] @@ -178,8 +178,8 @@ pub struct MutableGetRequestReceiptsForBlockParams { impl MutableGetRequestReceiptsForBlockParams { pub fn block_index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) - } + ScMutableInt32::new(self.id, PARAM_BLOCK_INDEX.get_key_id()) + } } #[derive(Clone, Copy)] @@ -189,8 +189,8 @@ pub struct ImmutableIsRequestProcessedParams { impl ImmutableIsRequestProcessedParams { pub fn request_id(&self) -> ScImmutableRequestID { - ScImmutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) - } + ScImmutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) + } } #[derive(Clone, Copy)] @@ -200,6 +200,6 @@ pub struct MutableIsRequestProcessedParams { impl MutableIsRequestProcessedParams { pub fn request_id(&self) -> ScMutableRequestID { - ScMutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) - } + ScMutableRequestID::new(self.id, PARAM_REQUEST_ID.get_key_id()) + } } diff --git a/packages/vm/wasmlib/src/coreblocklog/results.rs b/packages/vm/wasmlib/src/coreblocklog/results.rs index a3a0e6a750..19809b8973 100644 --- a/packages/vm/wasmlib/src/coreblocklog/results.rs +++ b/packages/vm/wasmlib/src/coreblocklog/results.rs @@ -19,16 +19,16 @@ pub struct ImmutableControlAddressesResults { impl ImmutableControlAddressesResults { pub fn block_index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) - } + ScImmutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) + } pub fn governing_address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, RESULT_GOVERNING_ADDRESS.get_key_id()) - } + ScImmutableAddress::new(self.id, RESULT_GOVERNING_ADDRESS.get_key_id()) + } pub fn state_controller_address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, RESULT_STATE_CONTROLLER_ADDRESS.get_key_id()) - } + ScImmutableAddress::new(self.id, RESULT_STATE_CONTROLLER_ADDRESS.get_key_id()) + } } #[derive(Clone, Copy)] @@ -38,16 +38,16 @@ pub struct MutableControlAddressesResults { impl MutableControlAddressesResults { pub fn block_index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) - } + ScMutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) + } pub fn governing_address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, RESULT_GOVERNING_ADDRESS.get_key_id()) - } + ScMutableAddress::new(self.id, RESULT_GOVERNING_ADDRESS.get_key_id()) + } pub fn state_controller_address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, RESULT_STATE_CONTROLLER_ADDRESS.get_key_id()) - } + ScMutableAddress::new(self.id, RESULT_STATE_CONTROLLER_ADDRESS.get_key_id()) + } } #[derive(Clone, Copy)] @@ -57,8 +57,8 @@ pub struct ImmutableGetBlockInfoResults { impl ImmutableGetBlockInfoResults { pub fn block_info(&self) -> ScImmutableBytes { - ScImmutableBytes::new(self.id, RESULT_BLOCK_INFO.get_key_id()) - } + ScImmutableBytes::new(self.id, RESULT_BLOCK_INFO.get_key_id()) + } } #[derive(Clone, Copy)] @@ -68,12 +68,12 @@ pub struct MutableGetBlockInfoResults { impl MutableGetBlockInfoResults { pub fn block_info(&self) -> ScMutableBytes { - ScMutableBytes::new(self.id, RESULT_BLOCK_INFO.get_key_id()) - } + ScMutableBytes::new(self.id, RESULT_BLOCK_INFO.get_key_id()) + } } pub struct ArrayOfImmutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfImmutableBytes { @@ -93,13 +93,13 @@ pub struct ImmutableGetEventsForBlockResults { impl ImmutableGetEventsForBlockResults { pub fn event(&self) -> ArrayOfImmutableBytes { - let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); - ArrayOfImmutableBytes { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); + ArrayOfImmutableBytes { obj_id: arr_id } + } } pub struct ArrayOfMutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfMutableBytes { @@ -123,9 +123,9 @@ pub struct MutableGetEventsForBlockResults { impl MutableGetEventsForBlockResults { pub fn event(&self) -> ArrayOfMutableBytes { - let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); - ArrayOfMutableBytes { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); + ArrayOfMutableBytes { obj_id: arr_id } + } } #[derive(Clone, Copy)] @@ -135,9 +135,9 @@ pub struct ImmutableGetEventsForContractResults { impl ImmutableGetEventsForContractResults { pub fn event(&self) -> ArrayOfImmutableBytes { - let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); - ArrayOfImmutableBytes { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); + ArrayOfImmutableBytes { obj_id: arr_id } + } } #[derive(Clone, Copy)] @@ -147,9 +147,9 @@ pub struct MutableGetEventsForContractResults { impl MutableGetEventsForContractResults { pub fn event(&self) -> ArrayOfMutableBytes { - let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); - ArrayOfMutableBytes { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); + ArrayOfMutableBytes { obj_id: arr_id } + } } #[derive(Clone, Copy)] @@ -159,9 +159,9 @@ pub struct ImmutableGetEventsForRequestResults { impl ImmutableGetEventsForRequestResults { pub fn event(&self) -> ArrayOfImmutableBytes { - let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); - ArrayOfImmutableBytes { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); + ArrayOfImmutableBytes { obj_id: arr_id } + } } #[derive(Clone, Copy)] @@ -171,9 +171,9 @@ pub struct MutableGetEventsForRequestResults { impl MutableGetEventsForRequestResults { pub fn event(&self) -> ArrayOfMutableBytes { - let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); - ArrayOfMutableBytes { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_EVENT.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); + ArrayOfMutableBytes { obj_id: arr_id } + } } #[derive(Clone, Copy)] @@ -183,12 +183,12 @@ pub struct ImmutableGetLatestBlockInfoResults { impl ImmutableGetLatestBlockInfoResults { pub fn block_index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) - } + ScImmutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) + } pub fn block_info(&self) -> ScImmutableBytes { - ScImmutableBytes::new(self.id, RESULT_BLOCK_INFO.get_key_id()) - } + ScImmutableBytes::new(self.id, RESULT_BLOCK_INFO.get_key_id()) + } } #[derive(Clone, Copy)] @@ -198,16 +198,16 @@ pub struct MutableGetLatestBlockInfoResults { impl MutableGetLatestBlockInfoResults { pub fn block_index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) - } + ScMutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) + } pub fn block_info(&self) -> ScMutableBytes { - ScMutableBytes::new(self.id, RESULT_BLOCK_INFO.get_key_id()) - } + ScMutableBytes::new(self.id, RESULT_BLOCK_INFO.get_key_id()) + } } pub struct ArrayOfImmutableRequestID { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfImmutableRequestID { @@ -227,13 +227,13 @@ pub struct ImmutableGetRequestIDsForBlockResults { impl ImmutableGetRequestIDsForBlockResults { pub fn request_id(&self) -> ArrayOfImmutableRequestID { - let arr_id = get_object_id(self.id, RESULT_REQUEST_ID.get_key_id(), TYPE_ARRAY16 | TYPE_REQUEST_ID); - ArrayOfImmutableRequestID { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_REQUEST_ID.get_key_id(), TYPE_ARRAY16 | TYPE_REQUEST_ID); + ArrayOfImmutableRequestID { obj_id: arr_id } + } } pub struct ArrayOfMutableRequestID { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfMutableRequestID { @@ -257,9 +257,9 @@ pub struct MutableGetRequestIDsForBlockResults { impl MutableGetRequestIDsForBlockResults { pub fn request_id(&self) -> ArrayOfMutableRequestID { - let arr_id = get_object_id(self.id, RESULT_REQUEST_ID.get_key_id(), TYPE_ARRAY16 | TYPE_REQUEST_ID); - ArrayOfMutableRequestID { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_REQUEST_ID.get_key_id(), TYPE_ARRAY16 | TYPE_REQUEST_ID); + ArrayOfMutableRequestID { obj_id: arr_id } + } } #[derive(Clone, Copy)] @@ -269,16 +269,16 @@ pub struct ImmutableGetRequestReceiptResults { impl ImmutableGetRequestReceiptResults { pub fn block_index(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) - } + ScImmutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) + } pub fn request_index(&self) -> ScImmutableInt16 { - ScImmutableInt16::new(self.id, RESULT_REQUEST_INDEX.get_key_id()) - } + ScImmutableInt16::new(self.id, RESULT_REQUEST_INDEX.get_key_id()) + } pub fn request_record(&self) -> ScImmutableBytes { - ScImmutableBytes::new(self.id, RESULT_REQUEST_RECORD.get_key_id()) - } + ScImmutableBytes::new(self.id, RESULT_REQUEST_RECORD.get_key_id()) + } } #[derive(Clone, Copy)] @@ -288,16 +288,16 @@ pub struct MutableGetRequestReceiptResults { impl MutableGetRequestReceiptResults { pub fn block_index(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) - } + ScMutableInt32::new(self.id, RESULT_BLOCK_INDEX.get_key_id()) + } pub fn request_index(&self) -> ScMutableInt16 { - ScMutableInt16::new(self.id, RESULT_REQUEST_INDEX.get_key_id()) - } + ScMutableInt16::new(self.id, RESULT_REQUEST_INDEX.get_key_id()) + } pub fn request_record(&self) -> ScMutableBytes { - ScMutableBytes::new(self.id, RESULT_REQUEST_RECORD.get_key_id()) - } + ScMutableBytes::new(self.id, RESULT_REQUEST_RECORD.get_key_id()) + } } #[derive(Clone, Copy)] @@ -307,9 +307,9 @@ pub struct ImmutableGetRequestReceiptsForBlockResults { impl ImmutableGetRequestReceiptsForBlockResults { pub fn request_record(&self) -> ArrayOfImmutableBytes { - let arr_id = get_object_id(self.id, RESULT_REQUEST_RECORD.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); - ArrayOfImmutableBytes { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_REQUEST_RECORD.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); + ArrayOfImmutableBytes { obj_id: arr_id } + } } #[derive(Clone, Copy)] @@ -319,9 +319,9 @@ pub struct MutableGetRequestReceiptsForBlockResults { impl MutableGetRequestReceiptsForBlockResults { pub fn request_record(&self) -> ArrayOfMutableBytes { - let arr_id = get_object_id(self.id, RESULT_REQUEST_RECORD.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); - ArrayOfMutableBytes { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_REQUEST_RECORD.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); + ArrayOfMutableBytes { obj_id: arr_id } + } } #[derive(Clone, Copy)] @@ -331,8 +331,8 @@ pub struct ImmutableIsRequestProcessedResults { impl ImmutableIsRequestProcessedResults { pub fn request_processed(&self) -> ScImmutableString { - ScImmutableString::new(self.id, RESULT_REQUEST_PROCESSED.get_key_id()) - } + ScImmutableString::new(self.id, RESULT_REQUEST_PROCESSED.get_key_id()) + } } #[derive(Clone, Copy)] @@ -342,6 +342,6 @@ pub struct MutableIsRequestProcessedResults { impl MutableIsRequestProcessedResults { pub fn request_processed(&self) -> ScMutableString { - ScMutableString::new(self.id, RESULT_REQUEST_PROCESSED.get_key_id()) - } + ScMutableString::new(self.id, RESULT_REQUEST_PROCESSED.get_key_id()) + } } diff --git a/packages/vm/wasmlib/src/coregovernance/consts.rs b/packages/vm/wasmlib/src/coregovernance/consts.rs index 01d676af06..69059554b2 100644 --- a/packages/vm/wasmlib/src/coregovernance/consts.rs +++ b/packages/vm/wasmlib/src/coregovernance/consts.rs @@ -5,63 +5,59 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use crate::*; -pub const SC_NAME: &str = "governance"; -pub const SC_DESCRIPTION: &str = "Core governance contract"; -pub const HSC_NAME: ScHname = ScHname(0x17cf909f); - -pub(crate) const PARAM_CHAIN_OWNER: &str = "oi"; -pub(crate) const PARAM_FEE_COLOR: &str = "fc"; -pub(crate) const PARAM_HNAME: &str = "hn"; -pub(crate) const PARAM_MAX_BLOB_SIZE: &str = "bs"; -pub(crate) const PARAM_MAX_EVENT_SIZE: &str = "es"; -pub(crate) const PARAM_MAX_EVENTS_PER_REQ: &str = "ne"; -pub(crate) const PARAM_OWNER_FEE: &str = "of"; -pub(crate) const PARAM_STATE_CONTROLLER_ADDRESS: &str = "S"; -pub(crate) const PARAM_VALIDATOR_FEE: &str = "vf"; - -pub(crate) const RESULT_ALLOWED_STATE_CONTROLLER_ADDRESSES: &str = "a"; -pub(crate) const RESULT_CHAIN_ID: &str = "c"; -pub(crate) const RESULT_CHAIN_OWNER_ID: &str = "o"; -pub(crate) const RESULT_DEFAULT_OWNER_FEE: &str = "do"; -pub(crate) const RESULT_DEFAULT_VALIDATOR_FEE: &str = "dv"; -pub(crate) const RESULT_DESCRIPTION: &str = "d"; -pub(crate) const RESULT_FEE_COLOR: &str = "f"; -pub(crate) const RESULT_MAX_BLOB_SIZE: &str = "mb"; -pub(crate) const RESULT_MAX_EVENT_SIZE: &str = "me"; -pub(crate) const RESULT_MAX_EVENTS_PER_REQ: &str = "mr"; -pub(crate) const RESULT_OWNER_FEE: &str = "of"; -pub(crate) const RESULT_VALIDATOR_FEE: &str = "vf"; - -pub(crate) const FUNC_ADD_ALLOWED_STATE_CONTROLLER_ADDRESS: &str = "addAllowedStateControllerAddress"; -pub(crate) const FUNC_CLAIM_CHAIN_OWNERSHIP: &str = "claimChainOwnership"; -pub(crate) const FUNC_DELEGATE_CHAIN_OWNERSHIP: &str = "delegateChainOwnership"; -pub(crate) const FUNC_REMOVE_ALLOWED_STATE_CONTROLLER_ADDRESS: &str = "removeAllowedStateControllerAddress"; -pub(crate) const FUNC_ROTATE_STATE_CONTROLLER: &str = "rotateStateController"; -pub(crate) const FUNC_SET_CHAIN_INFO: &str = "setChainInfo"; -pub(crate) const FUNC_SET_CONTRACT_FEE: &str = "setContractFee"; -pub(crate) const FUNC_SET_DEFAULT_FEE: &str = "setDefaultFee"; -pub(crate) const VIEW_GET_ALLOWED_STATE_CONTROLLER_ADDRESSES: &str = "getAllowedStateControllerAddresses"; -pub(crate) const VIEW_GET_CHAIN_INFO: &str = "getChainInfo"; -pub(crate) const VIEW_GET_FEE_INFO: &str = "getFeeInfo"; -pub(crate) const VIEW_GET_MAX_BLOB_SIZE: &str = "getMaxBlobSize"; - -pub(crate) const HFUNC_ADD_ALLOWED_STATE_CONTROLLER_ADDRESS: ScHname = ScHname(0x9469d567); -pub(crate) const HFUNC_CLAIM_CHAIN_OWNERSHIP: ScHname = ScHname(0x03ff0fc0); -pub(crate) const HFUNC_DELEGATE_CHAIN_OWNERSHIP: ScHname = ScHname(0x93ecb6ad); -pub(crate) const HFUNC_REMOVE_ALLOWED_STATE_CONTROLLER_ADDRESS: ScHname = ScHname(0x31f69447); -pub(crate) const HFUNC_ROTATE_STATE_CONTROLLER: ScHname = ScHname(0x244d1038); -pub(crate) const HFUNC_SET_CHAIN_INFO: ScHname = ScHname(0x702f5d2b); -pub(crate) const HFUNC_SET_CONTRACT_FEE: ScHname = ScHname(0x8421a42b); -pub(crate) const HFUNC_SET_DEFAULT_FEE: ScHname = ScHname(0x3310ecd0); -pub(crate) const HVIEW_GET_ALLOWED_STATE_CONTROLLER_ADDRESSES: ScHname = ScHname(0xf3505183); -pub(crate) const HVIEW_GET_CHAIN_INFO: ScHname = ScHname(0x434477e2); -pub(crate) const HVIEW_GET_FEE_INFO: ScHname = ScHname(0x9fe54b48); -pub(crate) const HVIEW_GET_MAX_BLOB_SIZE: ScHname = ScHname(0xe1db3d28); - -// @formatter:on +pub const SC_NAME : &str = "governance"; +pub const SC_DESCRIPTION : &str = "Core governance contract"; +pub const HSC_NAME : ScHname = ScHname(0x17cf909f); + +pub(crate) const PARAM_CHAIN_OWNER : &str = "oi"; +pub(crate) const PARAM_FEE_COLOR : &str = "fc"; +pub(crate) const PARAM_HNAME : &str = "hn"; +pub(crate) const PARAM_MAX_BLOB_SIZE : &str = "bs"; +pub(crate) const PARAM_MAX_EVENT_SIZE : &str = "es"; +pub(crate) const PARAM_MAX_EVENTS_PER_REQ : &str = "ne"; +pub(crate) const PARAM_OWNER_FEE : &str = "of"; +pub(crate) const PARAM_STATE_CONTROLLER_ADDRESS : &str = "S"; +pub(crate) const PARAM_VALIDATOR_FEE : &str = "vf"; + +pub(crate) const RESULT_ALLOWED_STATE_CONTROLLER_ADDRESSES : &str = "a"; +pub(crate) const RESULT_CHAIN_ID : &str = "c"; +pub(crate) const RESULT_CHAIN_OWNER_ID : &str = "o"; +pub(crate) const RESULT_DEFAULT_OWNER_FEE : &str = "do"; +pub(crate) const RESULT_DEFAULT_VALIDATOR_FEE : &str = "dv"; +pub(crate) const RESULT_DESCRIPTION : &str = "d"; +pub(crate) const RESULT_FEE_COLOR : &str = "f"; +pub(crate) const RESULT_MAX_BLOB_SIZE : &str = "mb"; +pub(crate) const RESULT_MAX_EVENT_SIZE : &str = "me"; +pub(crate) const RESULT_MAX_EVENTS_PER_REQ : &str = "mr"; +pub(crate) const RESULT_OWNER_FEE : &str = "of"; +pub(crate) const RESULT_VALIDATOR_FEE : &str = "vf"; + +pub(crate) const FUNC_ADD_ALLOWED_STATE_CONTROLLER_ADDRESS : &str = "addAllowedStateControllerAddress"; +pub(crate) const FUNC_CLAIM_CHAIN_OWNERSHIP : &str = "claimChainOwnership"; +pub(crate) const FUNC_DELEGATE_CHAIN_OWNERSHIP : &str = "delegateChainOwnership"; +pub(crate) const FUNC_REMOVE_ALLOWED_STATE_CONTROLLER_ADDRESS : &str = "removeAllowedStateControllerAddress"; +pub(crate) const FUNC_ROTATE_STATE_CONTROLLER : &str = "rotateStateController"; +pub(crate) const FUNC_SET_CHAIN_INFO : &str = "setChainInfo"; +pub(crate) const FUNC_SET_CONTRACT_FEE : &str = "setContractFee"; +pub(crate) const FUNC_SET_DEFAULT_FEE : &str = "setDefaultFee"; +pub(crate) const VIEW_GET_ALLOWED_STATE_CONTROLLER_ADDRESSES : &str = "getAllowedStateControllerAddresses"; +pub(crate) const VIEW_GET_CHAIN_INFO : &str = "getChainInfo"; +pub(crate) const VIEW_GET_FEE_INFO : &str = "getFeeInfo"; +pub(crate) const VIEW_GET_MAX_BLOB_SIZE : &str = "getMaxBlobSize"; + +pub(crate) const HFUNC_ADD_ALLOWED_STATE_CONTROLLER_ADDRESS : ScHname = ScHname(0x9469d567); +pub(crate) const HFUNC_CLAIM_CHAIN_OWNERSHIP : ScHname = ScHname(0x03ff0fc0); +pub(crate) const HFUNC_DELEGATE_CHAIN_OWNERSHIP : ScHname = ScHname(0x93ecb6ad); +pub(crate) const HFUNC_REMOVE_ALLOWED_STATE_CONTROLLER_ADDRESS : ScHname = ScHname(0x31f69447); +pub(crate) const HFUNC_ROTATE_STATE_CONTROLLER : ScHname = ScHname(0x244d1038); +pub(crate) const HFUNC_SET_CHAIN_INFO : ScHname = ScHname(0x702f5d2b); +pub(crate) const HFUNC_SET_CONTRACT_FEE : ScHname = ScHname(0x8421a42b); +pub(crate) const HFUNC_SET_DEFAULT_FEE : ScHname = ScHname(0x3310ecd0); +pub(crate) const HVIEW_GET_ALLOWED_STATE_CONTROLLER_ADDRESSES : ScHname = ScHname(0xf3505183); +pub(crate) const HVIEW_GET_CHAIN_INFO : ScHname = ScHname(0x434477e2); +pub(crate) const HVIEW_GET_FEE_INFO : ScHname = ScHname(0x9fe54b48); +pub(crate) const HVIEW_GET_MAX_BLOB_SIZE : ScHname = ScHname(0xe1db3d28); diff --git a/packages/vm/wasmlib/src/coregovernance/contract.rs b/packages/vm/wasmlib/src/coregovernance/contract.rs index 7fa127cb43..333b15d675 100644 --- a/packages/vm/wasmlib/src/coregovernance/contract.rs +++ b/packages/vm/wasmlib/src/coregovernance/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -15,63 +13,63 @@ use crate::*; use crate::coregovernance::*; pub struct AddAllowedStateControllerAddressCall { - pub func: ScFunc, - pub params: MutableAddAllowedStateControllerAddressParams, + pub func: ScFunc, + pub params: MutableAddAllowedStateControllerAddressParams, } pub struct ClaimChainOwnershipCall { - pub func: ScFunc, + pub func: ScFunc, } pub struct DelegateChainOwnershipCall { - pub func: ScFunc, - pub params: MutableDelegateChainOwnershipParams, + pub func: ScFunc, + pub params: MutableDelegateChainOwnershipParams, } pub struct RemoveAllowedStateControllerAddressCall { - pub func: ScFunc, - pub params: MutableRemoveAllowedStateControllerAddressParams, + pub func: ScFunc, + pub params: MutableRemoveAllowedStateControllerAddressParams, } pub struct RotateStateControllerCall { - pub func: ScFunc, - pub params: MutableRotateStateControllerParams, + pub func: ScFunc, + pub params: MutableRotateStateControllerParams, } pub struct SetChainInfoCall { - pub func: ScFunc, - pub params: MutableSetChainInfoParams, + pub func: ScFunc, + pub params: MutableSetChainInfoParams, } pub struct SetContractFeeCall { - pub func: ScFunc, - pub params: MutableSetContractFeeParams, + pub func: ScFunc, + pub params: MutableSetContractFeeParams, } pub struct SetDefaultFeeCall { - pub func: ScFunc, - pub params: MutableSetDefaultFeeParams, + pub func: ScFunc, + pub params: MutableSetDefaultFeeParams, } pub struct GetAllowedStateControllerAddressesCall { - pub func: ScView, - pub results: ImmutableGetAllowedStateControllerAddressesResults, + pub func: ScView, + pub results: ImmutableGetAllowedStateControllerAddressesResults, } pub struct GetChainInfoCall { - pub func: ScView, - pub results: ImmutableGetChainInfoResults, + pub func: ScView, + pub results: ImmutableGetChainInfoResults, } pub struct GetFeeInfoCall { - pub func: ScView, - pub params: MutableGetFeeInfoParams, - pub results: ImmutableGetFeeInfoResults, + pub func: ScView, + pub params: MutableGetFeeInfoParams, + pub results: ImmutableGetFeeInfoResults, } pub struct GetMaxBlobSizeCall { - pub func: ScView, - pub results: ImmutableGetMaxBlobSizeResults, + pub func: ScView, + pub results: ImmutableGetMaxBlobSizeResults, } pub struct ScFuncs { @@ -80,98 +78,107 @@ pub struct ScFuncs { impl ScFuncs { pub fn add_allowed_state_controller_address(_ctx: & dyn ScFuncCallContext) -> AddAllowedStateControllerAddressCall { let mut f = AddAllowedStateControllerAddressCall { - func: ScFunc::new(HSC_NAME, HFUNC_ADD_ALLOWED_STATE_CONTROLLER_ADDRESS), + func: ScFunc::new(HSC_NAME, HFUNC_ADD_ALLOWED_STATE_CONTROLLER_ADDRESS), params: MutableAddAllowedStateControllerAddressParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn claim_chain_ownership(_ctx: & dyn ScFuncCallContext) -> ClaimChainOwnershipCall { ClaimChainOwnershipCall { func: ScFunc::new(HSC_NAME, HFUNC_CLAIM_CHAIN_OWNERSHIP), } } + pub fn delegate_chain_ownership(_ctx: & dyn ScFuncCallContext) -> DelegateChainOwnershipCall { let mut f = DelegateChainOwnershipCall { - func: ScFunc::new(HSC_NAME, HFUNC_DELEGATE_CHAIN_OWNERSHIP), + func: ScFunc::new(HSC_NAME, HFUNC_DELEGATE_CHAIN_OWNERSHIP), params: MutableDelegateChainOwnershipParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn remove_allowed_state_controller_address(_ctx: & dyn ScFuncCallContext) -> RemoveAllowedStateControllerAddressCall { let mut f = RemoveAllowedStateControllerAddressCall { - func: ScFunc::new(HSC_NAME, HFUNC_REMOVE_ALLOWED_STATE_CONTROLLER_ADDRESS), + func: ScFunc::new(HSC_NAME, HFUNC_REMOVE_ALLOWED_STATE_CONTROLLER_ADDRESS), params: MutableRemoveAllowedStateControllerAddressParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn rotate_state_controller(_ctx: & dyn ScFuncCallContext) -> RotateStateControllerCall { let mut f = RotateStateControllerCall { - func: ScFunc::new(HSC_NAME, HFUNC_ROTATE_STATE_CONTROLLER), + func: ScFunc::new(HSC_NAME, HFUNC_ROTATE_STATE_CONTROLLER), params: MutableRotateStateControllerParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn set_chain_info(_ctx: & dyn ScFuncCallContext) -> SetChainInfoCall { let mut f = SetChainInfoCall { - func: ScFunc::new(HSC_NAME, HFUNC_SET_CHAIN_INFO), + func: ScFunc::new(HSC_NAME, HFUNC_SET_CHAIN_INFO), params: MutableSetChainInfoParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn set_contract_fee(_ctx: & dyn ScFuncCallContext) -> SetContractFeeCall { let mut f = SetContractFeeCall { - func: ScFunc::new(HSC_NAME, HFUNC_SET_CONTRACT_FEE), + func: ScFunc::new(HSC_NAME, HFUNC_SET_CONTRACT_FEE), params: MutableSetContractFeeParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn set_default_fee(_ctx: & dyn ScFuncCallContext) -> SetDefaultFeeCall { let mut f = SetDefaultFeeCall { - func: ScFunc::new(HSC_NAME, HFUNC_SET_DEFAULT_FEE), + func: ScFunc::new(HSC_NAME, HFUNC_SET_DEFAULT_FEE), params: MutableSetDefaultFeeParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn get_allowed_state_controller_addresses(_ctx: & dyn ScViewCallContext) -> GetAllowedStateControllerAddressesCall { let mut f = GetAllowedStateControllerAddressesCall { - func: ScView::new(HSC_NAME, HVIEW_GET_ALLOWED_STATE_CONTROLLER_ADDRESSES), + func: ScView::new(HSC_NAME, HVIEW_GET_ALLOWED_STATE_CONTROLLER_ADDRESSES), results: ImmutableGetAllowedStateControllerAddressesResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn get_chain_info(_ctx: & dyn ScViewCallContext) -> GetChainInfoCall { let mut f = GetChainInfoCall { - func: ScView::new(HSC_NAME, HVIEW_GET_CHAIN_INFO), + func: ScView::new(HSC_NAME, HVIEW_GET_CHAIN_INFO), results: ImmutableGetChainInfoResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } + pub fn get_fee_info(_ctx: & dyn ScViewCallContext) -> GetFeeInfoCall { let mut f = GetFeeInfoCall { - func: ScView::new(HSC_NAME, HVIEW_GET_FEE_INFO), - params: MutableGetFeeInfoParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_GET_FEE_INFO), + params: MutableGetFeeInfoParams { id: 0 }, results: ImmutableGetFeeInfoResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_max_blob_size(_ctx: & dyn ScViewCallContext) -> GetMaxBlobSizeCall { let mut f = GetMaxBlobSizeCall { - func: ScView::new(HSC_NAME, HVIEW_GET_MAX_BLOB_SIZE), + func: ScView::new(HSC_NAME, HVIEW_GET_MAX_BLOB_SIZE), results: ImmutableGetMaxBlobSizeResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/packages/vm/wasmlib/src/coregovernance/params.rs b/packages/vm/wasmlib/src/coregovernance/params.rs index 0e80984554..e995d10b14 100644 --- a/packages/vm/wasmlib/src/coregovernance/params.rs +++ b/packages/vm/wasmlib/src/coregovernance/params.rs @@ -19,16 +19,16 @@ pub struct ImmutableAddAllowedStateControllerAddressParams { impl ImmutableAddAllowedStateControllerAddressParams { pub fn chain_owner(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, PARAM_CHAIN_OWNER.get_key_id()) - } + ScImmutableAgentID::new(self.id, PARAM_CHAIN_OWNER.get_key_id()) + } pub fn fee_color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, PARAM_FEE_COLOR.get_key_id()) - } + ScImmutableColor::new(self.id, PARAM_FEE_COLOR.get_key_id()) + } pub fn state_controller_address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) - } + ScImmutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) + } } #[derive(Clone, Copy)] @@ -38,16 +38,16 @@ pub struct MutableAddAllowedStateControllerAddressParams { impl MutableAddAllowedStateControllerAddressParams { pub fn chain_owner(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, PARAM_CHAIN_OWNER.get_key_id()) - } + ScMutableAgentID::new(self.id, PARAM_CHAIN_OWNER.get_key_id()) + } pub fn fee_color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, PARAM_FEE_COLOR.get_key_id()) - } + ScMutableColor::new(self.id, PARAM_FEE_COLOR.get_key_id()) + } pub fn state_controller_address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) - } + ScMutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) + } } #[derive(Clone, Copy)] @@ -57,8 +57,8 @@ pub struct ImmutableDelegateChainOwnershipParams { impl ImmutableDelegateChainOwnershipParams { pub fn chain_owner(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, PARAM_CHAIN_OWNER.get_key_id()) - } + ScImmutableAgentID::new(self.id, PARAM_CHAIN_OWNER.get_key_id()) + } } #[derive(Clone, Copy)] @@ -68,8 +68,8 @@ pub struct MutableDelegateChainOwnershipParams { impl MutableDelegateChainOwnershipParams { pub fn chain_owner(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, PARAM_CHAIN_OWNER.get_key_id()) - } + ScMutableAgentID::new(self.id, PARAM_CHAIN_OWNER.get_key_id()) + } } #[derive(Clone, Copy)] @@ -79,8 +79,8 @@ pub struct ImmutableRemoveAllowedStateControllerAddressParams { impl ImmutableRemoveAllowedStateControllerAddressParams { pub fn state_controller_address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) - } + ScImmutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) + } } #[derive(Clone, Copy)] @@ -90,8 +90,8 @@ pub struct MutableRemoveAllowedStateControllerAddressParams { impl MutableRemoveAllowedStateControllerAddressParams { pub fn state_controller_address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) - } + ScMutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) + } } #[derive(Clone, Copy)] @@ -101,8 +101,8 @@ pub struct ImmutableRotateStateControllerParams { impl ImmutableRotateStateControllerParams { pub fn state_controller_address(&self) -> ScImmutableAddress { - ScImmutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) - } + ScImmutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) + } } #[derive(Clone, Copy)] @@ -112,8 +112,8 @@ pub struct MutableRotateStateControllerParams { impl MutableRotateStateControllerParams { pub fn state_controller_address(&self) -> ScMutableAddress { - ScMutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) - } + ScMutableAddress::new(self.id, PARAM_STATE_CONTROLLER_ADDRESS.get_key_id()) + } } #[derive(Clone, Copy)] @@ -123,24 +123,24 @@ pub struct ImmutableSetChainInfoParams { impl ImmutableSetChainInfoParams { pub fn max_blob_size(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, PARAM_MAX_BLOB_SIZE.get_key_id()) - } + ScImmutableInt32::new(self.id, PARAM_MAX_BLOB_SIZE.get_key_id()) + } pub fn max_event_size(&self) -> ScImmutableInt16 { - ScImmutableInt16::new(self.id, PARAM_MAX_EVENT_SIZE.get_key_id()) - } + ScImmutableInt16::new(self.id, PARAM_MAX_EVENT_SIZE.get_key_id()) + } pub fn max_events_per_req(&self) -> ScImmutableInt16 { - ScImmutableInt16::new(self.id, PARAM_MAX_EVENTS_PER_REQ.get_key_id()) - } + ScImmutableInt16::new(self.id, PARAM_MAX_EVENTS_PER_REQ.get_key_id()) + } pub fn owner_fee(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) - } + ScImmutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) + } pub fn validator_fee(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) - } + ScImmutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) + } } #[derive(Clone, Copy)] @@ -150,24 +150,24 @@ pub struct MutableSetChainInfoParams { impl MutableSetChainInfoParams { pub fn max_blob_size(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, PARAM_MAX_BLOB_SIZE.get_key_id()) - } + ScMutableInt32::new(self.id, PARAM_MAX_BLOB_SIZE.get_key_id()) + } pub fn max_event_size(&self) -> ScMutableInt16 { - ScMutableInt16::new(self.id, PARAM_MAX_EVENT_SIZE.get_key_id()) - } + ScMutableInt16::new(self.id, PARAM_MAX_EVENT_SIZE.get_key_id()) + } pub fn max_events_per_req(&self) -> ScMutableInt16 { - ScMutableInt16::new(self.id, PARAM_MAX_EVENTS_PER_REQ.get_key_id()) - } + ScMutableInt16::new(self.id, PARAM_MAX_EVENTS_PER_REQ.get_key_id()) + } pub fn owner_fee(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) - } + ScMutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) + } pub fn validator_fee(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) - } + ScMutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) + } } #[derive(Clone, Copy)] @@ -177,16 +177,16 @@ pub struct ImmutableSetContractFeeParams { impl ImmutableSetContractFeeParams { pub fn hname(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, PARAM_HNAME.get_key_id()) - } + ScImmutableHname::new(self.id, PARAM_HNAME.get_key_id()) + } pub fn owner_fee(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) - } + ScImmutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) + } pub fn validator_fee(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) - } + ScImmutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) + } } #[derive(Clone, Copy)] @@ -196,16 +196,16 @@ pub struct MutableSetContractFeeParams { impl MutableSetContractFeeParams { pub fn hname(&self) -> ScMutableHname { - ScMutableHname::new(self.id, PARAM_HNAME.get_key_id()) - } + ScMutableHname::new(self.id, PARAM_HNAME.get_key_id()) + } pub fn owner_fee(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) - } + ScMutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) + } pub fn validator_fee(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) - } + ScMutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) + } } #[derive(Clone, Copy)] @@ -215,12 +215,12 @@ pub struct ImmutableSetDefaultFeeParams { impl ImmutableSetDefaultFeeParams { pub fn owner_fee(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) - } + ScImmutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) + } pub fn validator_fee(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) - } + ScImmutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) + } } #[derive(Clone, Copy)] @@ -230,12 +230,12 @@ pub struct MutableSetDefaultFeeParams { impl MutableSetDefaultFeeParams { pub fn owner_fee(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) - } + ScMutableInt64::new(self.id, PARAM_OWNER_FEE.get_key_id()) + } pub fn validator_fee(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) - } + ScMutableInt64::new(self.id, PARAM_VALIDATOR_FEE.get_key_id()) + } } #[derive(Clone, Copy)] @@ -245,8 +245,8 @@ pub struct ImmutableGetFeeInfoParams { impl ImmutableGetFeeInfoParams { pub fn hname(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, PARAM_HNAME.get_key_id()) - } + ScImmutableHname::new(self.id, PARAM_HNAME.get_key_id()) + } } #[derive(Clone, Copy)] @@ -256,6 +256,6 @@ pub struct MutableGetFeeInfoParams { impl MutableGetFeeInfoParams { pub fn hname(&self) -> ScMutableHname { - ScMutableHname::new(self.id, PARAM_HNAME.get_key_id()) - } + ScMutableHname::new(self.id, PARAM_HNAME.get_key_id()) + } } diff --git a/packages/vm/wasmlib/src/coregovernance/results.rs b/packages/vm/wasmlib/src/coregovernance/results.rs index 486dc86988..0c5e2c9709 100644 --- a/packages/vm/wasmlib/src/coregovernance/results.rs +++ b/packages/vm/wasmlib/src/coregovernance/results.rs @@ -13,7 +13,7 @@ use crate::coregovernance::*; use crate::host::*; pub struct ArrayOfImmutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfImmutableBytes { @@ -33,13 +33,13 @@ pub struct ImmutableGetAllowedStateControllerAddressesResults { impl ImmutableGetAllowedStateControllerAddressesResults { pub fn allowed_state_controller_addresses(&self) -> ArrayOfImmutableBytes { - let arr_id = get_object_id(self.id, RESULT_ALLOWED_STATE_CONTROLLER_ADDRESSES.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); - ArrayOfImmutableBytes { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_ALLOWED_STATE_CONTROLLER_ADDRESSES.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); + ArrayOfImmutableBytes { obj_id: arr_id } + } } pub struct ArrayOfMutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl ArrayOfMutableBytes { @@ -63,9 +63,9 @@ pub struct MutableGetAllowedStateControllerAddressesResults { impl MutableGetAllowedStateControllerAddressesResults { pub fn allowed_state_controller_addresses(&self) -> ArrayOfMutableBytes { - let arr_id = get_object_id(self.id, RESULT_ALLOWED_STATE_CONTROLLER_ADDRESSES.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); - ArrayOfMutableBytes { obj_id: arr_id } - } + let arr_id = get_object_id(self.id, RESULT_ALLOWED_STATE_CONTROLLER_ADDRESSES.get_key_id(), TYPE_ARRAY16 | TYPE_BYTES); + ArrayOfMutableBytes { obj_id: arr_id } + } } #[derive(Clone, Copy)] @@ -75,40 +75,40 @@ pub struct ImmutableGetChainInfoResults { impl ImmutableGetChainInfoResults { pub fn chain_id(&self) -> ScImmutableChainID { - ScImmutableChainID::new(self.id, RESULT_CHAIN_ID.get_key_id()) - } + ScImmutableChainID::new(self.id, RESULT_CHAIN_ID.get_key_id()) + } pub fn chain_owner_id(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, RESULT_CHAIN_OWNER_ID.get_key_id()) - } + ScImmutableAgentID::new(self.id, RESULT_CHAIN_OWNER_ID.get_key_id()) + } pub fn default_owner_fee(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, RESULT_DEFAULT_OWNER_FEE.get_key_id()) - } + ScImmutableInt64::new(self.id, RESULT_DEFAULT_OWNER_FEE.get_key_id()) + } pub fn default_validator_fee(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, RESULT_DEFAULT_VALIDATOR_FEE.get_key_id()) - } + ScImmutableInt64::new(self.id, RESULT_DEFAULT_VALIDATOR_FEE.get_key_id()) + } pub fn description(&self) -> ScImmutableString { - ScImmutableString::new(self.id, RESULT_DESCRIPTION.get_key_id()) - } + ScImmutableString::new(self.id, RESULT_DESCRIPTION.get_key_id()) + } pub fn fee_color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, RESULT_FEE_COLOR.get_key_id()) - } + ScImmutableColor::new(self.id, RESULT_FEE_COLOR.get_key_id()) + } pub fn max_blob_size(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, RESULT_MAX_BLOB_SIZE.get_key_id()) - } + ScImmutableInt32::new(self.id, RESULT_MAX_BLOB_SIZE.get_key_id()) + } pub fn max_event_size(&self) -> ScImmutableInt16 { - ScImmutableInt16::new(self.id, RESULT_MAX_EVENT_SIZE.get_key_id()) - } + ScImmutableInt16::new(self.id, RESULT_MAX_EVENT_SIZE.get_key_id()) + } pub fn max_events_per_req(&self) -> ScImmutableInt16 { - ScImmutableInt16::new(self.id, RESULT_MAX_EVENTS_PER_REQ.get_key_id()) - } + ScImmutableInt16::new(self.id, RESULT_MAX_EVENTS_PER_REQ.get_key_id()) + } } #[derive(Clone, Copy)] @@ -118,40 +118,40 @@ pub struct MutableGetChainInfoResults { impl MutableGetChainInfoResults { pub fn chain_id(&self) -> ScMutableChainID { - ScMutableChainID::new(self.id, RESULT_CHAIN_ID.get_key_id()) - } + ScMutableChainID::new(self.id, RESULT_CHAIN_ID.get_key_id()) + } pub fn chain_owner_id(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, RESULT_CHAIN_OWNER_ID.get_key_id()) - } + ScMutableAgentID::new(self.id, RESULT_CHAIN_OWNER_ID.get_key_id()) + } pub fn default_owner_fee(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, RESULT_DEFAULT_OWNER_FEE.get_key_id()) - } + ScMutableInt64::new(self.id, RESULT_DEFAULT_OWNER_FEE.get_key_id()) + } pub fn default_validator_fee(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, RESULT_DEFAULT_VALIDATOR_FEE.get_key_id()) - } + ScMutableInt64::new(self.id, RESULT_DEFAULT_VALIDATOR_FEE.get_key_id()) + } pub fn description(&self) -> ScMutableString { - ScMutableString::new(self.id, RESULT_DESCRIPTION.get_key_id()) - } + ScMutableString::new(self.id, RESULT_DESCRIPTION.get_key_id()) + } pub fn fee_color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, RESULT_FEE_COLOR.get_key_id()) - } + ScMutableColor::new(self.id, RESULT_FEE_COLOR.get_key_id()) + } pub fn max_blob_size(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, RESULT_MAX_BLOB_SIZE.get_key_id()) - } + ScMutableInt32::new(self.id, RESULT_MAX_BLOB_SIZE.get_key_id()) + } pub fn max_event_size(&self) -> ScMutableInt16 { - ScMutableInt16::new(self.id, RESULT_MAX_EVENT_SIZE.get_key_id()) - } + ScMutableInt16::new(self.id, RESULT_MAX_EVENT_SIZE.get_key_id()) + } pub fn max_events_per_req(&self) -> ScMutableInt16 { - ScMutableInt16::new(self.id, RESULT_MAX_EVENTS_PER_REQ.get_key_id()) - } + ScMutableInt16::new(self.id, RESULT_MAX_EVENTS_PER_REQ.get_key_id()) + } } #[derive(Clone, Copy)] @@ -161,16 +161,16 @@ pub struct ImmutableGetFeeInfoResults { impl ImmutableGetFeeInfoResults { pub fn fee_color(&self) -> ScImmutableColor { - ScImmutableColor::new(self.id, RESULT_FEE_COLOR.get_key_id()) - } + ScImmutableColor::new(self.id, RESULT_FEE_COLOR.get_key_id()) + } pub fn owner_fee(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, RESULT_OWNER_FEE.get_key_id()) - } + ScImmutableInt64::new(self.id, RESULT_OWNER_FEE.get_key_id()) + } pub fn validator_fee(&self) -> ScImmutableInt64 { - ScImmutableInt64::new(self.id, RESULT_VALIDATOR_FEE.get_key_id()) - } + ScImmutableInt64::new(self.id, RESULT_VALIDATOR_FEE.get_key_id()) + } } #[derive(Clone, Copy)] @@ -180,16 +180,16 @@ pub struct MutableGetFeeInfoResults { impl MutableGetFeeInfoResults { pub fn fee_color(&self) -> ScMutableColor { - ScMutableColor::new(self.id, RESULT_FEE_COLOR.get_key_id()) - } + ScMutableColor::new(self.id, RESULT_FEE_COLOR.get_key_id()) + } pub fn owner_fee(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, RESULT_OWNER_FEE.get_key_id()) - } + ScMutableInt64::new(self.id, RESULT_OWNER_FEE.get_key_id()) + } pub fn validator_fee(&self) -> ScMutableInt64 { - ScMutableInt64::new(self.id, RESULT_VALIDATOR_FEE.get_key_id()) - } + ScMutableInt64::new(self.id, RESULT_VALIDATOR_FEE.get_key_id()) + } } #[derive(Clone, Copy)] @@ -199,8 +199,8 @@ pub struct ImmutableGetMaxBlobSizeResults { impl ImmutableGetMaxBlobSizeResults { pub fn max_blob_size(&self) -> ScImmutableInt32 { - ScImmutableInt32::new(self.id, RESULT_MAX_BLOB_SIZE.get_key_id()) - } + ScImmutableInt32::new(self.id, RESULT_MAX_BLOB_SIZE.get_key_id()) + } } #[derive(Clone, Copy)] @@ -210,6 +210,6 @@ pub struct MutableGetMaxBlobSizeResults { impl MutableGetMaxBlobSizeResults { pub fn max_blob_size(&self) -> ScMutableInt32 { - ScMutableInt32::new(self.id, RESULT_MAX_BLOB_SIZE.get_key_id()) - } + ScMutableInt32::new(self.id, RESULT_MAX_BLOB_SIZE.get_key_id()) + } } diff --git a/packages/vm/wasmlib/src/coreroot/consts.rs b/packages/vm/wasmlib/src/coreroot/consts.rs index 567e71665a..6644fc38a1 100644 --- a/packages/vm/wasmlib/src/coreroot/consts.rs +++ b/packages/vm/wasmlib/src/coreroot/consts.rs @@ -5,36 +5,32 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use crate::*; -pub const SC_NAME: &str = "root"; -pub const SC_DESCRIPTION: &str = "Core root contract"; -pub const HSC_NAME: ScHname = ScHname(0xcebf5908); - -pub(crate) const PARAM_DEPLOYER: &str = "dp"; -pub(crate) const PARAM_DESCRIPTION: &str = "ds"; -pub(crate) const PARAM_HNAME: &str = "hn"; -pub(crate) const PARAM_NAME: &str = "nm"; -pub(crate) const PARAM_PROGRAM_HASH: &str = "ph"; - -pub(crate) const RESULT_CONTRACT_FOUND: &str = "cf"; -pub(crate) const RESULT_CONTRACT_REC_DATA: &str = "dt"; -pub(crate) const RESULT_CONTRACT_REGISTRY: &str = "r"; - -pub(crate) const FUNC_DEPLOY_CONTRACT: &str = "deployContract"; -pub(crate) const FUNC_GRANT_DEPLOY_PERMISSION: &str = "grantDeployPermission"; -pub(crate) const FUNC_REVOKE_DEPLOY_PERMISSION: &str = "revokeDeployPermission"; -pub(crate) const VIEW_FIND_CONTRACT: &str = "findContract"; -pub(crate) const VIEW_GET_CONTRACT_RECORDS: &str = "getContractRecords"; - -pub(crate) const HFUNC_DEPLOY_CONTRACT: ScHname = ScHname(0x28232c27); -pub(crate) const HFUNC_GRANT_DEPLOY_PERMISSION: ScHname = ScHname(0xf440263a); -pub(crate) const HFUNC_REVOKE_DEPLOY_PERMISSION: ScHname = ScHname(0x850744f1); -pub(crate) const HVIEW_FIND_CONTRACT: ScHname = ScHname(0xc145ca00); -pub(crate) const HVIEW_GET_CONTRACT_RECORDS: ScHname = ScHname(0x078b3ef3); - -// @formatter:on +pub const SC_NAME : &str = "root"; +pub const SC_DESCRIPTION : &str = "Core root contract"; +pub const HSC_NAME : ScHname = ScHname(0xcebf5908); + +pub(crate) const PARAM_DEPLOYER : &str = "dp"; +pub(crate) const PARAM_DESCRIPTION : &str = "ds"; +pub(crate) const PARAM_HNAME : &str = "hn"; +pub(crate) const PARAM_NAME : &str = "nm"; +pub(crate) const PARAM_PROGRAM_HASH : &str = "ph"; + +pub(crate) const RESULT_CONTRACT_FOUND : &str = "cf"; +pub(crate) const RESULT_CONTRACT_REC_DATA : &str = "dt"; +pub(crate) const RESULT_CONTRACT_REGISTRY : &str = "r"; + +pub(crate) const FUNC_DEPLOY_CONTRACT : &str = "deployContract"; +pub(crate) const FUNC_GRANT_DEPLOY_PERMISSION : &str = "grantDeployPermission"; +pub(crate) const FUNC_REVOKE_DEPLOY_PERMISSION : &str = "revokeDeployPermission"; +pub(crate) const VIEW_FIND_CONTRACT : &str = "findContract"; +pub(crate) const VIEW_GET_CONTRACT_RECORDS : &str = "getContractRecords"; + +pub(crate) const HFUNC_DEPLOY_CONTRACT : ScHname = ScHname(0x28232c27); +pub(crate) const HFUNC_GRANT_DEPLOY_PERMISSION : ScHname = ScHname(0xf440263a); +pub(crate) const HFUNC_REVOKE_DEPLOY_PERMISSION : ScHname = ScHname(0x850744f1); +pub(crate) const HVIEW_FIND_CONTRACT : ScHname = ScHname(0xc145ca00); +pub(crate) const HVIEW_GET_CONTRACT_RECORDS : ScHname = ScHname(0x078b3ef3); diff --git a/packages/vm/wasmlib/src/coreroot/contract.rs b/packages/vm/wasmlib/src/coreroot/contract.rs index fe9ba90cdc..99fb71ce4c 100644 --- a/packages/vm/wasmlib/src/coreroot/contract.rs +++ b/packages/vm/wasmlib/src/coreroot/contract.rs @@ -5,8 +5,6 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -// @formatter:off - #![allow(dead_code)] use std::ptr; @@ -15,29 +13,29 @@ use crate::*; use crate::coreroot::*; pub struct DeployContractCall { - pub func: ScFunc, - pub params: MutableDeployContractParams, + pub func: ScFunc, + pub params: MutableDeployContractParams, } pub struct GrantDeployPermissionCall { - pub func: ScFunc, - pub params: MutableGrantDeployPermissionParams, + pub func: ScFunc, + pub params: MutableGrantDeployPermissionParams, } pub struct RevokeDeployPermissionCall { - pub func: ScFunc, - pub params: MutableRevokeDeployPermissionParams, + pub func: ScFunc, + pub params: MutableRevokeDeployPermissionParams, } pub struct FindContractCall { - pub func: ScView, - pub params: MutableFindContractParams, - pub results: ImmutableFindContractResults, + pub func: ScView, + pub params: MutableFindContractParams, + pub results: ImmutableFindContractResults, } pub struct GetContractRecordsCall { - pub func: ScView, - pub results: ImmutableGetContractRecordsResults, + pub func: ScView, + pub results: ImmutableGetContractRecordsResults, } pub struct ScFuncs { @@ -46,45 +44,47 @@ pub struct ScFuncs { impl ScFuncs { pub fn deploy_contract(_ctx: & dyn ScFuncCallContext) -> DeployContractCall { let mut f = DeployContractCall { - func: ScFunc::new(HSC_NAME, HFUNC_DEPLOY_CONTRACT), + func: ScFunc::new(HSC_NAME, HFUNC_DEPLOY_CONTRACT), params: MutableDeployContractParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn grant_deploy_permission(_ctx: & dyn ScFuncCallContext) -> GrantDeployPermissionCall { let mut f = GrantDeployPermissionCall { - func: ScFunc::new(HSC_NAME, HFUNC_GRANT_DEPLOY_PERMISSION), + func: ScFunc::new(HSC_NAME, HFUNC_GRANT_DEPLOY_PERMISSION), params: MutableGrantDeployPermissionParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn revoke_deploy_permission(_ctx: & dyn ScFuncCallContext) -> RevokeDeployPermissionCall { let mut f = RevokeDeployPermissionCall { - func: ScFunc::new(HSC_NAME, HFUNC_REVOKE_DEPLOY_PERMISSION), + func: ScFunc::new(HSC_NAME, HFUNC_REVOKE_DEPLOY_PERMISSION), params: MutableRevokeDeployPermissionParams { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, ptr::null_mut()); f } + pub fn find_contract(_ctx: & dyn ScViewCallContext) -> FindContractCall { let mut f = FindContractCall { - func: ScView::new(HSC_NAME, HVIEW_FIND_CONTRACT), - params: MutableFindContractParams { id: 0 }, + func: ScView::new(HSC_NAME, HVIEW_FIND_CONTRACT), + params: MutableFindContractParams { id: 0 }, results: ImmutableFindContractResults { id: 0 }, }; f.func.set_ptrs(&mut f.params.id, &mut f.results.id); f } + pub fn get_contract_records(_ctx: & dyn ScViewCallContext) -> GetContractRecordsCall { let mut f = GetContractRecordsCall { - func: ScView::new(HSC_NAME, HVIEW_GET_CONTRACT_RECORDS), + func: ScView::new(HSC_NAME, HVIEW_GET_CONTRACT_RECORDS), results: ImmutableGetContractRecordsResults { id: 0 }, }; f.func.set_ptrs(ptr::null_mut(), &mut f.results.id); f } } - -// @formatter:on diff --git a/packages/vm/wasmlib/src/coreroot/params.rs b/packages/vm/wasmlib/src/coreroot/params.rs index dd20e78e87..59257f5334 100644 --- a/packages/vm/wasmlib/src/coreroot/params.rs +++ b/packages/vm/wasmlib/src/coreroot/params.rs @@ -19,16 +19,16 @@ pub struct ImmutableDeployContractParams { impl ImmutableDeployContractParams { pub fn description(&self) -> ScImmutableString { - ScImmutableString::new(self.id, PARAM_DESCRIPTION.get_key_id()) - } + ScImmutableString::new(self.id, PARAM_DESCRIPTION.get_key_id()) + } pub fn name(&self) -> ScImmutableString { - ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) - } + ScImmutableString::new(self.id, PARAM_NAME.get_key_id()) + } pub fn program_hash(&self) -> ScImmutableHash { - ScImmutableHash::new(self.id, PARAM_PROGRAM_HASH.get_key_id()) - } + ScImmutableHash::new(self.id, PARAM_PROGRAM_HASH.get_key_id()) + } } #[derive(Clone, Copy)] @@ -38,16 +38,16 @@ pub struct MutableDeployContractParams { impl MutableDeployContractParams { pub fn description(&self) -> ScMutableString { - ScMutableString::new(self.id, PARAM_DESCRIPTION.get_key_id()) - } + ScMutableString::new(self.id, PARAM_DESCRIPTION.get_key_id()) + } pub fn name(&self) -> ScMutableString { - ScMutableString::new(self.id, PARAM_NAME.get_key_id()) - } + ScMutableString::new(self.id, PARAM_NAME.get_key_id()) + } pub fn program_hash(&self) -> ScMutableHash { - ScMutableHash::new(self.id, PARAM_PROGRAM_HASH.get_key_id()) - } + ScMutableHash::new(self.id, PARAM_PROGRAM_HASH.get_key_id()) + } } #[derive(Clone, Copy)] @@ -57,8 +57,8 @@ pub struct ImmutableGrantDeployPermissionParams { impl ImmutableGrantDeployPermissionParams { pub fn deployer(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, PARAM_DEPLOYER.get_key_id()) - } + ScImmutableAgentID::new(self.id, PARAM_DEPLOYER.get_key_id()) + } } #[derive(Clone, Copy)] @@ -68,8 +68,8 @@ pub struct MutableGrantDeployPermissionParams { impl MutableGrantDeployPermissionParams { pub fn deployer(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, PARAM_DEPLOYER.get_key_id()) - } + ScMutableAgentID::new(self.id, PARAM_DEPLOYER.get_key_id()) + } } #[derive(Clone, Copy)] @@ -79,8 +79,8 @@ pub struct ImmutableRevokeDeployPermissionParams { impl ImmutableRevokeDeployPermissionParams { pub fn deployer(&self) -> ScImmutableAgentID { - ScImmutableAgentID::new(self.id, PARAM_DEPLOYER.get_key_id()) - } + ScImmutableAgentID::new(self.id, PARAM_DEPLOYER.get_key_id()) + } } #[derive(Clone, Copy)] @@ -90,8 +90,8 @@ pub struct MutableRevokeDeployPermissionParams { impl MutableRevokeDeployPermissionParams { pub fn deployer(&self) -> ScMutableAgentID { - ScMutableAgentID::new(self.id, PARAM_DEPLOYER.get_key_id()) - } + ScMutableAgentID::new(self.id, PARAM_DEPLOYER.get_key_id()) + } } #[derive(Clone, Copy)] @@ -101,8 +101,8 @@ pub struct ImmutableFindContractParams { impl ImmutableFindContractParams { pub fn hname(&self) -> ScImmutableHname { - ScImmutableHname::new(self.id, PARAM_HNAME.get_key_id()) - } + ScImmutableHname::new(self.id, PARAM_HNAME.get_key_id()) + } } #[derive(Clone, Copy)] @@ -112,6 +112,6 @@ pub struct MutableFindContractParams { impl MutableFindContractParams { pub fn hname(&self) -> ScMutableHname { - ScMutableHname::new(self.id, PARAM_HNAME.get_key_id()) - } + ScMutableHname::new(self.id, PARAM_HNAME.get_key_id()) + } } diff --git a/packages/vm/wasmlib/src/coreroot/results.rs b/packages/vm/wasmlib/src/coreroot/results.rs index 4529c608a5..9a4f88fdb5 100644 --- a/packages/vm/wasmlib/src/coreroot/results.rs +++ b/packages/vm/wasmlib/src/coreroot/results.rs @@ -19,12 +19,12 @@ pub struct ImmutableFindContractResults { impl ImmutableFindContractResults { pub fn contract_found(&self) -> ScImmutableBytes { - ScImmutableBytes::new(self.id, RESULT_CONTRACT_FOUND.get_key_id()) - } + ScImmutableBytes::new(self.id, RESULT_CONTRACT_FOUND.get_key_id()) + } pub fn contract_rec_data(&self) -> ScImmutableBytes { - ScImmutableBytes::new(self.id, RESULT_CONTRACT_REC_DATA.get_key_id()) - } + ScImmutableBytes::new(self.id, RESULT_CONTRACT_REC_DATA.get_key_id()) + } } #[derive(Clone, Copy)] @@ -34,20 +34,20 @@ pub struct MutableFindContractResults { impl MutableFindContractResults { pub fn contract_found(&self) -> ScMutableBytes { - ScMutableBytes::new(self.id, RESULT_CONTRACT_FOUND.get_key_id()) - } + ScMutableBytes::new(self.id, RESULT_CONTRACT_FOUND.get_key_id()) + } pub fn contract_rec_data(&self) -> ScMutableBytes { - ScMutableBytes::new(self.id, RESULT_CONTRACT_REC_DATA.get_key_id()) - } + ScMutableBytes::new(self.id, RESULT_CONTRACT_REC_DATA.get_key_id()) + } } pub struct MapHnameToImmutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapHnameToImmutableBytes { - pub fn get_bytes(&self, key: &ScHname) -> ScImmutableBytes { + pub fn get_bytes(&self, key: ScHname) -> ScImmutableBytes { ScImmutableBytes::new(self.obj_id, key.get_key_id()) } } @@ -59,21 +59,21 @@ pub struct ImmutableGetContractRecordsResults { impl ImmutableGetContractRecordsResults { pub fn contract_registry(&self) -> MapHnameToImmutableBytes { - let map_id = get_object_id(self.id, RESULT_CONTRACT_REGISTRY.get_key_id(), TYPE_MAP); - MapHnameToImmutableBytes { obj_id: map_id } - } + let map_id = get_object_id(self.id, RESULT_CONTRACT_REGISTRY.get_key_id(), TYPE_MAP); + MapHnameToImmutableBytes { obj_id: map_id } + } } pub struct MapHnameToMutableBytes { - pub(crate) obj_id: i32, + pub(crate) obj_id: i32, } impl MapHnameToMutableBytes { pub fn clear(&self) { - clear(self.obj_id) + clear(self.obj_id); } - pub fn get_bytes(&self, key: &ScHname) -> ScMutableBytes { + pub fn get_bytes(&self, key: ScHname) -> ScMutableBytes { ScMutableBytes::new(self.obj_id, key.get_key_id()) } } @@ -85,7 +85,7 @@ pub struct MutableGetContractRecordsResults { impl MutableGetContractRecordsResults { pub fn contract_registry(&self) -> MapHnameToMutableBytes { - let map_id = get_object_id(self.id, RESULT_CONTRACT_REGISTRY.get_key_id(), TYPE_MAP); - MapHnameToMutableBytes { obj_id: map_id } - } + let map_id = get_object_id(self.id, RESULT_CONTRACT_REGISTRY.get_key_id(), TYPE_MAP); + MapHnameToMutableBytes { obj_id: map_id } + } } diff --git a/packages/vm/wasmlib/src/events.rs b/packages/vm/wasmlib/src/events.rs new file mode 100644 index 0000000000..19d74cb1df --- /dev/null +++ b/packages/vm/wasmlib/src/events.rs @@ -0,0 +1,117 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +use crate::context::*; +use crate::hashtypes::*; +use crate::keys::*; + +// encodes separate entities into a byte buffer +pub struct EventEncoder { + event: String, +} + +impl EventEncoder { + // constructs an encoder + pub fn new(event_name: &str) -> EventEncoder { + let mut e = EventEncoder { event: event_name.to_string() }; + let timestamp = ROOT.get_int64(&KEY_TIMESTAMP).value(); + e.int64(timestamp / 1_000_000_000); + e + } + + // encodes an ScAddress into the byte buffer + pub fn address(&mut self, value: &ScAddress) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an ScAgentID into the byte buffer + pub fn agent_id(&mut self, value: &ScAgentID) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes a Bool as 0/1 into the byte buffer + pub fn bool(&mut self, value: bool) -> &EventEncoder { + self.uint8(value as u8) + } + + // encodes a substring of bytes into the byte buffer + pub fn bytes(&mut self, value: &[u8]) -> &EventEncoder { + self.string(&base58_encode(value)) + } + + // encodes an ScChainID into the byte buffer + pub fn chain_id(&mut self, value: &ScChainID) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an ScColor into the byte buffer + pub fn color(&mut self, value: &ScColor) -> &EventEncoder { + self.string(&value.to_string()) + } + + // retrieve the encoded byte buffer + pub fn emit(&self) { + ROOT.get_string(&KEY_EVENT).set_value(&self.event); + } + + // encodes an ScHash into the byte buffer + pub fn hash(&mut self, value: &ScHash) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an ScHname into the byte buffer + pub fn hname(&mut self, value: ScHname) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an Int8 into the byte buffer + pub fn int8(&mut self, value: i8) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an Int16 into the byte buffer + pub fn int16(&mut self, value: i16) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an Int32 into the byte buffer + pub fn int32(&mut self, value: i32) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an Int64 into the byte buffer + pub fn int64(&mut self, value: i64) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an ScRequestID into the byte buffer + pub fn request_id(&mut self, value: &ScRequestID) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an UTF-8 text string into the byte buffer + pub fn string(&mut self, value: &str) -> &EventEncoder { + self.event += &("|".to_owned() + value); + self + } + + // encodes an Uint8 into the byte buffer + pub fn uint8(&mut self, value: u8) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an Uint16 into the byte buffer + pub fn uint16(&mut self, value: u16) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an Uint32 into the byte buffer + pub fn uint32(&mut self, value: u32) -> &EventEncoder { + self.string(&value.to_string()) + } + + // encodes an Uint64 into the byte buffer + pub fn uint64(&mut self, value: u64) -> &EventEncoder { + self.string(&value.to_string()) + } +} diff --git a/packages/vm/wasmlib/src/hashtypes.rs b/packages/vm/wasmlib/src/hashtypes.rs index d71fcadec4..56fdb4ce2c 100644 --- a/packages/vm/wasmlib/src/hashtypes.rs +++ b/packages/vm/wasmlib/src/hashtypes.rs @@ -18,6 +18,8 @@ pub struct ScAddress { } impl ScAddress { + pub const ZERO: ScAddress = ScAddress { id: [0; 33] }; + // construct from byte array pub fn from_bytes(bytes: &[u8]) -> ScAddress { ScAddress { id: bytes.try_into().expect("invalid address id length") } @@ -44,7 +46,7 @@ impl ScAddress { // can be used as key in maps impl MapKey for ScAddress { fn get_key_id(&self) -> Key32 { - get_key_id_from_bytes(self.to_bytes()) + get_key_id_from_bytes(&self.id) } } @@ -57,8 +59,10 @@ pub struct ScAgentID { } impl ScAgentID { + pub const ZERO: ScAgentID = ScAgentID { id: [0; 37] }; + // construct from address and contract name hash - pub fn new(address: &ScAddress, hname: &ScHname) -> ScAgentID { + pub fn new(address: &ScAddress, hname: ScHname) -> ScAgentID { let mut agent_id = ScAgentID { id: [0; 37] }; agent_id.id[..33].copy_from_slice(&address.to_bytes()); agent_id.id[33..].copy_from_slice(&hname.to_bytes()); @@ -101,7 +105,7 @@ impl ScAgentID { // can be used as key in maps impl MapKey for ScAgentID { fn get_key_id(&self) -> Key32 { - get_key_id_from_bytes(self.to_bytes()) + get_key_id_from_bytes(&self.id) } } @@ -140,7 +144,7 @@ impl ScChainID { // can be used as key in maps impl MapKey for ScChainID { fn get_key_id(&self) -> Key32 { - get_key_id_from_bytes(self.to_bytes()) + get_key_id_from_bytes(&self.id) } } @@ -183,7 +187,7 @@ impl ScColor { // can be used as key in maps impl MapKey for ScColor { fn get_key_id(&self) -> Key32 { - get_key_id_from_bytes(self.to_bytes()) + get_key_id_from_bytes(&self.id) } } @@ -196,6 +200,8 @@ pub struct ScHash { } impl ScHash { + pub const ZERO: ScHash = ScHash { id: [0; 32] }; + // construct from byte array pub fn from_bytes(bytes: &[u8]) -> ScHash { ScHash { id: bytes.try_into().expect("invalid hash id length") } @@ -215,7 +221,7 @@ impl ScHash { // can be used as key in maps impl MapKey for ScHash { fn get_key_id(&self) -> Key32 { - get_key_id_from_bytes(self.to_bytes()) + get_key_id_from_bytes(&self.id) } } @@ -242,9 +248,16 @@ impl ScHname { self.0.to_le_bytes().to_vec() } - // human-readable string representation + // human-readable string representation: 8 hex digits pub fn to_string(&self) -> String { - self.0.to_string() + let hex = "0123456789abcdef".as_bytes(); + let mut res = [0u8; 8]; + let mut val = self.0; + for n in 0..8 { + res[7 - n] = hex[val as usize & 0x0f]; + val >>= 4; + } + String::from_utf8(res.to_vec()).expect("WTF? invalid?") } } @@ -283,6 +296,6 @@ impl ScRequestID { // can be used as key in maps impl MapKey for ScRequestID { fn get_key_id(&self) -> Key32 { - get_key_id_from_bytes(self.to_bytes()) + get_key_id_from_bytes(&self.id) } } diff --git a/packages/vm/wasmlib/src/host.rs b/packages/vm/wasmlib/src/host.rs index 49849bfe7a..72cac67eea 100644 --- a/packages/vm/wasmlib/src/host.rs +++ b/packages/vm/wasmlib/src/host.rs @@ -9,22 +9,25 @@ use crate::keys::*; // all type id values should exactly match their counterpart values on the host! pub const TYPE_ARRAY: i32 = 0x20; -pub const TYPE_ARRAY16: i32 = 0x30; -pub const TYPE_CALL: i32 = 0x40; +pub const TYPE_ARRAY16: i32 = 0x60; +pub const TYPE_CALL: i32 = 0x80; +pub const TYPE_MASK: i32 = 0x1f; pub const TYPE_ADDRESS: i32 = 1; pub const TYPE_AGENT_ID: i32 = 2; -pub const TYPE_BYTES: i32 = 3; -pub const TYPE_CHAIN_ID: i32 = 4; -pub const TYPE_COLOR: i32 = 5; -pub const TYPE_HASH: i32 = 6; -pub const TYPE_HNAME: i32 = 7; -pub const TYPE_INT16: i32 = 8; -pub const TYPE_INT32: i32 = 9; -pub const TYPE_INT64: i32 = 10; -pub const TYPE_MAP: i32 = 11; -pub const TYPE_REQUEST_ID: i32 = 12; -pub const TYPE_STRING: i32 = 13; +pub const TYPE_BOOL: i32 = 3; +pub const TYPE_BYTES: i32 = 4; +pub const TYPE_CHAIN_ID: i32 = 5; +pub const TYPE_COLOR: i32 = 6; +pub const TYPE_HASH: i32 = 7; +pub const TYPE_HNAME: i32 = 8; +pub const TYPE_INT8: i32 = 9; +pub const TYPE_INT16: i32 = 10; +pub const TYPE_INT32: i32 = 11; +pub const TYPE_INT64: i32 = 12; +pub const TYPE_MAP: i32 = 13; +pub const TYPE_REQUEST_ID: i32 = 14; +pub const TYPE_STRING: i32 = 15; pub const OBJ_ID_NULL: i32 = 0; pub const OBJ_ID_ROOT: i32 = 1; @@ -33,7 +36,7 @@ pub const OBJ_ID_PARAMS: i32 = 3; pub const OBJ_ID_RESULTS: i32 = 4; // size in bytes of predefined types, indexed by the TYPE_* consts -const TYPE_SIZES: &[u8] = &[0, 33, 37, 0, 33, 32, 32, 4, 2, 4, 8, 0, 34, 0]; +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 // to their counterparts on the host. @@ -42,12 +45,12 @@ extern { // Copy the value data bytes of type stored in the host container object , // under key , into the pre-allocated which can hold len bytes. // Returns the actual length of the value data bytes on the host. - pub fn hostGetBytes(obj_id: i32, key_id: i32, type_id: i32, buffer: *const u8, len: i32) -> i32; + pub fn hostGetBytes(obj_id: i32, key_id: i32, type_id: i32, buffer: *const u8, size: i32) -> i32; // Retrieve the key id associated with the data bytes of length . // A negative length indicates a bytes key, positive indicates a string key // We discern between the two for better readable logging purposes - pub fn hostGetKeyID(key: *const u8, len: i32) -> i32; + pub fn hostGetKeyID(key: *const u8, size: i32) -> i32; // Retrieve the id of the container sub-object of type stored in // the host container object , under key . @@ -55,7 +58,7 @@ extern { // copy the value data bytes of type from the // into the host container object , under key . - pub fn hostSetBytes(obj_id: i32, key_id: i32, type_id: i32, buffer: *const u8, len: i32); + pub fn hostSetBytes(obj_id: i32, key_id: i32, type_id: i32, buffer: *const u8, size: i32); } pub fn call_func(obj_id: i32, key_id: Key32, params: &[u8]) -> Vec { @@ -90,10 +93,19 @@ pub fn clear(obj_id: i32) { set_bytes(obj_id, KEY_LENGTH, TYPE_INT32, &0_i32.to_le_bytes()) } +// Delete the value with the specified key and type from the specified container object. +pub fn del_key(obj_id: i32, key_id: Key32, type_id: i32) { + unsafe { + // size -1 means delete + // this removes the need for a separate hostDelete function + hostSetBytes(obj_id, key_id.0, type_id, std::ptr::null_mut(), -1); + } +} + // Check if the specified container object contains a value with the specified key and type. pub fn exists(obj_id: i32, key_id: Key32, type_id: i32) -> bool { unsafe { - // negative length (-1) means only test for existence + // size -1 means only test for existence // returned size -1 indicates keyID not found (or error) // this removes the need for a separate hostExists function hostGetBytes(obj_id, key_id.0, type_id, std::ptr::null_mut(), -1) >= 0 @@ -117,7 +129,7 @@ pub fn get_bytes(obj_id: i32, key_id: Key32, type_id: i32) -> Vec { } } - // allocate a sufficient length byte array in Wasm memory + // allocate a sufficiently sized byte array in Wasm memory // and let the host copy the actual data bytes into this Wasm byte array let mut result = vec![0_u8; size as usize]; hostGetBytes(obj_id, key_id.0, type_id, result.as_mut_ptr(), size); @@ -143,6 +155,12 @@ pub fn get_key_id_from_string(key: &str) -> Key32 { } } +// Retrieve the key id that the host has associated with the specified integer key +pub fn get_key_id_from_uint64(key: u64, nr_of_bytes: usize) -> Key32 { + let bytes = key.to_le_bytes(); + get_key_id_from_bytes(&bytes[..nr_of_bytes]) +} + // Retrieve the length of an array container object on the host pub fn get_length(obj_id: i32) -> i32 { // special integer key "length" is used diff --git a/packages/vm/wasmlib/src/immutable.rs b/packages/vm/wasmlib/src/immutable.rs index 1391e749a0..577c1b0a00 100644 --- a/packages/vm/wasmlib/src/immutable.rs +++ b/packages/vm/wasmlib/src/immutable.rs @@ -106,6 +106,55 @@ impl ScImmutableAgentIDArray { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ +// value proxy for immutable Bool in host container +pub struct ScImmutableBool { + obj_id: i32, + key_id: Key32, +} + +impl ScImmutableBool { + pub fn new(obj_id: i32, key_id: Key32) -> ScImmutableBool { + ScImmutableBool { obj_id, key_id } + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_BOOL) + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // get value from host container + pub fn value(&self) -> bool { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_BOOL); + bytes[0] != 0 + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for immutable array of Bool +pub struct ScImmutableBoolArray { + pub(crate) obj_id: i32, +} + +impl ScImmutableBoolArray { + // get value proxy for item at index, index can be 0..length()-1 + pub fn get_bool(&self, index: i32) -> ScImmutableBool { + ScImmutableBool { obj_id: self.obj_id, key_id: Key32(index) } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + // value proxy for immutable bytes array in host container pub struct ScImmutableBytes { obj_id: i32, @@ -346,7 +395,56 @@ impl ScImmutableHnameArray { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for immutable int16 in host container +// value proxy for immutable Int8 in host container +pub struct ScImmutableInt8 { + obj_id: i32, + key_id: Key32, +} + +impl ScImmutableInt8 { + pub fn new(obj_id: i32, key_id: Key32) -> ScImmutableInt8 { + ScImmutableInt8 { obj_id, key_id } + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_INT8) + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // get value from host container + pub fn value(&self) -> i8 { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_INT8); + bytes[0] as i8 + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for immutable array of Int8 +pub struct ScImmutableInt8Array { + pub(crate) obj_id: i32, +} + +impl ScImmutableInt8Array { + // get value proxy for item at index, index can be 0..length()-1 + pub fn get_int8(&self, index: i32) -> ScImmutableInt8 { + ScImmutableInt8 { obj_id: self.obj_id, key_id: Key32(index) } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Int16 in host container pub struct ScImmutableInt16 { obj_id: i32, key_id: Key32, @@ -376,7 +474,7 @@ impl ScImmutableInt16 { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for immutable array of int16 +// array proxy for immutable array of Int16 pub struct ScImmutableInt16Array { pub(crate) obj_id: i32, } @@ -395,7 +493,7 @@ impl ScImmutableInt16Array { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for immutable int32 in host container +// value proxy for immutable Int32 in host container pub struct ScImmutableInt32 { obj_id: i32, key_id: Key32, @@ -425,7 +523,7 @@ impl ScImmutableInt32 { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for immutable array of int32 +// array proxy for immutable array of Int32 pub struct ScImmutableInt32Array { pub(crate) obj_id: i32, } @@ -444,7 +542,7 @@ impl ScImmutableInt32Array { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for immutable int64 in host container +// value proxy for immutable Int64 in host container pub struct ScImmutableInt64 { obj_id: i32, key_id: Key32, @@ -474,7 +572,7 @@ impl ScImmutableInt64 { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for immutable array of int64 +// array proxy for immutable array of Int64 pub struct ScImmutableInt64Array { pub(crate) obj_id: i32, } @@ -525,6 +623,17 @@ impl ScImmutableMap { ScImmutableAgentIDArray { obj_id: arr_id } } + // get value proxy for immutable Bool field specified by key + pub fn get_bool(&self, key: &T) -> ScImmutableBool { + ScImmutableBool { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScImmutableBoolArray specified by key + pub fn get_bool_array(&self, key: &T) -> ScImmutableBoolArray { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_BOOL | TYPE_ARRAY); + ScImmutableBoolArray { obj_id: arr_id } + } + // get value proxy for immutable bytes array field specified by key pub fn get_bytes(&self, key: &T) -> ScImmutableBytes { ScImmutableBytes { obj_id: self.obj_id, key_id: key.get_key_id() } @@ -580,7 +689,18 @@ impl ScImmutableMap { ScImmutableHnameArray { obj_id: arr_id } } - // get value proxy for immutable int16 field specified by key + // get value proxy for immutable Int8 field specified by key + pub fn get_int8(&self, key: &T) -> ScImmutableInt8 { + ScImmutableInt8 { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScImmutableInt8Array specified by key + pub fn get_int8_array(&self, key: &T) -> ScImmutableInt8Array { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_INT8 | TYPE_ARRAY); + ScImmutableInt8Array { obj_id: arr_id } + } + + // get value proxy for immutable Int16 field specified by key pub fn get_int16(&self, key: &T) -> ScImmutableInt16 { ScImmutableInt16 { obj_id: self.obj_id, key_id: key.get_key_id() } } @@ -591,7 +711,7 @@ impl ScImmutableMap { ScImmutableInt16Array { obj_id: arr_id } } - // get value proxy for immutable int32 field specified by key + // get value proxy for immutable Int32 field specified by key pub fn get_int32(&self, key: &T) -> ScImmutableInt32 { ScImmutableInt32 { obj_id: self.obj_id, key_id: key.get_key_id() } } @@ -602,7 +722,7 @@ impl ScImmutableMap { ScImmutableInt32Array { obj_id: arr_id } } - // get value proxy for immutable int64 field specified by key + // get value proxy for immutable Int64 field specified by key pub fn get_int64(&self, key: &T) -> ScImmutableInt64 { ScImmutableInt64 { obj_id: self.obj_id, key_id: key.get_key_id() } } @@ -647,6 +767,50 @@ impl ScImmutableMap { ScImmutableStringArray { obj_id: arr_id } } + // get value proxy for immutable Uint8 field specified by key + pub fn get_uint8(&self, key: &T) -> ScImmutableUint8 { + ScImmutableUint8 { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScImmutableUint8Array specified by key + pub fn get_uint8_array(&self, key: &T) -> ScImmutableUint8Array { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_INT8 | TYPE_ARRAY); + ScImmutableUint8Array { obj_id: arr_id } + } + + // get value proxy for immutable Uint16 field specified by key + pub fn get_uint16(&self, key: &T) -> ScImmutableUint16 { + ScImmutableUint16 { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScImmutableUint16Array specified by key + pub fn get_uint16_array(&self, key: &T) -> ScImmutableUint16Array { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_INT16 | TYPE_ARRAY); + ScImmutableUint16Array { obj_id: arr_id } + } + + // get value proxy for immutable Uint32 field specified by key + pub fn get_uint32(&self, key: &T) -> ScImmutableUint32 { + ScImmutableUint32 { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScImmutableUint32Array specified by key + pub fn get_uint32_array(&self, key: &T) -> ScImmutableUint32Array { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_INT32 | TYPE_ARRAY); + ScImmutableUint32Array { obj_id: arr_id } + } + + // get value proxy for immutable Uint64 field specified by key + pub fn get_uint64(&self, key: &T) -> ScImmutableUint64 { + ScImmutableUint64 { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScImmutableUint64Array specified by key + pub fn get_uint64_array(&self, key: &T) -> ScImmutableUint64Array { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_INT64 | TYPE_ARRAY); + ScImmutableUint64Array { obj_id: arr_id } + } + pub fn map_id(&self) -> i32 { self.obj_id } @@ -766,3 +930,199 @@ impl ScImmutableStringArray { get_length(self.obj_id) } } + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Uint8 in host container +pub struct ScImmutableUint8 { + obj_id: i32, + key_id: Key32, +} + +impl ScImmutableUint8 { + pub fn new(obj_id: i32, key_id: Key32) -> ScImmutableUint8 { + ScImmutableUint8 { obj_id, key_id } + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_INT8) + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // get value from host container + pub fn value(&self) -> u8 { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_INT8); + bytes[0] + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for immutable array of Uint8 +pub struct ScImmutableUint8Array { + pub(crate) obj_id: i32, +} + +impl ScImmutableUint8Array { + // get value proxy for item at index, index can be 0..length()-1 + pub fn get_uint8(&self, index: i32) -> ScImmutableUint8 { + ScImmutableUint8 { obj_id: self.obj_id, key_id: Key32(index) } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Uint16 in host container +pub struct ScImmutableUint16 { + obj_id: i32, + key_id: Key32, +} + +impl ScImmutableUint16 { + pub fn new(obj_id: i32, key_id: Key32) -> ScImmutableUint16 { + ScImmutableUint16 { obj_id, key_id } + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_INT16) + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // get value from host container + pub fn value(&self) -> u16 { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_INT16); + u16::from_le_bytes(bytes.try_into().expect("invalid u16 length")) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for immutable array of Uint16 +pub struct ScImmutableUint16Array { + pub(crate) obj_id: i32, +} + +impl ScImmutableUint16Array { + // get value proxy for item at index, index can be 0..length()-1 + pub fn get_uint16(&self, index: i32) -> ScImmutableUint16 { + ScImmutableUint16 { obj_id: self.obj_id, key_id: Key32(index) } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Uint32 in host container +pub struct ScImmutableUint32 { + obj_id: i32, + key_id: Key32, +} + +impl ScImmutableUint32 { + pub fn new(obj_id: i32, key_id: Key32) -> ScImmutableUint32 { + ScImmutableUint32 { obj_id, key_id } + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_INT32) + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // get value from host container + pub fn value(&self) -> u32 { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_INT32); + u32::from_le_bytes(bytes.try_into().expect("invalid u32 length")) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for immutable array of Uint32 +pub struct ScImmutableUint32Array { + pub(crate) obj_id: i32, +} + +impl ScImmutableUint32Array { + // get value proxy for item at index, index can be 0..length()-1 + pub fn get_uint32(&self, index: i32) -> ScImmutableUint32 { + ScImmutableUint32 { obj_id: self.obj_id, key_id: Key32(index) } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Uint64 in host container +pub struct ScImmutableUint64 { + obj_id: i32, + key_id: Key32, +} + +impl ScImmutableUint64 { + pub fn new(obj_id: i32, key_id: Key32) -> ScImmutableUint64 { + ScImmutableUint64 { obj_id, key_id } + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_INT64) + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // get value from host container + pub fn value(&self) -> u64 { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_INT64); + u64::from_le_bytes(bytes.try_into().expect("invalid u64 length")) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for immutable array of Uint64 +pub struct ScImmutableUint64Array { + pub(crate) obj_id: i32, +} + +impl ScImmutableUint64Array { + // get value proxy for item at index, index can be 0..length()-1 + pub fn get_uint64(&self, index: i32) -> ScImmutableUint64 { + ScImmutableUint64 { obj_id: self.obj_id, key_id: Key32(index) } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} diff --git a/packages/vm/wasmlib/src/lib.rs b/packages/vm/wasmlib/src/lib.rs index 83b33eb132..6b28fa2f1b 100644 --- a/packages/vm/wasmlib/src/lib.rs +++ b/packages/vm/wasmlib/src/lib.rs @@ -6,6 +6,7 @@ pub use bytes::*; pub use context::*; pub use contract::*; +pub use events::*; pub use exports::ScExports; pub use hashtypes::*; pub use immutable::*; @@ -20,6 +21,7 @@ pub mod coreblob; pub mod coreblocklog; pub mod coregovernance; pub mod coreroot; +mod events; mod exports; mod hashtypes; pub mod host; diff --git a/packages/vm/wasmlib/src/mutable.rs b/packages/vm/wasmlib/src/mutable.rs index a2a1afcf67..8ffaca21b0 100644 --- a/packages/vm/wasmlib/src/mutable.rs +++ b/packages/vm/wasmlib/src/mutable.rs @@ -24,6 +24,11 @@ impl ScMutableAddress { ScMutableAddress { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_ADDRESS); + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_ADDRESS) @@ -88,6 +93,11 @@ impl ScMutableAgentID { ScMutableAgentID { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_AGENT_ID) + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_AGENT_ID) @@ -141,6 +151,77 @@ impl ScMutableAgentIDArray { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ +// value proxy for mutable Bool in host container +pub struct ScMutableBool { + obj_id: i32, + key_id: Key32, +} + +impl ScMutableBool { + pub fn new(obj_id: i32, key_id: Key32) -> ScMutableBool { + ScMutableBool { obj_id, key_id } + } + + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_BOOL) + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_BOOL) + } + + // set value in host container + pub fn set_value(&self, val: bool) { + let bytes = [val as u8]; + set_bytes(self.obj_id, self.key_id, TYPE_BOOL, &bytes); + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // retrieve value from host container + pub fn value(&self) -> bool { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_BOOL); + bytes[0] != 0 + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for mutable array of Bool +pub struct ScMutableBoolArray { + pub(crate) obj_id: i32, +} + +impl ScMutableBoolArray { + // empty the array + pub fn clear(&self) { + clear(self.obj_id); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + pub fn get_bool(&self, index: i32) -> ScMutableBool { + ScMutableBool { obj_id: self.obj_id, key_id: Key32(index) } + } + + // get immutable version of array proxy + pub fn immutable(&self) -> ScImmutableBoolArray { + ScImmutableBoolArray { obj_id: self.obj_id } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + // value proxy for mutable bytes array in host container pub struct ScMutableBytes { obj_id: i32, @@ -152,6 +233,11 @@ impl ScMutableBytes { ScMutableBytes { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_BYTES) + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_BYTES) @@ -216,6 +302,11 @@ impl ScMutableChainID { ScMutableChainID { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_CHAIN_ID) + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_CHAIN_ID) @@ -280,6 +371,11 @@ impl ScMutableColor { ScMutableColor { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_COLOR) + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_COLOR) @@ -344,6 +440,11 @@ impl ScMutableHash { ScMutableHash { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_HASH) + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_HASH) @@ -408,6 +509,11 @@ impl ScMutableHname { ScMutableHname { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_HNAME) + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_HNAME) @@ -461,7 +567,78 @@ impl ScMutableHnameArray { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for mutable int16 in host container +// value proxy for mutable Int8 in host container +pub struct ScMutableInt8 { + obj_id: i32, + key_id: Key32, +} + +impl ScMutableInt8 { + pub fn new(obj_id: i32, key_id: Key32) -> ScMutableInt8 { + ScMutableInt8 { obj_id, key_id } + } + + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_INT8) + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_INT8) + } + + // set value in host container + pub fn set_value(&self, val: i8) { + let bytes = [val as u8]; + set_bytes(self.obj_id, self.key_id, TYPE_INT8, &bytes); + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // retrieve value from host container + pub fn value(&self) -> i8 { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_INT8); + bytes[0] as i8 + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for mutable array of Int8 +pub struct ScMutableInt8Array { + pub(crate) obj_id: i32, +} + +impl ScMutableInt8Array { + // empty the array + pub fn clear(&self) { + clear(self.obj_id); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + pub fn get_int8(&self, index: i32) -> ScMutableInt8 { + ScMutableInt8 { obj_id: self.obj_id, key_id: Key32(index) } + } + + // get immutable version of array proxy + pub fn immutable(&self) -> ScImmutableInt8Array { + ScImmutableInt8Array { obj_id: self.obj_id } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Int16 in host container pub struct ScMutableInt16 { obj_id: i32, key_id: Key32, @@ -472,6 +649,11 @@ impl ScMutableInt16 { ScMutableInt16 { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_INT16) + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_INT16) @@ -496,7 +678,7 @@ impl ScMutableInt16 { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for mutable array of int16 +// array proxy for mutable array of Int16 pub struct ScMutableInt16Array { pub(crate) obj_id: i32, } @@ -526,7 +708,7 @@ impl ScMutableInt16Array { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for mutable int32 in host container +// value proxy for mutable Int32 in host container pub struct ScMutableInt32 { obj_id: i32, key_id: Key32, @@ -537,6 +719,11 @@ impl ScMutableInt32 { ScMutableInt32 { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_INT32) + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_INT32) @@ -561,7 +748,7 @@ impl ScMutableInt32 { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for mutable array of int32 +// array proxy for mutable array of Int32 pub struct ScMutableInt32Array { pub(crate) obj_id: i32, } @@ -591,7 +778,7 @@ impl ScMutableInt32Array { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for mutable int64 in host container +// value proxy for mutable Int64 in host container pub struct ScMutableInt64 { obj_id: i32, key_id: Key32, @@ -602,6 +789,11 @@ impl ScMutableInt64 { ScMutableInt64 { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_INT64) + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_INT64) @@ -626,7 +818,7 @@ impl ScMutableInt64 { // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for mutable array of int64 +// array proxy for mutable array of Int64 pub struct ScMutableInt64Array { pub(crate) obj_id: i32, } @@ -700,6 +892,17 @@ impl ScMutableMap { ScMutableAgentIDArray { obj_id: arr_id } } + // get value proxy for mutable Bool field specified by key + pub fn get_bool(&self, key: &T) -> ScMutableBool { + ScMutableBool { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScMutableBoolArray specified by key + pub fn get_bool_array(&self, key: &T) -> ScMutableBoolArray { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_BOOL | TYPE_ARRAY); + ScMutableBoolArray { obj_id: arr_id } + } + // get value proxy for mutable bytes array field specified by key pub fn get_bytes(&self, key: &T) -> ScMutableBytes { ScMutableBytes { obj_id: self.obj_id, key_id: key.get_key_id() } @@ -755,7 +958,18 @@ impl ScMutableMap { ScMutableHnameArray { obj_id: arr_id } } - // get value proxy for mutable int16 field specified by key + // get value proxy for mutable Int8 field specified by key + pub fn get_int8(&self, key: &T) -> ScMutableInt8 { + ScMutableInt8 { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScMutableInt8Array specified by key + pub fn get_int8_array(&self, key: &T) -> ScMutableInt8Array { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_INT8 | TYPE_ARRAY); + ScMutableInt8Array { obj_id: arr_id } + } + + // get value proxy for mutable Int16 field specified by key pub fn get_int16(&self, key: &T) -> ScMutableInt16 { ScMutableInt16 { obj_id: self.obj_id, key_id: key.get_key_id() } } @@ -766,9 +980,9 @@ impl ScMutableMap { ScMutableInt16Array { obj_id: arr_id } } - // get value proxy for mutable int64 field specified by key - pub fn get_int64(&self, key: &T) -> ScMutableInt64 { - ScMutableInt64 { obj_id: self.obj_id, key_id: key.get_key_id() } + // get value proxy for mutable Int32 field specified by key + pub fn get_int32(&self, key: &T) -> ScMutableInt32 { + ScMutableInt32 { obj_id: self.obj_id, key_id: key.get_key_id() } } // get array proxy for ScMutableInt32Array specified by key @@ -777,9 +991,9 @@ impl ScMutableMap { ScMutableInt32Array { obj_id: arr_id } } - // get value proxy for mutable int32 field specified by key - pub fn get_int32(&self, key: &T) -> ScMutableInt32 { - ScMutableInt32 { obj_id: self.obj_id, key_id: key.get_key_id() } + // get value proxy for mutable Int64 field specified by key + pub fn get_int64(&self, key: &T) -> ScMutableInt64 { + ScMutableInt64 { obj_id: self.obj_id, key_id: key.get_key_id() } } // get array proxy for ScMutableInt64Array specified by key @@ -822,6 +1036,50 @@ impl ScMutableMap { ScMutableStringArray { obj_id: arr_id } } + // get value proxy for mutable Uint8 field specified by key + pub fn get_uint8(&self, key: &T) -> ScMutableUint8 { + ScMutableUint8 { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScMutableUint8Array specified by key + pub fn get_uint8_array(&self, key: &T) -> ScMutableUint8Array { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_INT8 | TYPE_ARRAY); + ScMutableUint8Array { obj_id: arr_id } + } + + // get value proxy for mutable Uint16 field specified by key + pub fn get_uint16(&self, key: &T) -> ScMutableUint16 { + ScMutableUint16 { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScMutableUint16Array specified by key + pub fn get_uint16_array(&self, key: &T) -> ScMutableUint16Array { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_INT16 | TYPE_ARRAY); + ScMutableUint16Array { obj_id: arr_id } + } + + // get value proxy for mutable Uint32 field specified by key + pub fn get_uint32(&self, key: &T) -> ScMutableUint32 { + ScMutableUint32 { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScMutableUint32Array specified by key + pub fn get_uint32_array(&self, key: &T) -> ScMutableUint32Array { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_INT32 | TYPE_ARRAY); + ScMutableUint32Array { obj_id: arr_id } + } + + // get value proxy for mutable Uint64 field specified by key + pub fn get_uint64(&self, key: &T) -> ScMutableUint64 { + ScMutableUint64 { obj_id: self.obj_id, key_id: key.get_key_id() } + } + + // get array proxy for ScMutableUint64Array specified by key + pub fn get_uint64_array(&self, key: &T) -> ScMutableUint64Array { + let arr_id = get_object_id(self.obj_id, key.get_key_id(), TYPE_INT64 | TYPE_ARRAY); + ScMutableUint64Array { obj_id: arr_id } + } + // get immutable version of map proxy pub fn immutable(&self) -> ScImmutableMap { ScImmutableMap { obj_id: self.obj_id } @@ -876,6 +1134,11 @@ impl ScMutableRequestID { ScMutableRequestID { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_REQUEST_ID) + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_REQUEST_ID) @@ -940,6 +1203,11 @@ impl ScMutableString { ScMutableString { obj_id, key_id } } + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_STRING) + } + // check if value exists in host container pub fn exists(&self) -> bool { exists(self.obj_id, self.key_id, TYPE_STRING) @@ -991,3 +1259,284 @@ impl ScMutableStringArray { get_length(self.obj_id) } } + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Uint8 in host container +pub struct ScMutableUint8 { + obj_id: i32, + key_id: Key32, +} + +impl ScMutableUint8 { + pub fn new(obj_id: i32, key_id: Key32) -> ScMutableUint8 { + ScMutableUint8 { obj_id, key_id } + } + + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_INT8) + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_INT8) + } + + // set value in host container + pub fn set_value(&self, val: u8) { + let bytes = [val]; + set_bytes(self.obj_id, self.key_id, TYPE_INT8, &bytes); + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // retrieve value from host container + pub fn value(&self) -> u8 { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_INT8); + bytes[0] + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for mutable array of Uint8 +pub struct ScMutableUint8Array { + pub(crate) obj_id: i32, +} + +impl ScMutableUint8Array { + // empty the array + pub fn clear(&self) { + clear(self.obj_id); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + pub fn get_uint8(&self, index: i32) -> ScMutableUint8 { + ScMutableUint8 { obj_id: self.obj_id, key_id: Key32(index) } + } + + // get immutable version of array proxy + pub fn immutable(&self) -> ScImmutableUint8Array { + ScImmutableUint8Array { obj_id: self.obj_id } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Uint16 in host container +pub struct ScMutableUint16 { + obj_id: i32, + key_id: Key32, +} + +impl ScMutableUint16 { + pub fn new(obj_id: i32, key_id: Key32) -> ScMutableUint16 { + ScMutableUint16 { obj_id, key_id } + } + + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_INT16) + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_INT16) + } + + // set value in host container + pub fn set_value(&self, val: u16) { + set_bytes(self.obj_id, self.key_id, TYPE_INT16, &val.to_le_bytes()); + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // retrieve value from host container + pub fn value(&self) -> u16 { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_INT16); + u16::from_le_bytes(bytes.try_into().expect("invalid u16 length")) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for mutable array of Uint16 +pub struct ScMutableUint16Array { + pub(crate) obj_id: i32, +} + +impl ScMutableUint16Array { + // empty the array + pub fn clear(&self) { + clear(self.obj_id); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + pub fn get_uint16(&self, index: i32) -> ScMutableUint16 { + ScMutableUint16 { obj_id: self.obj_id, key_id: Key32(index) } + } + + // get immutable version of array proxy + pub fn immutable(&self) -> ScImmutableUint16Array { + ScImmutableUint16Array { obj_id: self.obj_id } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Uint32 in host container +pub struct ScMutableUint32 { + obj_id: i32, + key_id: Key32, +} + +impl ScMutableUint32 { + pub fn new(obj_id: i32, key_id: Key32) -> ScMutableUint32 { + ScMutableUint32 { obj_id, key_id } + } + + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_INT32) + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_INT32) + } + + // set value in host container + pub fn set_value(&self, val: u32) { + set_bytes(self.obj_id, self.key_id, TYPE_INT32, &val.to_le_bytes()); + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // retrieve value from host container + pub fn value(&self) -> u32 { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_INT32); + u32::from_le_bytes(bytes.try_into().expect("invalid u32 length")) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for mutable array of Uint32 +pub struct ScMutableUint32Array { + pub(crate) obj_id: i32, +} + +impl ScMutableUint32Array { + // empty the array + pub fn clear(&self) { + clear(self.obj_id); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + pub fn get_uint32(&self, index: i32) -> ScMutableUint32 { + ScMutableUint32 { obj_id: self.obj_id, key_id: Key32(index) } + } + + // get immutable version of array proxy + pub fn immutable(&self) -> ScImmutableUint32Array { + ScImmutableUint32Array { obj_id: self.obj_id } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Uint64 in host container +pub struct ScMutableUint64 { + obj_id: i32, + key_id: Key32, +} + +impl ScMutableUint64 { + pub fn new(obj_id: i32, key_id: Key32) -> ScMutableUint64 { + ScMutableUint64 { obj_id, key_id } + } + + // delete value from host container + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_INT64) + } + + // check if value exists in host container + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_INT64) + } + + // set value in host container + pub fn set_value(&self, val: u64) { + set_bytes(self.obj_id, self.key_id, TYPE_INT64, &val.to_le_bytes()); + } + + // human-readable string representation + pub fn to_string(&self) -> String { + self.value().to_string() + } + + // retrieve value from host container + pub fn value(&self) -> u64 { + let bytes = get_bytes(self.obj_id, self.key_id, TYPE_INT64); + u64::from_le_bytes(bytes.try_into().expect("invalid ui64 length")) + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Uint64 +pub struct ScMutableUint64Array { + pub(crate) obj_id: i32, +} + +impl ScMutableUint64Array { + // empty the array + pub fn clear(&self) { + clear(self.obj_id); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + pub fn get_uint64(&self, index: i32) -> ScMutableUint64 { + ScMutableUint64 { obj_id: self.obj_id, key_id: Key32(index) } + } + + // get immutable version of array proxy + pub fn immutable(&self) -> ScImmutableUint64Array { + ScImmutableUint64Array { obj_id: self.obj_id } + } + + // number of items in array + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } +} diff --git a/packages/vm/wasmlib/ts/wasmlib/bytes.ts b/packages/vm/wasmlib/ts/wasmlib/bytes.ts index 35cab0e438..0cf37a1eb5 100644 --- a/packages/vm/wasmlib/ts/wasmlib/bytes.ts +++ b/packages/vm/wasmlib/ts/wasmlib/bytes.ts @@ -11,6 +11,9 @@ export class BytesDecoder { // constructs a decoder constructor(data: u8[]) { + if (data.length == 0) { + panic("cannot decode empty byte array, use exist()"); + } this.buf = data; } @@ -24,10 +27,15 @@ export class BytesDecoder { return ScAgentID.fromBytes(this.bytes()); } + // decodes a bool from the byte buffer + bool(): boolean { + return this.uint8() != 0; + } + // decodes the next substring of bytes from the byte buffer bytes(): u8[] { - let size = this.int32(); - if (this.buf.length < size) { + let size = this.uint32(); + if (u32(this.buf.length) < size) { panic("insufficient bytes"); } let value = this.buf.slice(0, size); @@ -55,6 +63,11 @@ export class BytesDecoder { return ScHname.fromBytes(this.bytes()); } + // decodes an int8 from the byte buffer + int8(): i8 { + return this.uint8() as i8; + } + // decodes an int16 from the byte buffer // note that these are encoded using leb128 encoding to conserve space int16(): i16 { @@ -115,6 +128,29 @@ export class BytesDecoder { return Convert.toString(this.bytes()); } + // decodes an uint8 from the byte buffer + uint8(): u8 { + return this.buf.shift(); + } + + // decodes an uint16 from the byte buffer + // note that these are encoded using leb128 encoding to conserve space + uint16(): u16 { + return this.int16() as u16; + } + + // decodes an uint32 from the byte buffer + // note that these are encoded using leb128 encoding to conserve space + uint32(): u32 { + return this.int32() as u32; + } + + // decodes an uint64 from the byte buffer + // note that these are encoded using leb128 encoding to conserve space + uint64(): u64 { + return this.int64() as u64; + } + close(): void { if (this.buf.length != 0) { panic("extra bytes"); @@ -135,19 +171,22 @@ export class BytesEncoder { // encodes an ScAddress into the byte buffer address(value: ScAddress): BytesEncoder { - this.bytes(value.toBytes()); - return this; + return this.bytes(value.toBytes()); } // encodes an ScAgentID into the byte buffer agentID(value: ScAgentID): BytesEncoder { - this.bytes(value.toBytes()); - return this; + return this.bytes(value.toBytes()); + } + + // encodes a bool into the byte buffer + bool(val: boolean): BytesEncoder { + return this.int8(val ? 1 : 0); } // encodes a substring of bytes into the byte buffer bytes(value: u8[]): BytesEncoder { - this.int32(value.length); + this.uint32(value.length); for (let i = 0; i < value.length; i++) { this.buf.push(value[i]); } @@ -156,14 +195,12 @@ export class BytesEncoder { // encodes an ScChainID into the byte buffer chainID(value: ScChainID): BytesEncoder { - this.bytes(value.toBytes()); - return this; + return this.bytes(value.toBytes()); } // encodes an ScColor into the byte buffer color(value: ScColor): BytesEncoder { - this.bytes(value.toBytes()); - return this; + return this.bytes(value.toBytes()); } // retrieve the encoded byte buffer @@ -173,14 +210,17 @@ export class BytesEncoder { // encodes an ScHash into the byte buffer hash(value: ScHash): BytesEncoder { - this.bytes(value.toBytes()); - return this; + return this.bytes(value.toBytes()); } // encodes an ScHname into the byte buffer hname(value: ScHname): BytesEncoder { - this.bytes(value.toBytes()); - return this; + return this.bytes(value.toBytes()); + } + + // encodes an int8 into the byte buffer + int8(val: i8): BytesEncoder { + return this.uint8(val as u8); } // encodes an int16 into the byte buffer @@ -218,13 +258,35 @@ export class BytesEncoder { // encodes an ScRequestID into the byte buffer requestID(value: ScRequestID): BytesEncoder { - this.bytes(value.toBytes()); - return this; + return this.bytes(value.toBytes()); } // encodes an UTF-8 text string into the byte buffer string(value: string): BytesEncoder { - this.bytes(Convert.fromString(value)); + return this.bytes(Convert.fromString(value)); + } + + // encodes an uint8 into the byte buffer + uint8(val: u8): BytesEncoder { + this.buf.push(val); return this; } + + // encodes an uint16 into the byte buffer + // note that these are encoded using leb128 encoding to conserve space + uint16(val: u16): BytesEncoder { + return this.int16(val as i16); + } + + // encodes an uint32 into the byte buffer + // note that these are encoded using leb128 encoding to conserve space + uint32(val: u32): BytesEncoder { + return this.int32(val as i32); + } + + // encodes an uint64 into the byte buffer + // note that these are encoded using leb128 encoding to conserve space + uint64(val: u64): BytesEncoder { + return this.int64(val as i64); + } } diff --git a/packages/vm/wasmlib/ts/wasmlib/context.ts b/packages/vm/wasmlib/ts/wasmlib/context.ts index f6bddb0c90..13ab878698 100644 --- a/packages/vm/wasmlib/ts/wasmlib/context.ts +++ b/packages/vm/wasmlib/ts/wasmlib/context.ts @@ -7,7 +7,7 @@ import {BytesDecoder, BytesEncoder} from "./bytes"; import {Convert} from "./convert"; import {ScFuncCallContext, ScViewCallContext} from "./contract"; import {ScAddress, ScAgentID, ScChainID, ScColor, ScHash, ScHname, ScRequestID} from "./hashtypes"; -import {log, OBJ_ID_ROOT, panic} from "./host"; +import {log, OBJ_ID_ROOT, OBJ_ID_STATE, panic} from "./host"; import {ScImmutableColorArray, ScImmutableMap} from "./immutable"; import * as keys from "./keys"; import {ScMutableMap} from "./mutable"; @@ -163,13 +163,6 @@ export class ScUtility { let result = this.utility.callFunc(keys.KEY_HNAME, Convert.fromString(name)); return ScHname.fromBytes(result); } - - // generates a random value from 0 to max (exclusive max) using a deterministic RNG - random(max: i64): i64 { - let result = this.utility.callFunc(keys.KEY_RANDOM, []); - let rnd = Convert.toI64(result); - return (rnd as u64 % max as u64) as i64; - } } // wrapper function for simplified internal access to base58 encoding @@ -279,11 +272,6 @@ export class ScFuncContext extends ScBaseContext implements ScViewCallContext, S return ROOT.getMap(keys.KEY_RETURN).immutable(); } - // shorthand to synchronously call a smart contract function of the current contract - callSelf(hfunction: ScHname, params: ScMutableMap | null, transfers: ScTransfers | null): ScImmutableMap { - return this.call(this.contract(), hfunction, params, transfers); - } - // retrieve the agent id of the caller of the smart contract caller(): ScAgentID { return ROOT.getAgentID(keys.KEY_CALLER).value(); @@ -329,9 +317,16 @@ export class ScFuncContext extends ScBaseContext implements ScViewCallContext, S ROOT.getBytes(keys.KEY_POST).setValue(encode.data()); } - // shorthand to asynchronously call a smart contract function of the current contract - postSelf(hfunction: ScHname, params: ScMutableMap | null, transfer: ScTransfers, delay: i32): void { - this.post(this.chainID(), this.contract(), hfunction, params, transfer, delay); + // generates a random value from 0 to max (exclusive max) using a deterministic RNG + random(max: i64): i64 { + let state = new ScMutableMap(OBJ_ID_STATE); + let rnd = state.getBytes(keys.KEY_RANDOM); + let seed = rnd.value(); + if (seed.length == 0) { + seed = ROOT.getBytes(keys.KEY_RANDOM).value(); + } + rnd.setValue(this.utility().hashSha3(seed).toBytes()); + return (Convert.toI64(seed.slice(0, 8)) as u64 % max as u64) as i64; } // retrieve the request id of this transaction @@ -373,11 +368,6 @@ export class ScViewContext extends ScBaseContext implements ScViewCallContext { return ROOT.getMap(keys.KEY_RETURN).immutable(); } - // shorthand to synchronously call a smart contract view of the current contract - callSelf(hfunction: ScHname, params: ScMutableMap | null): ScImmutableMap { - return this.call(this.contract(), hfunction, params); - } - // access immutable state storage on the host state(): ScImmutableMap { return ROOT.getMap(keys.KEY_STATE).immutable(); diff --git a/packages/vm/wasmlib/ts/wasmlib/coreaccounts/consts.ts b/packages/vm/wasmlib/ts/wasmlib/coreaccounts/consts.ts index 82006e4680..967aa43c5f 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreaccounts/consts.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreaccounts/consts.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export const ScName = "accounts"; export const ScDescription = "Core chain account ledger contract"; @@ -16,6 +16,8 @@ export const ParamWithdrawAmount = "m"; export const ParamWithdrawColor = "c"; export const ResultAccountNonce = "n"; +export const ResultAgents = "this"; +export const ResultBalances = "this"; export const FuncDeposit = "deposit"; export const FuncHarvest = "harvest"; diff --git a/packages/vm/wasmlib/ts/wasmlib/coreaccounts/contract.ts b/packages/vm/wasmlib/ts/wasmlib/coreaccounts/contract.ts index f969323f7d..a8fa2cb85b 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreaccounts/contract.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreaccounts/contract.ts @@ -5,47 +5,46 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class DepositCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDeposit); - params: sc.MutableDepositParams = new sc.MutableDepositParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDeposit); + params: sc.MutableDepositParams = new sc.MutableDepositParams(); } export class HarvestCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncHarvest); - params: sc.MutableHarvestParams = new sc.MutableHarvestParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncHarvest); + params: sc.MutableHarvestParams = new sc.MutableHarvestParams(); } export class WithdrawCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncWithdraw); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncWithdraw); } export class AccountsCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewAccounts); - results: sc.ImmutableAccountsResults = new sc.ImmutableAccountsResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewAccounts); + results: sc.ImmutableAccountsResults = new sc.ImmutableAccountsResults(); } export class BalanceCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewBalance); - params: sc.MutableBalanceParams = new sc.MutableBalanceParams(); - results: sc.ImmutableBalanceResults = new sc.ImmutableBalanceResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewBalance); + params: sc.MutableBalanceParams = new sc.MutableBalanceParams(); + results: sc.ImmutableBalanceResults = new sc.ImmutableBalanceResults(); } export class GetAccountNonceCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetAccountNonce); - params: sc.MutableGetAccountNonceParams = new sc.MutableGetAccountNonceParams(); - results: sc.ImmutableGetAccountNonceResults = new sc.ImmutableGetAccountNonceResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetAccountNonce); + params: sc.MutableGetAccountNonceParams = new sc.MutableGetAccountNonceParams(); + results: sc.ImmutableGetAccountNonceResults = new sc.ImmutableGetAccountNonceResults(); } export class TotalAssetsCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTotalAssets); - results: sc.ImmutableTotalAssetsResults = new sc.ImmutableTotalAssetsResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewTotalAssets); + results: sc.ImmutableTotalAssetsResults = new sc.ImmutableTotalAssetsResults(); } export class ScFuncs { - static deposit(ctx: wasmlib.ScFuncCallContext): DepositCall { let f = new DepositCall(); f.func.setPtrs(f.params, null); @@ -59,8 +58,7 @@ export class ScFuncs { } static withdraw(ctx: wasmlib.ScFuncCallContext): WithdrawCall { - let f = new WithdrawCall(); - return f; + return new WithdrawCall(); } static accounts(ctx: wasmlib.ScViewCallContext): AccountsCall { diff --git a/packages/vm/wasmlib/ts/wasmlib/coreaccounts/params.ts b/packages/vm/wasmlib/ts/wasmlib/coreaccounts/params.ts index 3ab645fd6e..973afb6f3e 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreaccounts/params.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreaccounts/params.ts @@ -5,69 +5,61 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ImmutableDepositParams extends wasmlib.ScMapID { - agentID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); - } + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); + } } export class MutableDepositParams extends wasmlib.ScMapID { - agentID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); - } + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); + } } export class ImmutableHarvestParams extends wasmlib.ScMapID { - withdrawAmount(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamWithdrawAmount)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamWithdrawAmount)); + } withdrawColor(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamWithdrawColor)); - } + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamWithdrawColor)); + } } export class MutableHarvestParams extends wasmlib.ScMapID { - withdrawAmount(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamWithdrawAmount)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamWithdrawAmount)); + } withdrawColor(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamWithdrawColor)); - } + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamWithdrawColor)); + } } export class ImmutableBalanceParams extends wasmlib.ScMapID { - agentID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); - } + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); + } } export class MutableBalanceParams extends wasmlib.ScMapID { - agentID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); - } + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); + } } export class ImmutableGetAccountNonceParams extends wasmlib.ScMapID { - agentID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); - } + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); + } } export class MutableGetAccountNonceParams extends wasmlib.ScMapID { - agentID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); - } + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamAgentID)); + } } diff --git a/packages/vm/wasmlib/ts/wasmlib/coreaccounts/results.ts b/packages/vm/wasmlib/ts/wasmlib/coreaccounts/results.ts index e0eb7ca6ea..a6c043e58f 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreaccounts/results.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreaccounts/results.ts @@ -5,11 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class MapAgentIDToImmutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -21,21 +21,20 @@ export class MapAgentIDToImmutableBytes { } export class ImmutableAccountsResults extends wasmlib.ScMapID { - agents(): sc.MapAgentIDToImmutableBytes { - return new sc.MapAgentIDToImmutableBytes(this.mapID); - } + return new sc.MapAgentIDToImmutableBytes(this.mapID); + } } export class MapAgentIDToMutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getBytes(key: wasmlib.ScAgentID): wasmlib.ScMutableBytes { @@ -44,14 +43,13 @@ export class MapAgentIDToMutableBytes { } export class MutableAccountsResults extends wasmlib.ScMapID { - agents(): sc.MapAgentIDToMutableBytes { - return new sc.MapAgentIDToMutableBytes(this.mapID); - } + return new sc.MapAgentIDToMutableBytes(this.mapID); + } } export class MapColorToImmutableInt64 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -63,21 +61,20 @@ export class MapColorToImmutableInt64 { } export class ImmutableBalanceResults extends wasmlib.ScMapID { - balances(): sc.MapColorToImmutableInt64 { - return new sc.MapColorToImmutableInt64(this.mapID); - } + return new sc.MapColorToImmutableInt64(this.mapID); + } } export class MapColorToMutableInt64 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getInt64(key: wasmlib.ScColor): wasmlib.ScMutableInt64 { @@ -86,36 +83,31 @@ export class MapColorToMutableInt64 { } export class MutableBalanceResults extends wasmlib.ScMapID { - balances(): sc.MapColorToMutableInt64 { - return new sc.MapColorToMutableInt64(this.mapID); - } + return new sc.MapColorToMutableInt64(this.mapID); + } } export class ImmutableGetAccountNonceResults extends wasmlib.ScMapID { - accountNonce(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultAccountNonce)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultAccountNonce)); + } } export class MutableGetAccountNonceResults extends wasmlib.ScMapID { - accountNonce(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultAccountNonce)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultAccountNonce)); + } } export class ImmutableTotalAssetsResults extends wasmlib.ScMapID { - balances(): sc.MapColorToImmutableInt64 { - return new sc.MapColorToImmutableInt64(this.mapID); - } + return new sc.MapColorToImmutableInt64(this.mapID); + } } export class MutableTotalAssetsResults extends wasmlib.ScMapID { - balances(): sc.MapColorToMutableInt64 { - return new sc.MapColorToMutableInt64(this.mapID); - } + return new sc.MapColorToMutableInt64(this.mapID); + } } diff --git a/packages/vm/wasmlib/ts/wasmlib/coreblob/consts.ts b/packages/vm/wasmlib/ts/wasmlib/coreblob/consts.ts index 0e49977214..9293fa2b4f 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreblob/consts.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreblob/consts.ts @@ -5,17 +5,19 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export const ScName = "blob"; export const ScDescription = "Core blob contract"; export const HScName = new wasmlib.ScHname(0xfd91bc63); +export const ParamBlobs = "this"; export const ParamField = "field"; export const ParamHash = "hash"; -export const ResultBytes = "bytes"; -export const ResultHash = "hash"; +export const ResultBlobSizes = "this"; +export const ResultBytes = "bytes"; +export const ResultHash = "hash"; export const FuncStoreBlob = "storeBlob"; export const ViewGetBlobField = "getBlobField"; diff --git a/packages/vm/wasmlib/ts/wasmlib/coreblob/contract.ts b/packages/vm/wasmlib/ts/wasmlib/coreblob/contract.ts index 7fd8422de0..61e3359ae3 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreblob/contract.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreblob/contract.ts @@ -5,34 +5,33 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class StoreBlobCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncStoreBlob); - params: sc.MutableStoreBlobParams = new sc.MutableStoreBlobParams(); - results: sc.ImmutableStoreBlobResults = new sc.ImmutableStoreBlobResults(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncStoreBlob); + params: sc.MutableStoreBlobParams = new sc.MutableStoreBlobParams(); + results: sc.ImmutableStoreBlobResults = new sc.ImmutableStoreBlobResults(); } export class GetBlobFieldCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetBlobField); - params: sc.MutableGetBlobFieldParams = new sc.MutableGetBlobFieldParams(); - results: sc.ImmutableGetBlobFieldResults = new sc.ImmutableGetBlobFieldResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetBlobField); + params: sc.MutableGetBlobFieldParams = new sc.MutableGetBlobFieldParams(); + results: sc.ImmutableGetBlobFieldResults = new sc.ImmutableGetBlobFieldResults(); } export class GetBlobInfoCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetBlobInfo); - params: sc.MutableGetBlobInfoParams = new sc.MutableGetBlobInfoParams(); - results: sc.ImmutableGetBlobInfoResults = new sc.ImmutableGetBlobInfoResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetBlobInfo); + params: sc.MutableGetBlobInfoParams = new sc.MutableGetBlobInfoParams(); + results: sc.ImmutableGetBlobInfoResults = new sc.ImmutableGetBlobInfoResults(); } export class ListBlobsCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewListBlobs); - results: sc.ImmutableListBlobsResults = new sc.ImmutableListBlobsResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewListBlobs); + results: sc.ImmutableListBlobsResults = new sc.ImmutableListBlobsResults(); } export class ScFuncs { - static storeBlob(ctx: wasmlib.ScFuncCallContext): StoreBlobCall { let f = new StoreBlobCall(); f.func.setPtrs(f.params, f.results); diff --git a/packages/vm/wasmlib/ts/wasmlib/coreblob/params.ts b/packages/vm/wasmlib/ts/wasmlib/coreblob/params.ts index 0c86f3ab50..b334596688 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreblob/params.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreblob/params.ts @@ -5,83 +5,77 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class MapStringToImmutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } getBytes(key: string): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.objID, wasmlib.Key32.fromString(key).getKeyID()); + return new wasmlib.ScImmutableBytes(this.objID, wasmlib.Key32.fromString(key)); } } export class ImmutableStoreBlobParams extends wasmlib.ScMapID { - blobs(): sc.MapStringToImmutableBytes { - return new sc.MapStringToImmutableBytes(this.mapID); - } + return new sc.MapStringToImmutableBytes(this.mapID); + } } export class MapStringToMutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getBytes(key: string): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.objID, wasmlib.Key32.fromString(key).getKeyID()); + return new wasmlib.ScMutableBytes(this.objID, wasmlib.Key32.fromString(key)); } } export class MutableStoreBlobParams extends wasmlib.ScMapID { - blobs(): sc.MapStringToMutableBytes { - return new sc.MapStringToMutableBytes(this.mapID); - } + return new sc.MapStringToMutableBytes(this.mapID); + } } export class ImmutableGetBlobFieldParams extends wasmlib.ScMapID { - field(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamField)); - } + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamField)); + } hash(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); - } + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); + } } export class MutableGetBlobFieldParams extends wasmlib.ScMapID { - field(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamField)); - } + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamField)); + } hash(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); - } + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); + } } export class ImmutableGetBlobInfoParams extends wasmlib.ScMapID { - hash(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); - } + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); + } } export class MutableGetBlobInfoParams extends wasmlib.ScMapID { - hash(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); - } + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamHash)); + } } diff --git a/packages/vm/wasmlib/ts/wasmlib/coreblob/results.ts b/packages/vm/wasmlib/ts/wasmlib/coreblob/results.ts index ec64602e60..f10b4bf968 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreblob/results.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreblob/results.ts @@ -5,81 +5,75 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ImmutableStoreBlobResults extends wasmlib.ScMapID { - hash(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ResultHash)); - } + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ResultHash)); + } } export class MutableStoreBlobResults extends wasmlib.ScMapID { - hash(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ResultHash)); - } + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ResultHash)); + } } export class ImmutableGetBlobFieldResults extends wasmlib.ScMapID { - bytes(): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBytes)); - } + return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBytes)); + } } export class MutableGetBlobFieldResults extends wasmlib.ScMapID { - bytes(): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBytes)); - } + return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBytes)); + } } export class MapStringToImmutableInt32 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } getInt32(key: string): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.objID, wasmlib.Key32.fromString(key).getKeyID()); + return new wasmlib.ScImmutableInt32(this.objID, wasmlib.Key32.fromString(key)); } } export class ImmutableGetBlobInfoResults extends wasmlib.ScMapID { - blobSizes(): sc.MapStringToImmutableInt32 { - return new sc.MapStringToImmutableInt32(this.mapID); - } + return new sc.MapStringToImmutableInt32(this.mapID); + } } export class MapStringToMutableInt32 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getInt32(key: string): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.objID, wasmlib.Key32.fromString(key).getKeyID()); + return new wasmlib.ScMutableInt32(this.objID, wasmlib.Key32.fromString(key)); } } export class MutableGetBlobInfoResults extends wasmlib.ScMapID { - blobSizes(): sc.MapStringToMutableInt32 { - return new sc.MapStringToMutableInt32(this.mapID); - } + return new sc.MapStringToMutableInt32(this.mapID); + } } export class MapHashToImmutableInt32 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -91,21 +85,20 @@ export class MapHashToImmutableInt32 { } export class ImmutableListBlobsResults extends wasmlib.ScMapID { - blobSizes(): sc.MapHashToImmutableInt32 { - return new sc.MapHashToImmutableInt32(this.mapID); - } + return new sc.MapHashToImmutableInt32(this.mapID); + } } export class MapHashToMutableInt32 { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getInt32(key: wasmlib.ScHash): wasmlib.ScMutableInt32 { @@ -114,8 +107,7 @@ export class MapHashToMutableInt32 { } export class MutableListBlobsResults extends wasmlib.ScMapID { - blobSizes(): sc.MapHashToMutableInt32 { - return new sc.MapHashToMutableInt32(this.mapID); - } + return new sc.MapHashToMutableInt32(this.mapID); + } } diff --git a/packages/vm/wasmlib/ts/wasmlib/coreblocklog/consts.ts b/packages/vm/wasmlib/ts/wasmlib/coreblocklog/consts.ts index 11238f332a..8525d71f43 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreblocklog/consts.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreblocklog/consts.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export const ScName = "blocklog"; export const ScDescription = "Core block log contract"; diff --git a/packages/vm/wasmlib/ts/wasmlib/coreblocklog/contract.ts b/packages/vm/wasmlib/ts/wasmlib/coreblocklog/contract.ts index ffc38aef7e..4c7fe2800f 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreblocklog/contract.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreblocklog/contract.ts @@ -5,69 +5,68 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ControlAddressesCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewControlAddresses); - results: sc.ImmutableControlAddressesResults = new sc.ImmutableControlAddressesResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewControlAddresses); + results: sc.ImmutableControlAddressesResults = new sc.ImmutableControlAddressesResults(); } export class GetBlockInfoCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetBlockInfo); - params: sc.MutableGetBlockInfoParams = new sc.MutableGetBlockInfoParams(); - results: sc.ImmutableGetBlockInfoResults = new sc.ImmutableGetBlockInfoResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetBlockInfo); + params: sc.MutableGetBlockInfoParams = new sc.MutableGetBlockInfoParams(); + results: sc.ImmutableGetBlockInfoResults = new sc.ImmutableGetBlockInfoResults(); } export class GetEventsForBlockCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetEventsForBlock); - params: sc.MutableGetEventsForBlockParams = new sc.MutableGetEventsForBlockParams(); - results: sc.ImmutableGetEventsForBlockResults = new sc.ImmutableGetEventsForBlockResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetEventsForBlock); + params: sc.MutableGetEventsForBlockParams = new sc.MutableGetEventsForBlockParams(); + results: sc.ImmutableGetEventsForBlockResults = new sc.ImmutableGetEventsForBlockResults(); } export class GetEventsForContractCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetEventsForContract); - params: sc.MutableGetEventsForContractParams = new sc.MutableGetEventsForContractParams(); - results: sc.ImmutableGetEventsForContractResults = new sc.ImmutableGetEventsForContractResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetEventsForContract); + params: sc.MutableGetEventsForContractParams = new sc.MutableGetEventsForContractParams(); + results: sc.ImmutableGetEventsForContractResults = new sc.ImmutableGetEventsForContractResults(); } export class GetEventsForRequestCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetEventsForRequest); - params: sc.MutableGetEventsForRequestParams = new sc.MutableGetEventsForRequestParams(); - results: sc.ImmutableGetEventsForRequestResults = new sc.ImmutableGetEventsForRequestResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetEventsForRequest); + params: sc.MutableGetEventsForRequestParams = new sc.MutableGetEventsForRequestParams(); + results: sc.ImmutableGetEventsForRequestResults = new sc.ImmutableGetEventsForRequestResults(); } export class GetLatestBlockInfoCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetLatestBlockInfo); - results: sc.ImmutableGetLatestBlockInfoResults = new sc.ImmutableGetLatestBlockInfoResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetLatestBlockInfo); + results: sc.ImmutableGetLatestBlockInfoResults = new sc.ImmutableGetLatestBlockInfoResults(); } export class GetRequestIDsForBlockCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetRequestIDsForBlock); - params: sc.MutableGetRequestIDsForBlockParams = new sc.MutableGetRequestIDsForBlockParams(); - results: sc.ImmutableGetRequestIDsForBlockResults = new sc.ImmutableGetRequestIDsForBlockResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetRequestIDsForBlock); + params: sc.MutableGetRequestIDsForBlockParams = new sc.MutableGetRequestIDsForBlockParams(); + results: sc.ImmutableGetRequestIDsForBlockResults = new sc.ImmutableGetRequestIDsForBlockResults(); } export class GetRequestReceiptCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetRequestReceipt); - params: sc.MutableGetRequestReceiptParams = new sc.MutableGetRequestReceiptParams(); - results: sc.ImmutableGetRequestReceiptResults = new sc.ImmutableGetRequestReceiptResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetRequestReceipt); + params: sc.MutableGetRequestReceiptParams = new sc.MutableGetRequestReceiptParams(); + results: sc.ImmutableGetRequestReceiptResults = new sc.ImmutableGetRequestReceiptResults(); } export class GetRequestReceiptsForBlockCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetRequestReceiptsForBlock); - params: sc.MutableGetRequestReceiptsForBlockParams = new sc.MutableGetRequestReceiptsForBlockParams(); - results: sc.ImmutableGetRequestReceiptsForBlockResults = new sc.ImmutableGetRequestReceiptsForBlockResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetRequestReceiptsForBlock); + params: sc.MutableGetRequestReceiptsForBlockParams = new sc.MutableGetRequestReceiptsForBlockParams(); + results: sc.ImmutableGetRequestReceiptsForBlockResults = new sc.ImmutableGetRequestReceiptsForBlockResults(); } export class IsRequestProcessedCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewIsRequestProcessed); - params: sc.MutableIsRequestProcessedParams = new sc.MutableIsRequestProcessedParams(); - results: sc.ImmutableIsRequestProcessedResults = new sc.ImmutableIsRequestProcessedResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewIsRequestProcessed); + params: sc.MutableIsRequestProcessedParams = new sc.MutableIsRequestProcessedParams(); + results: sc.ImmutableIsRequestProcessedResults = new sc.ImmutableIsRequestProcessedResults(); } export class ScFuncs { - static controlAddresses(ctx: wasmlib.ScViewCallContext): ControlAddressesCall { let f = new ControlAddressesCall(); f.func.setPtrs(null, f.results); diff --git a/packages/vm/wasmlib/ts/wasmlib/coreblocklog/params.ts b/packages/vm/wasmlib/ts/wasmlib/coreblocklog/params.ts index a9907bfb27..0343cbf2e7 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreblocklog/params.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreblocklog/params.ts @@ -5,133 +5,117 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ImmutableGetBlockInfoParams extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); + } } export class MutableGetBlockInfoParams extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); + } } export class ImmutableGetEventsForBlockParams extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); + } } export class MutableGetEventsForBlockParams extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); + } } export class ImmutableGetEventsForContractParams extends wasmlib.ScMapID { - contractHname(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamContractHname)); - } + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamContractHname)); + } fromBlock(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamFromBlock)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamFromBlock)); + } toBlock(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamToBlock)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamToBlock)); + } } export class MutableGetEventsForContractParams extends wasmlib.ScMapID { - contractHname(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamContractHname)); - } + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamContractHname)); + } fromBlock(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamFromBlock)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamFromBlock)); + } toBlock(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamToBlock)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamToBlock)); + } } export class ImmutableGetEventsForRequestParams extends wasmlib.ScMapID { - requestID(): wasmlib.ScImmutableRequestID { - return new wasmlib.ScImmutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); - } + return new wasmlib.ScImmutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); + } } export class MutableGetEventsForRequestParams extends wasmlib.ScMapID { - requestID(): wasmlib.ScMutableRequestID { - return new wasmlib.ScMutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); - } + return new wasmlib.ScMutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); + } } export class ImmutableGetRequestIDsForBlockParams extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); + } } export class MutableGetRequestIDsForBlockParams extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); + } } export class ImmutableGetRequestReceiptParams extends wasmlib.ScMapID { - requestID(): wasmlib.ScImmutableRequestID { - return new wasmlib.ScImmutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); - } + return new wasmlib.ScImmutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); + } } export class MutableGetRequestReceiptParams extends wasmlib.ScMapID { - requestID(): wasmlib.ScMutableRequestID { - return new wasmlib.ScMutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); - } + return new wasmlib.ScMutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); + } } export class ImmutableGetRequestReceiptsForBlockParams extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); + } } export class MutableGetRequestReceiptsForBlockParams extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamBlockIndex)); + } } export class ImmutableIsRequestProcessedParams extends wasmlib.ScMapID { - requestID(): wasmlib.ScImmutableRequestID { - return new wasmlib.ScImmutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); - } + return new wasmlib.ScImmutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); + } } export class MutableIsRequestProcessedParams extends wasmlib.ScMapID { - requestID(): wasmlib.ScMutableRequestID { - return new wasmlib.ScMutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); - } + return new wasmlib.ScMutableRequestID(this.mapID, wasmlib.Key32.fromString(sc.ParamRequestID)); + } } diff --git a/packages/vm/wasmlib/ts/wasmlib/coreblocklog/results.ts b/packages/vm/wasmlib/ts/wasmlib/coreblocklog/results.ts index 01852ab376..0cdeab00e9 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreblocklog/results.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreblocklog/results.ts @@ -5,55 +5,51 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ImmutableControlAddressesResults extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); + } governingAddress(): wasmlib.ScImmutableAddress { - return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ResultGoverningAddress)); - } + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ResultGoverningAddress)); + } stateControllerAddress(): wasmlib.ScImmutableAddress { - return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ResultStateControllerAddress)); - } + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ResultStateControllerAddress)); + } } export class MutableControlAddressesResults extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); + } governingAddress(): wasmlib.ScMutableAddress { - return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ResultGoverningAddress)); - } + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ResultGoverningAddress)); + } stateControllerAddress(): wasmlib.ScMutableAddress { - return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ResultStateControllerAddress)); - } + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ResultStateControllerAddress)); + } } export class ImmutableGetBlockInfoResults extends wasmlib.ScMapID { - blockInfo(): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockInfo)); - } + return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockInfo)); + } } export class MutableGetBlockInfoResults extends wasmlib.ScMapID { - blockInfo(): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockInfo)); - } + return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockInfo)); + } } export class ArrayOfImmutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -69,15 +65,14 @@ export class ArrayOfImmutableBytes { } export class ImmutableGetEventsForBlockResults extends wasmlib.ScMapID { - event(): sc.ArrayOfImmutableBytes { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); - return new sc.ArrayOfImmutableBytes(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); + return new sc.ArrayOfImmutableBytes(arrID); + } } export class ArrayOfMutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -97,69 +92,62 @@ export class ArrayOfMutableBytes { } export class MutableGetEventsForBlockResults extends wasmlib.ScMapID { - event(): sc.ArrayOfMutableBytes { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); - return new sc.ArrayOfMutableBytes(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); + return new sc.ArrayOfMutableBytes(arrID); + } } export class ImmutableGetEventsForContractResults extends wasmlib.ScMapID { - event(): sc.ArrayOfImmutableBytes { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); - return new sc.ArrayOfImmutableBytes(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); + return new sc.ArrayOfImmutableBytes(arrID); + } } export class MutableGetEventsForContractResults extends wasmlib.ScMapID { - event(): sc.ArrayOfMutableBytes { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); - return new sc.ArrayOfMutableBytes(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); + return new sc.ArrayOfMutableBytes(arrID); + } } export class ImmutableGetEventsForRequestResults extends wasmlib.ScMapID { - event(): sc.ArrayOfImmutableBytes { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); - return new sc.ArrayOfImmutableBytes(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); + return new sc.ArrayOfImmutableBytes(arrID); + } } export class MutableGetEventsForRequestResults extends wasmlib.ScMapID { - event(): sc.ArrayOfMutableBytes { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); - return new sc.ArrayOfMutableBytes(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultEvent), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); + return new sc.ArrayOfMutableBytes(arrID); + } } export class ImmutableGetLatestBlockInfoResults extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); + } blockInfo(): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockInfo)); - } + return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockInfo)); + } } export class MutableGetLatestBlockInfoResults extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); + } blockInfo(): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockInfo)); - } + return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockInfo)); + } } export class ArrayOfImmutableRequestID { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -175,15 +163,14 @@ export class ArrayOfImmutableRequestID { } export class ImmutableGetRequestIDsForBlockResults extends wasmlib.ScMapID { - requestID(): sc.ArrayOfImmutableRequestID { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestID), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_REQUEST_ID); - return new sc.ArrayOfImmutableRequestID(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestID), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_REQUEST_ID); + return new sc.ArrayOfImmutableRequestID(arrID); + } } export class ArrayOfMutableRequestID { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -203,69 +190,62 @@ export class ArrayOfMutableRequestID { } export class MutableGetRequestIDsForBlockResults extends wasmlib.ScMapID { - requestID(): sc.ArrayOfMutableRequestID { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestID), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_REQUEST_ID); - return new sc.ArrayOfMutableRequestID(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestID), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_REQUEST_ID); + return new sc.ArrayOfMutableRequestID(arrID); + } } export class ImmutableGetRequestReceiptResults extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); + } requestIndex(): wasmlib.ScImmutableInt16 { - return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestIndex)); - } + return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestIndex)); + } requestRecord(): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestRecord)); - } + return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestRecord)); + } } export class MutableGetRequestReceiptResults extends wasmlib.ScMapID { - blockIndex(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultBlockIndex)); + } requestIndex(): wasmlib.ScMutableInt16 { - return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestIndex)); - } + return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestIndex)); + } requestRecord(): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestRecord)); - } + return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestRecord)); + } } export class ImmutableGetRequestReceiptsForBlockResults extends wasmlib.ScMapID { - requestRecord(): sc.ArrayOfImmutableBytes { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestRecord), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); - return new sc.ArrayOfImmutableBytes(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestRecord), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); + return new sc.ArrayOfImmutableBytes(arrID); + } } export class MutableGetRequestReceiptsForBlockResults extends wasmlib.ScMapID { - requestRecord(): sc.ArrayOfMutableBytes { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestRecord), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); - return new sc.ArrayOfMutableBytes(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestRecord), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); + return new sc.ArrayOfMutableBytes(arrID); + } } export class ImmutableIsRequestProcessedResults extends wasmlib.ScMapID { - requestProcessed(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestProcessed)); - } + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestProcessed)); + } } export class MutableIsRequestProcessedResults extends wasmlib.ScMapID { - requestProcessed(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestProcessed)); - } + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultRequestProcessed)); + } } diff --git a/packages/vm/wasmlib/ts/wasmlib/coregovernance/consts.ts b/packages/vm/wasmlib/ts/wasmlib/coregovernance/consts.ts index c3ea510454..bc538fbb2b 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coregovernance/consts.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coregovernance/consts.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export const ScName = "governance"; export const ScDescription = "Core governance contract"; diff --git a/packages/vm/wasmlib/ts/wasmlib/coregovernance/contract.ts b/packages/vm/wasmlib/ts/wasmlib/coregovernance/contract.ts index dfc45e5702..045e454730 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coregovernance/contract.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coregovernance/contract.ts @@ -5,71 +5,70 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class AddAllowedStateControllerAddressCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncAddAllowedStateControllerAddress); - params: sc.MutableAddAllowedStateControllerAddressParams = new sc.MutableAddAllowedStateControllerAddressParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncAddAllowedStateControllerAddress); + params: sc.MutableAddAllowedStateControllerAddressParams = new sc.MutableAddAllowedStateControllerAddressParams(); } export class ClaimChainOwnershipCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncClaimChainOwnership); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncClaimChainOwnership); } export class DelegateChainOwnershipCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDelegateChainOwnership); - params: sc.MutableDelegateChainOwnershipParams = new sc.MutableDelegateChainOwnershipParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDelegateChainOwnership); + params: sc.MutableDelegateChainOwnershipParams = new sc.MutableDelegateChainOwnershipParams(); } export class RemoveAllowedStateControllerAddressCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncRemoveAllowedStateControllerAddress); - params: sc.MutableRemoveAllowedStateControllerAddressParams = new sc.MutableRemoveAllowedStateControllerAddressParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncRemoveAllowedStateControllerAddress); + params: sc.MutableRemoveAllowedStateControllerAddressParams = new sc.MutableRemoveAllowedStateControllerAddressParams(); } export class RotateStateControllerCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncRotateStateController); - params: sc.MutableRotateStateControllerParams = new sc.MutableRotateStateControllerParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncRotateStateController); + params: sc.MutableRotateStateControllerParams = new sc.MutableRotateStateControllerParams(); } export class SetChainInfoCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetChainInfo); - params: sc.MutableSetChainInfoParams = new sc.MutableSetChainInfoParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetChainInfo); + params: sc.MutableSetChainInfoParams = new sc.MutableSetChainInfoParams(); } export class SetContractFeeCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetContractFee); - params: sc.MutableSetContractFeeParams = new sc.MutableSetContractFeeParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetContractFee); + params: sc.MutableSetContractFeeParams = new sc.MutableSetContractFeeParams(); } export class SetDefaultFeeCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetDefaultFee); - params: sc.MutableSetDefaultFeeParams = new sc.MutableSetDefaultFeeParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncSetDefaultFee); + params: sc.MutableSetDefaultFeeParams = new sc.MutableSetDefaultFeeParams(); } export class GetAllowedStateControllerAddressesCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetAllowedStateControllerAddresses); - results: sc.ImmutableGetAllowedStateControllerAddressesResults = new sc.ImmutableGetAllowedStateControllerAddressesResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetAllowedStateControllerAddresses); + results: sc.ImmutableGetAllowedStateControllerAddressesResults = new sc.ImmutableGetAllowedStateControllerAddressesResults(); } export class GetChainInfoCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetChainInfo); - results: sc.ImmutableGetChainInfoResults = new sc.ImmutableGetChainInfoResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetChainInfo); + results: sc.ImmutableGetChainInfoResults = new sc.ImmutableGetChainInfoResults(); } export class GetFeeInfoCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetFeeInfo); - params: sc.MutableGetFeeInfoParams = new sc.MutableGetFeeInfoParams(); - results: sc.ImmutableGetFeeInfoResults = new sc.ImmutableGetFeeInfoResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetFeeInfo); + params: sc.MutableGetFeeInfoParams = new sc.MutableGetFeeInfoParams(); + results: sc.ImmutableGetFeeInfoResults = new sc.ImmutableGetFeeInfoResults(); } export class GetMaxBlobSizeCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetMaxBlobSize); - results: sc.ImmutableGetMaxBlobSizeResults = new sc.ImmutableGetMaxBlobSizeResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetMaxBlobSize); + results: sc.ImmutableGetMaxBlobSizeResults = new sc.ImmutableGetMaxBlobSizeResults(); } export class ScFuncs { - static addAllowedStateControllerAddress(ctx: wasmlib.ScFuncCallContext): AddAllowedStateControllerAddressCall { let f = new AddAllowedStateControllerAddressCall(); f.func.setPtrs(f.params, null); @@ -77,8 +76,7 @@ export class ScFuncs { } static claimChainOwnership(ctx: wasmlib.ScFuncCallContext): ClaimChainOwnershipCall { - let f = new ClaimChainOwnershipCall(); - return f; + return new ClaimChainOwnershipCall(); } static delegateChainOwnership(ctx: wasmlib.ScFuncCallContext): DelegateChainOwnershipCall { diff --git a/packages/vm/wasmlib/ts/wasmlib/coregovernance/params.ts b/packages/vm/wasmlib/ts/wasmlib/coregovernance/params.ts index 7a42ac6c0f..8e0b37cb46 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coregovernance/params.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coregovernance/params.ts @@ -5,189 +5,173 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ImmutableAddAllowedStateControllerAddressParams extends wasmlib.ScMapID { - chainOwner(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwner)); - } + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwner)); + } feeColor(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamFeeColor)); - } + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamFeeColor)); + } stateControllerAddress(): wasmlib.ScImmutableAddress { - return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); - } + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); + } } export class MutableAddAllowedStateControllerAddressParams extends wasmlib.ScMapID { - chainOwner(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwner)); - } + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwner)); + } feeColor(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamFeeColor)); - } + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ParamFeeColor)); + } stateControllerAddress(): wasmlib.ScMutableAddress { - return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); - } + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); + } } export class ImmutableDelegateChainOwnershipParams extends wasmlib.ScMapID { - chainOwner(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwner)); - } + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwner)); + } } export class MutableDelegateChainOwnershipParams extends wasmlib.ScMapID { - chainOwner(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwner)); - } + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamChainOwner)); + } } export class ImmutableRemoveAllowedStateControllerAddressParams extends wasmlib.ScMapID { - stateControllerAddress(): wasmlib.ScImmutableAddress { - return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); - } + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); + } } export class MutableRemoveAllowedStateControllerAddressParams extends wasmlib.ScMapID { - stateControllerAddress(): wasmlib.ScMutableAddress { - return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); - } + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); + } } export class ImmutableRotateStateControllerParams extends wasmlib.ScMapID { - stateControllerAddress(): wasmlib.ScImmutableAddress { - return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); - } + return new wasmlib.ScImmutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); + } } export class MutableRotateStateControllerParams extends wasmlib.ScMapID { - stateControllerAddress(): wasmlib.ScMutableAddress { - return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); - } + return new wasmlib.ScMutableAddress(this.mapID, wasmlib.Key32.fromString(sc.ParamStateControllerAddress)); + } } export class ImmutableSetChainInfoParams extends wasmlib.ScMapID { - maxBlobSize(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxBlobSize)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxBlobSize)); + } maxEventSize(): wasmlib.ScImmutableInt16 { - return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxEventSize)); - } + return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxEventSize)); + } maxEventsPerReq(): wasmlib.ScImmutableInt16 { - return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxEventsPerReq)); - } + return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxEventsPerReq)); + } ownerFee(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); + } validatorFee(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); + } } export class MutableSetChainInfoParams extends wasmlib.ScMapID { - maxBlobSize(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxBlobSize)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxBlobSize)); + } maxEventSize(): wasmlib.ScMutableInt16 { - return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxEventSize)); - } + return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxEventSize)); + } maxEventsPerReq(): wasmlib.ScMutableInt16 { - return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxEventsPerReq)); - } + return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ParamMaxEventsPerReq)); + } ownerFee(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); + } validatorFee(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); + } } export class ImmutableSetContractFeeParams extends wasmlib.ScMapID { - hname(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); - } + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); + } ownerFee(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); + } validatorFee(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); + } } export class MutableSetContractFeeParams extends wasmlib.ScMapID { - hname(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); - } + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); + } ownerFee(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); + } validatorFee(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); + } } export class ImmutableSetDefaultFeeParams extends wasmlib.ScMapID { - ownerFee(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); + } validatorFee(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); + } } export class MutableSetDefaultFeeParams extends wasmlib.ScMapID { - ownerFee(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamOwnerFee)); + } validatorFee(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ParamValidatorFee)); + } } export class ImmutableGetFeeInfoParams extends wasmlib.ScMapID { - hname(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); - } + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); + } } export class MutableGetFeeInfoParams extends wasmlib.ScMapID { - hname(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); - } + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); + } } diff --git a/packages/vm/wasmlib/ts/wasmlib/coregovernance/results.ts b/packages/vm/wasmlib/ts/wasmlib/coregovernance/results.ts index 8404346f4b..96b3881322 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coregovernance/results.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coregovernance/results.ts @@ -5,11 +5,11 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ArrayOfImmutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -25,15 +25,14 @@ export class ArrayOfImmutableBytes { } export class ImmutableGetAllowedStateControllerAddressesResults extends wasmlib.ScMapID { - allowedStateControllerAddresses(): sc.ArrayOfImmutableBytes { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultAllowedStateControllerAddresses), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); - return new sc.ArrayOfImmutableBytes(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultAllowedStateControllerAddresses), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); + return new sc.ArrayOfImmutableBytes(arrID); + } } export class ArrayOfMutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -53,131 +52,124 @@ export class ArrayOfMutableBytes { } export class MutableGetAllowedStateControllerAddressesResults extends wasmlib.ScMapID { - allowedStateControllerAddresses(): sc.ArrayOfMutableBytes { - let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultAllowedStateControllerAddresses), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); - return new sc.ArrayOfMutableBytes(arrID) - } + let arrID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultAllowedStateControllerAddresses), wasmlib.TYPE_ARRAY16|wasmlib.TYPE_BYTES); + return new sc.ArrayOfMutableBytes(arrID); + } } export class ImmutableGetChainInfoResults extends wasmlib.ScMapID { - chainID(): wasmlib.ScImmutableChainID { - return new wasmlib.ScImmutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainID)); - } + return new wasmlib.ScImmutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainID)); + } chainOwnerID(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainOwnerID)); - } + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainOwnerID)); + } defaultOwnerFee(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultDefaultOwnerFee)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultDefaultOwnerFee)); + } defaultValidatorFee(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultDefaultValidatorFee)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultDefaultValidatorFee)); + } description(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultDescription)); - } + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultDescription)); + } feeColor(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultFeeColor)); - } + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultFeeColor)); + } maxBlobSize(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxBlobSize)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxBlobSize)); + } maxEventSize(): wasmlib.ScImmutableInt16 { - return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxEventSize)); - } + return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxEventSize)); + } maxEventsPerReq(): wasmlib.ScImmutableInt16 { - return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxEventsPerReq)); - } + return new wasmlib.ScImmutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxEventsPerReq)); + } } export class MutableGetChainInfoResults extends wasmlib.ScMapID { - chainID(): wasmlib.ScMutableChainID { - return new wasmlib.ScMutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainID)); - } + return new wasmlib.ScMutableChainID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainID)); + } chainOwnerID(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainOwnerID)); - } + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ResultChainOwnerID)); + } defaultOwnerFee(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultDefaultOwnerFee)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultDefaultOwnerFee)); + } defaultValidatorFee(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultDefaultValidatorFee)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultDefaultValidatorFee)); + } description(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultDescription)); - } + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ResultDescription)); + } feeColor(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultFeeColor)); - } + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultFeeColor)); + } maxBlobSize(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxBlobSize)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxBlobSize)); + } maxEventSize(): wasmlib.ScMutableInt16 { - return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxEventSize)); - } + return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxEventSize)); + } maxEventsPerReq(): wasmlib.ScMutableInt16 { - return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxEventsPerReq)); - } + return new wasmlib.ScMutableInt16(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxEventsPerReq)); + } } export class ImmutableGetFeeInfoResults extends wasmlib.ScMapID { - feeColor(): wasmlib.ScImmutableColor { - return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultFeeColor)); - } + return new wasmlib.ScImmutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultFeeColor)); + } ownerFee(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultOwnerFee)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultOwnerFee)); + } validatorFee(): wasmlib.ScImmutableInt64 { - return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultValidatorFee)); - } + return new wasmlib.ScImmutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultValidatorFee)); + } } export class MutableGetFeeInfoResults extends wasmlib.ScMapID { - feeColor(): wasmlib.ScMutableColor { - return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultFeeColor)); - } + return new wasmlib.ScMutableColor(this.mapID, wasmlib.Key32.fromString(sc.ResultFeeColor)); + } ownerFee(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultOwnerFee)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultOwnerFee)); + } validatorFee(): wasmlib.ScMutableInt64 { - return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultValidatorFee)); - } + return new wasmlib.ScMutableInt64(this.mapID, wasmlib.Key32.fromString(sc.ResultValidatorFee)); + } } export class ImmutableGetMaxBlobSizeResults extends wasmlib.ScMapID { - maxBlobSize(): wasmlib.ScImmutableInt32 { - return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxBlobSize)); - } + return new wasmlib.ScImmutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxBlobSize)); + } } export class MutableGetMaxBlobSizeResults extends wasmlib.ScMapID { - maxBlobSize(): wasmlib.ScMutableInt32 { - return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxBlobSize)); - } + return new wasmlib.ScMutableInt32(this.mapID, wasmlib.Key32.fromString(sc.ResultMaxBlobSize)); + } } diff --git a/packages/vm/wasmlib/ts/wasmlib/coreroot/consts.ts b/packages/vm/wasmlib/ts/wasmlib/coreroot/consts.ts index 48b60cfd17..8d5626b329 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreroot/consts.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreroot/consts.ts @@ -5,7 +5,7 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; export const ScName = "root"; export const ScDescription = "Core root contract"; diff --git a/packages/vm/wasmlib/ts/wasmlib/coreroot/contract.ts b/packages/vm/wasmlib/ts/wasmlib/coreroot/contract.ts index f4617d16b2..7ab3399228 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreroot/contract.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreroot/contract.ts @@ -5,37 +5,36 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class DeployContractCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDeployContract); - params: sc.MutableDeployContractParams = new sc.MutableDeployContractParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncDeployContract); + params: sc.MutableDeployContractParams = new sc.MutableDeployContractParams(); } export class GrantDeployPermissionCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncGrantDeployPermission); - params: sc.MutableGrantDeployPermissionParams = new sc.MutableGrantDeployPermissionParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncGrantDeployPermission); + params: sc.MutableGrantDeployPermissionParams = new sc.MutableGrantDeployPermissionParams(); } export class RevokeDeployPermissionCall { - func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncRevokeDeployPermission); - params: sc.MutableRevokeDeployPermissionParams = new sc.MutableRevokeDeployPermissionParams(); + func: wasmlib.ScFunc = new wasmlib.ScFunc(sc.HScName, sc.HFuncRevokeDeployPermission); + params: sc.MutableRevokeDeployPermissionParams = new sc.MutableRevokeDeployPermissionParams(); } export class FindContractCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewFindContract); - params: sc.MutableFindContractParams = new sc.MutableFindContractParams(); - results: sc.ImmutableFindContractResults = new sc.ImmutableFindContractResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewFindContract); + params: sc.MutableFindContractParams = new sc.MutableFindContractParams(); + results: sc.ImmutableFindContractResults = new sc.ImmutableFindContractResults(); } export class GetContractRecordsCall { - func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetContractRecords); - results: sc.ImmutableGetContractRecordsResults = new sc.ImmutableGetContractRecordsResults(); + func: wasmlib.ScView = new wasmlib.ScView(sc.HScName, sc.HViewGetContractRecords); + results: sc.ImmutableGetContractRecordsResults = new sc.ImmutableGetContractRecordsResults(); } export class ScFuncs { - static deployContract(ctx: wasmlib.ScFuncCallContext): DeployContractCall { let f = new DeployContractCall(); f.func.setPtrs(f.params, null); diff --git a/packages/vm/wasmlib/ts/wasmlib/coreroot/params.ts b/packages/vm/wasmlib/ts/wasmlib/coreroot/params.ts index 065688b604..9129658507 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreroot/params.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreroot/params.ts @@ -5,77 +5,69 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ImmutableDeployContractParams extends wasmlib.ScMapID { - description(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamDescription)); - } + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamDescription)); + } name(): wasmlib.ScImmutableString { - return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); - } + return new wasmlib.ScImmutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); + } programHash(): wasmlib.ScImmutableHash { - return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamProgramHash)); - } + return new wasmlib.ScImmutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamProgramHash)); + } } export class MutableDeployContractParams extends wasmlib.ScMapID { - description(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamDescription)); - } + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamDescription)); + } name(): wasmlib.ScMutableString { - return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); - } + return new wasmlib.ScMutableString(this.mapID, wasmlib.Key32.fromString(sc.ParamName)); + } programHash(): wasmlib.ScMutableHash { - return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamProgramHash)); - } + return new wasmlib.ScMutableHash(this.mapID, wasmlib.Key32.fromString(sc.ParamProgramHash)); + } } export class ImmutableGrantDeployPermissionParams extends wasmlib.ScMapID { - deployer(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDeployer)); - } + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDeployer)); + } } export class MutableGrantDeployPermissionParams extends wasmlib.ScMapID { - deployer(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDeployer)); - } + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDeployer)); + } } export class ImmutableRevokeDeployPermissionParams extends wasmlib.ScMapID { - deployer(): wasmlib.ScImmutableAgentID { - return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDeployer)); - } + return new wasmlib.ScImmutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDeployer)); + } } export class MutableRevokeDeployPermissionParams extends wasmlib.ScMapID { - deployer(): wasmlib.ScMutableAgentID { - return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDeployer)); - } + return new wasmlib.ScMutableAgentID(this.mapID, wasmlib.Key32.fromString(sc.ParamDeployer)); + } } export class ImmutableFindContractParams extends wasmlib.ScMapID { - hname(): wasmlib.ScImmutableHname { - return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); - } + return new wasmlib.ScImmutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); + } } export class MutableFindContractParams extends wasmlib.ScMapID { - hname(): wasmlib.ScMutableHname { - return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); - } + return new wasmlib.ScMutableHname(this.mapID, wasmlib.Key32.fromString(sc.ParamHname)); + } } diff --git a/packages/vm/wasmlib/ts/wasmlib/coreroot/results.ts b/packages/vm/wasmlib/ts/wasmlib/coreroot/results.ts index 5448e3f722..7a7cf43c50 100644 --- a/packages/vm/wasmlib/ts/wasmlib/coreroot/results.ts +++ b/packages/vm/wasmlib/ts/wasmlib/coreroot/results.ts @@ -5,33 +5,31 @@ // >>>> DO NOT CHANGE THIS FILE! <<<< // Change the json schema instead -import * as wasmlib from "wasmlib" +import * as wasmlib from "wasmlib"; import * as sc from "./index"; export class ImmutableFindContractResults extends wasmlib.ScMapID { - contractFound(): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultContractFound)); - } + return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultContractFound)); + } contractRecData(): wasmlib.ScImmutableBytes { - return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultContractRecData)); - } + return new wasmlib.ScImmutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultContractRecData)); + } } export class MutableFindContractResults extends wasmlib.ScMapID { - contractFound(): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultContractFound)); - } + return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultContractFound)); + } contractRecData(): wasmlib.ScMutableBytes { - return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultContractRecData)); - } + return new wasmlib.ScMutableBytes(this.mapID, wasmlib.Key32.fromString(sc.ResultContractRecData)); + } } export class MapHnameToImmutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; @@ -43,22 +41,21 @@ export class MapHnameToImmutableBytes { } export class ImmutableGetContractRecordsResults extends wasmlib.ScMapID { - contractRegistry(): sc.MapHnameToImmutableBytes { - let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultContractRegistry), wasmlib.TYPE_MAP); - return new sc.MapHnameToImmutableBytes(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultContractRegistry), wasmlib.TYPE_MAP); + return new sc.MapHnameToImmutableBytes(mapID); + } } export class MapHnameToMutableBytes { - objID: i32; + objID: i32; constructor(objID: i32) { this.objID = objID; } clear(): void { - wasmlib.clear(this.objID) + wasmlib.clear(this.objID); } getBytes(key: wasmlib.ScHname): wasmlib.ScMutableBytes { @@ -67,9 +64,8 @@ export class MapHnameToMutableBytes { } export class MutableGetContractRecordsResults extends wasmlib.ScMapID { - contractRegistry(): sc.MapHnameToMutableBytes { - let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultContractRegistry), wasmlib.TYPE_MAP); - return new sc.MapHnameToMutableBytes(mapID); - } + let mapID = wasmlib.getObjectID(this.mapID, wasmlib.Key32.fromString(sc.ResultContractRegistry), wasmlib.TYPE_MAP); + return new sc.MapHnameToMutableBytes(mapID); + } } diff --git a/packages/vm/wasmlib/ts/wasmlib/events.ts b/packages/vm/wasmlib/ts/wasmlib/events.ts new file mode 100644 index 0000000000..0779992c77 --- /dev/null +++ b/packages/vm/wasmlib/ts/wasmlib/events.ts @@ -0,0 +1,115 @@ +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +import {ScAddress, ScAgentID, ScChainID, ScColor, ScHash, ScHname, ScRequestID} from "./hashtypes"; +import * as keys from "./keys"; +import {base58Encode, ROOT} from "./context"; + +// encodes separate entities into a byte buffer +export class EventEncoder { + event: string; + + // constructs an encoder + constructor(eventName: string) { + this.event = eventName; + let timestamp = ROOT.getInt64(keys.KEY_TIMESTAMP).value(); + this.int64(timestamp / 1_000_000_000); + } + + // encodes an ScAddress into the byte buffer + address(value: ScAddress): EventEncoder { + return this.string(value.toString()); + } + + // encodes an ScAgentID into the byte buffer + agentID(value: ScAgentID): EventEncoder { + return this.string(value.toString()); + } + + // encodes a Bool into the byte buffer + bool(value: bool): EventEncoder { + return this.uint8(value ? 1 : 0); + } + + // encodes a substring of bytes into the byte buffer + bytes(value: u8[]): EventEncoder { + return this.string(base58Encode(value)); + } + + // encodes an ScChainID into the byte buffer + chainID(value: ScChainID): EventEncoder { + return this.string(value.toString()); + } + + // encodes an ScColor into the byte buffer + color(value: ScColor): EventEncoder { + return this.string(value.toString()); + } + + // retrieve the encoded byte buffer + emit(): void { + ROOT.getString(keys.KEY_EVENT).setValue(this.event); + } + + // encodes an ScHash into the byte buffer + hash(value: ScHash): EventEncoder { + return this.string(value.toString()); + } + + // encodes an ScHname into the byte buffer + hname(value: ScHname): EventEncoder { + return this.string(value.toString()); + } + + // encodes an Int8 into the byte buffer + int8(value: i8): EventEncoder { + return this.string(value.toString()); + } + + // encodes an Int16 into the byte buffer + int16(value: i16): EventEncoder { + return this.string(value.toString()); + } + + // encodes an Int32 into the byte buffer + int32(value: i32): EventEncoder { + return this.string(value.toString()); + } + + // encodes an Int64 into the byte buffer + int64(value: i64): EventEncoder { + return this.string(value.toString()); + } + + // encodes an ScRequestID into the byte buffer + requestID(value: ScRequestID): EventEncoder { + return this.string(value.toString()); + } + + // encodes an UTF-8 text string into the byte buffer + string(value: string): EventEncoder { + //TODO encode potential vertical bars that are present in the value string + this.event += "|" + value; + return this; + } + + // encodes an Uint8 into the byte buffer + uint8(value: u8): EventEncoder { + return this.string(value.toString()); + } + + // encodes an Uint16 into the byte buffer + uint16(value: u16): EventEncoder { + return this.string(value.toString()); + } + + // encodes an Uint32 into the byte buffer + uint32(value: u32): EventEncoder { + return this.string(value.toString()); + } + + // encodes an Uint64 into the byte buffer + uint64(value: u64): EventEncoder { + return this.string(value.toString()); + } +} diff --git a/packages/vm/wasmlib/ts/wasmlib/hashtypes.ts b/packages/vm/wasmlib/ts/wasmlib/hashtypes.ts index 98d65a0324..72e35f1ac5 100644 --- a/packages/vm/wasmlib/ts/wasmlib/hashtypes.ts +++ b/packages/vm/wasmlib/ts/wasmlib/hashtypes.ts @@ -41,7 +41,7 @@ export class ScAddress implements MapKey { // can be used as key in maps getKeyID(): Key32 { - return getKeyIDFromBytes(this.toBytes()); + return getKeyIDFromBytes(this.id); } // convert to byte array representation @@ -91,7 +91,7 @@ export class ScAgentID implements MapKey { // can be used as key in maps getKeyID(): Key32 { - return getKeyIDFromBytes(this.toBytes()); + return getKeyIDFromBytes(this.id); } // get contract name hash for this agent @@ -146,7 +146,7 @@ export class ScChainID implements MapKey { // can be used as key in maps getKeyID(): Key32 { - return getKeyIDFromBytes(this.toBytes()); + return getKeyIDFromBytes(this.id); } // convert to byte array representation @@ -197,7 +197,7 @@ export class ScColor implements MapKey { // can be used as key in maps getKeyID(): Key32 { - return getKeyIDFromBytes(this.toBytes()); + return getKeyIDFromBytes(this.id); } // convert to byte array representation @@ -233,7 +233,7 @@ export class ScHash implements MapKey { // can be used as key in maps getKeyID(): Key32 { - return getKeyIDFromBytes(this.toBytes()); + return getKeyIDFromBytes(this.id); } // convert to byte array representation @@ -288,10 +288,15 @@ export class ScHname implements MapKey { return this.id; } - // human-readable string representation + // human-readable string representation: 8 hex digits toString(): string { - let id = Convert.toI32(this.id); - return id.toString(); + const hex = "0123456789abcdef"; + let res = "" + for (let i = 3; i >= 0; i--) { + let b = this.id[i]; + res += hex.charAt((b >> 4) & 0x0f) + hex.charAt(b & 0x0f); + } + return res; } } @@ -317,7 +322,7 @@ export class ScRequestID implements MapKey { // can be used as key in maps getKeyID(): Key32 { - return getKeyIDFromBytes(this.toBytes()); + return getKeyIDFromBytes(this.id); } // convert to byte array representation diff --git a/packages/vm/wasmlib/ts/wasmlib/host.ts b/packages/vm/wasmlib/ts/wasmlib/host.ts index 426741ae3a..a830b80eb0 100644 --- a/packages/vm/wasmlib/ts/wasmlib/host.ts +++ b/packages/vm/wasmlib/ts/wasmlib/host.ts @@ -10,22 +10,25 @@ import * as keys from "./keys"; import {Convert} from "./convert"; export const TYPE_ARRAY: i32 = 0x20; -export const TYPE_ARRAY16: i32 = 0x30; -export const TYPE_CALL: i32 = 0x40; +export const TYPE_ARRAY16: i32 = 0x60; +export const TYPE_CALL: i32 = 0x80; +export const TYPE_MASK: i32 = 0x1f; export const TYPE_ADDRESS: i32 = 1; export const TYPE_AGENT_ID: i32 = 2; -export const TYPE_BYTES: i32 = 3; -export const TYPE_CHAIN_ID: i32 = 4; -export const TYPE_COLOR: i32 = 5; -export const TYPE_HASH: i32 = 6; -export const TYPE_HNAME: i32 = 7; -export const TYPE_INT16: i32 = 8; -export const TYPE_INT32: i32 = 9; -export const TYPE_INT64: i32 = 10; -export const TYPE_MAP: i32 = 11; -export const TYPE_REQUEST_ID: i32 = 12; -export const TYPE_STRING: i32 = 13; +export const TYPE_BOOL: i32 = 3; +export const TYPE_BYTES: i32 = 4; +export const TYPE_CHAIN_ID: i32 = 5; +export const TYPE_COLOR: i32 = 6; +export const TYPE_HASH: i32 = 7; +export const TYPE_HNAME: i32 = 8; +export const TYPE_INT8: i32 = 9; +export const TYPE_INT16: i32 = 10; +export const TYPE_INT32: i32 = 11; +export const TYPE_INT64: i32 = 12; +export const TYPE_MAP: i32 = 13; +export const TYPE_REQUEST_ID: i32 = 14; +export const TYPE_STRING: i32 = 15; export const OBJ_ID_NULL: i32 = 0; export const OBJ_ID_ROOT: i32 = 1; @@ -34,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, 0, 33, 32, 32, 4, 2, 4, 8, 0, 34, 0]; +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 @@ -84,7 +87,14 @@ export function callFunc(objID: i32, keyID: Key32, params: u8[]): u8[] { // Removes all its sub-objects as well. export function clear(objID: i32): void { // special key "length" is used with integer value zero - setBytes(objID, keys.KEY_LENGTH, TYPE_INT32, Convert.fromI32(0)) + setBytes(objID, keys.KEY_LENGTH, TYPE_INT32, Convert.fromI32(0)); +} + +// Delete the value with the specified key and type from the specified container object. +export function delKey(objID: i32, keyID: Key32, typeID: i32): void { + // size -1 means delete + // this removes the need for a separate hostDelete function + hostSetBytes(objID, keyID.keyID, typeID, 0, -1); } // Check if the specified container object contains a value with the specified key and type. @@ -138,6 +148,12 @@ export function getKeyIDFromString(key: string): Key32 { return getKeyID(bytes, bytes.length); } +// Retrieve the key id that the host has associated with the specified integer key +export function getKeyIDFromUint64(key: u64, nrOfBytes: usize): Key32 { + // negative size indicates this is a bytes key + return getKeyID(Convert.fromI64(key as i64), -nrOfBytes - 1); +} + // Retrieve the length of an array container object on the host export function getLength(objID: i32): i32 { // special integer key "length" is used @@ -152,12 +168,12 @@ export function getObjectID(objID: i32, keyID: Key32, typeID: i32): i32 { // Direct logging of informational text to host log export function log(text: string): void { - setBytes(1, keys.KEY_LOG, TYPE_STRING, Convert.fromString(text)) + setBytes(1, keys.KEY_LOG, TYPE_STRING, Convert.fromString(text)); } // Direct logging of error to host log, followed by panicking out of the Wasm code export function panic(text: string): void { - setBytes(1, keys.KEY_PANIC, TYPE_STRING, Convert.fromString(text)) + setBytes(1, keys.KEY_PANIC, TYPE_STRING, Convert.fromString(text)); } // Store the provided value bytes of specified type in the specified container object @@ -169,5 +185,5 @@ export function setBytes(objID: i32, keyID: Key32, typeID: i32, value: u8[]): vo // Direct logging of debug trace text to host log export function trace(text: string): void { - setBytes(1, keys.KEY_TRACE, TYPE_STRING, Convert.fromString(text)) + setBytes(1, keys.KEY_TRACE, TYPE_STRING, Convert.fromString(text)); } diff --git a/packages/vm/wasmlib/ts/wasmlib/immutable.ts b/packages/vm/wasmlib/ts/wasmlib/immutable.ts index 104b77c43f..78519b84cd 100644 --- a/packages/vm/wasmlib/ts/wasmlib/immutable.ts +++ b/packages/vm/wasmlib/ts/wasmlib/immutable.ts @@ -7,7 +7,6 @@ import { base58Encode } from "./context"; import {Convert} from "./convert"; import {ScAddress,ScAgentID,ScChainID,ScColor,ScHash,ScHname,ScRequestID} from "./hashtypes"; import * as host from "./host"; -import {callFunc, exists, getBytes, getLength, getObjectID} from "./host"; import {Key32,MapKey} from "./keys"; // value proxy for immutable ScAddress in host container @@ -22,7 +21,7 @@ export class ScImmutableAddress { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_ADDRESS); + return host.exists(this.objID, this.keyID, host.TYPE_ADDRESS); } // human-readable string representation @@ -32,7 +31,7 @@ export class ScImmutableAddress { // get value from host container value(): ScAddress { - return ScAddress.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_ADDRESS)); + return ScAddress.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_ADDRESS)); } } @@ -53,7 +52,7 @@ export class ScImmutableAddressArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -71,7 +70,7 @@ export class ScImmutableAgentID { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_AGENT_ID); + return host.exists(this.objID, this.keyID, host.TYPE_AGENT_ID); } // human-readable string representation @@ -81,7 +80,7 @@ export class ScImmutableAgentID { // get value from host container value(): ScAgentID { - return ScAgentID.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_AGENT_ID)); + return ScAgentID.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_AGENT_ID)); } } @@ -102,7 +101,57 @@ export class ScImmutableAgentIDArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Bool in host container +export class ScImmutableBool { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_BOOL); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // get value from host container + value(): boolean { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_BOOL); + return bytes[0] != 0; + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for immutable array of Bool +export class ScImmutableBoolArray { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // get value proxy for item at index, index can be 0..length()-1 + getBool(index: i32): ScImmutableBool { + return new ScImmutableBool(this.objID, new Key32(index)); + } + + // number of items in array + length(): i32 { + return host.getLength(this.objID); } } @@ -120,7 +169,7 @@ export class ScImmutableBytes { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_BYTES); + return host.exists(this.objID, this.keyID, host.TYPE_BYTES); } // human-readable string representation @@ -130,7 +179,7 @@ export class ScImmutableBytes { // get value from host container value(): u8[] { - return getBytes(this.objID, this.keyID, host.TYPE_BYTES); + return host.getBytes(this.objID, this.keyID, host.TYPE_BYTES); } } @@ -151,7 +200,7 @@ export class ScImmutableBytesArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -169,7 +218,7 @@ export class ScImmutableChainID { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_CHAIN_ID); + return host.exists(this.objID, this.keyID, host.TYPE_CHAIN_ID); } // human-readable string representation @@ -179,7 +228,7 @@ export class ScImmutableChainID { // get value from host container value(): ScChainID { - return ScChainID.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_CHAIN_ID)); + return ScChainID.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_CHAIN_ID)); } } @@ -200,7 +249,7 @@ export class ScImmutableChainIDArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -218,7 +267,7 @@ export class ScImmutableColor { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_COLOR); + return host.exists(this.objID, this.keyID, host.TYPE_COLOR); } // human-readable string representation @@ -228,7 +277,7 @@ export class ScImmutableColor { // get value from host container value(): ScColor { - return ScColor.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_COLOR)); + return ScColor.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_COLOR)); } } @@ -249,7 +298,7 @@ export class ScImmutableColorArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -267,7 +316,7 @@ export class ScImmutableHash { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_HASH); + return host.exists(this.objID, this.keyID, host.TYPE_HASH); } // human-readable string representation @@ -277,7 +326,7 @@ export class ScImmutableHash { // get value from host container value(): ScHash { - return ScHash.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_HASH)); + return ScHash.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_HASH)); } } @@ -298,7 +347,7 @@ export class ScImmutableHashArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -316,7 +365,7 @@ export class ScImmutableHname { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_HNAME); + return host.exists(this.objID, this.keyID, host.TYPE_HNAME); } // human-readable string representation @@ -326,7 +375,7 @@ export class ScImmutableHname { // get value from host container value(): ScHname { - return ScHname.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_HNAME)); + return ScHname.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_HNAME)); } } @@ -347,13 +396,63 @@ export class ScImmutableHnameArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Int8 in host container +export class ScImmutableInt8 { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_INT8); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // get value from host container + value(): i8 { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT8); + return bytes[0] as i8; } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for immutable int16 in host container +// array proxy for immutable array of Int8 +export class ScImmutableInt8Array { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // get value proxy for item at index, index can be 0..length()-1 + getInt8(index: i32): ScImmutableInt8 { + return new ScImmutableInt8(this.objID, new Key32(index)); + } + + // number of items in array + length(): i32 { + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Int16 in host container export class ScImmutableInt16 { objID: i32; keyID: Key32; @@ -365,7 +464,7 @@ export class ScImmutableInt16 { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_INT16); + return host.exists(this.objID, this.keyID, host.TYPE_INT16); } // human-readable string representation @@ -375,14 +474,14 @@ export class ScImmutableInt16 { // get value from host container value(): i16 { - let bytes = getBytes(this.objID, this.keyID, host.TYPE_INT16); + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT16); return Convert.toI16(bytes); } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for immutable array of int16 +// array proxy for immutable array of Int16 export class ScImmutableInt16Array { objID: i32; @@ -397,13 +496,13 @@ export class ScImmutableInt16Array { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for immutable int32 in host container +// value proxy for immutable Int32 in host container export class ScImmutableInt32 { objID: i32; keyID: Key32; @@ -415,7 +514,7 @@ export class ScImmutableInt32 { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_INT32); + return host.exists(this.objID, this.keyID, host.TYPE_INT32); } // human-readable string representation @@ -425,14 +524,14 @@ export class ScImmutableInt32 { // get value from host container value(): i32 { - let bytes = getBytes(this.objID, this.keyID, host.TYPE_INT32); + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT32); return Convert.toI32(bytes); } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for immutable array of int32 +// array proxy for immutable array of Int32 export class ScImmutableInt32Array { objID: i32; @@ -447,13 +546,13 @@ export class ScImmutableInt32Array { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for immutable int64 in host container +// value proxy for immutable Int64 in host container export class ScImmutableInt64 { objID: i32; keyID: Key32; @@ -465,7 +564,7 @@ export class ScImmutableInt64 { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_INT64); + return host.exists(this.objID, this.keyID, host.TYPE_INT64); } // human-readable string representation @@ -475,14 +574,14 @@ export class ScImmutableInt64 { // get value from host container value(): i64 { - let bytes = getBytes(this.objID, this.keyID, host.TYPE_INT64); + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT64); return Convert.toI64(bytes); } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for immutable array of int64 +// array proxy for immutable array of Int64 export class ScImmutableInt64Array { objID: i32; @@ -497,7 +596,7 @@ export class ScImmutableInt64Array { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -512,7 +611,7 @@ export class ScImmutableMap { } callFunc(keyID: Key32, params: u8[]): u8[] { - return callFunc(this.objID, keyID, params); + return host.callFunc(this.objID, keyID, params); } // get value proxy for immutable ScAddress field specified by key @@ -522,7 +621,7 @@ export class ScImmutableMap { // get array proxy for ScImmutableAddressArray specified by key getAddressArray(key: MapKey): ScImmutableAddressArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_ADDRESS | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_ADDRESS | host.TYPE_ARRAY); return new ScImmutableAddressArray(arrID); } @@ -533,10 +632,21 @@ export class ScImmutableMap { // get array proxy for ScImmutableAgentIDArray specified by key getAgentIDArray(key: MapKey): ScImmutableAgentIDArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_AGENT_ID | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_AGENT_ID | host.TYPE_ARRAY); return new ScImmutableAgentIDArray(arrID); } + // get value proxy for immutable Bool field specified by key + getBool(key: MapKey): ScImmutableBool { + return new ScImmutableBool(this.objID, key.getKeyID()); + } + + // get array proxy for ScImmutableBoolArray specified by key + getBoolArray(key: MapKey): ScImmutableBoolArray { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_BOOL | host.TYPE_ARRAY); + return new ScImmutableBoolArray(arrID); + } + // get value proxy for immutable bytes array field specified by key getBytes(key: MapKey): ScImmutableBytes { return new ScImmutableBytes(this.objID, key.getKeyID()); @@ -544,7 +654,7 @@ export class ScImmutableMap { // get array proxy for ScImmutableBytesArray specified by key getBytesArray(key: MapKey): ScImmutableBytesArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_BYTES | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_BYTES | host.TYPE_ARRAY); return new ScImmutableBytesArray(arrID); } @@ -555,7 +665,7 @@ export class ScImmutableMap { // get array proxy for ScImmutableChainIDArray specified by key getChainIDArray(key: MapKey): ScImmutableChainIDArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_CHAIN_ID | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_CHAIN_ID | host.TYPE_ARRAY); return new ScImmutableChainIDArray(arrID); } @@ -566,7 +676,7 @@ export class ScImmutableMap { // get array proxy for ScImmutableColorArray specified by key getColorArray(key: MapKey): ScImmutableColorArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_COLOR | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_COLOR | host.TYPE_ARRAY); return new ScImmutableColorArray(arrID); } @@ -577,7 +687,7 @@ export class ScImmutableMap { // get array proxy for ScImmutableHashArray specified by key getHashArray(key: MapKey): ScImmutableHashArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_HASH | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_HASH | host.TYPE_ARRAY); return new ScImmutableHashArray(arrID); } @@ -588,52 +698,63 @@ export class ScImmutableMap { // get array proxy for ScImmutableHnameArray specified by key getHnameArray(key: MapKey): ScImmutableHnameArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_HNAME | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_HNAME | host.TYPE_ARRAY); return new ScImmutableHnameArray(arrID); } - // get value proxy for immutable int16 field specified by key + // get value proxy for immutable Int8 field specified by key + getInt8(key: MapKey): ScImmutableInt8 { + return new ScImmutableInt8(this.objID, key.getKeyID()); + } + + // get array proxy for ScImmutableInt8Array specified by key + getInt8Array(key: MapKey): ScImmutableInt8Array { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT8 | host.TYPE_ARRAY); + return new ScImmutableInt8Array(arrID); + } + + // get value proxy for immutable Int16 field specified by key getInt16(key: MapKey): ScImmutableInt16 { return new ScImmutableInt16(this.objID, key.getKeyID()); } // get array proxy for ScImmutableInt16Array specified by key getInt16Array(key: MapKey): ScImmutableInt16Array { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_INT16 | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT16 | host.TYPE_ARRAY); return new ScImmutableInt16Array(arrID); } - // get value proxy for immutable int32 field specified by key + // get value proxy for immutable Int32 field specified by key getInt32(key: MapKey): ScImmutableInt32 { return new ScImmutableInt32(this.objID, key.getKeyID()); } // get array proxy for ScImmutableInt32Array specified by key getInt32Array(key: MapKey): ScImmutableInt32Array { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_INT32 | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT32 | host.TYPE_ARRAY); return new ScImmutableInt32Array(arrID); } - // get value proxy for immutable int64 field specified by key + // get value proxy for immutable Int64 field specified by key getInt64(key: MapKey): ScImmutableInt64 { return new ScImmutableInt64(this.objID, key.getKeyID()); } // get array proxy for ScImmutableInt64Array specified by key getInt64Array(key: MapKey): ScImmutableInt64Array { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_INT64 | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT64 | host.TYPE_ARRAY); return new ScImmutableInt64Array(arrID); } // get map proxy for ScImmutableMap specified by key getMap(key: MapKey): ScImmutableMap { - let mapID = getObjectID(this.objID, key.getKeyID(), host.TYPE_MAP); + let mapID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_MAP); return new ScImmutableMap(mapID); } // get array proxy for ScImmutableMapArray specified by key getMapArray(key: MapKey): ScImmutableMapArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_MAP | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_MAP | host.TYPE_ARRAY); return new ScImmutableMapArray(arrID); } @@ -644,7 +765,7 @@ export class ScImmutableMap { // get array proxy for ScImmutableRequestIDArray specified by key getRequestIDArray(key: MapKey): ScImmutableRequestIDArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_REQUEST_ID | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_REQUEST_ID | host.TYPE_ARRAY); return new ScImmutableRequestIDArray(arrID); } @@ -655,10 +776,54 @@ export class ScImmutableMap { // get array proxy for ScImmutableStringArray specified by key getStringArray(key: MapKey): ScImmutableStringArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_STRING | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_STRING | host.TYPE_ARRAY); return new ScImmutableStringArray(arrID); } + // get value proxy for immutable Uint8 field specified by key + getUint8(key: MapKey): ScImmutableUint8 { + return new ScImmutableUint8(this.objID, key.getKeyID()); + } + + // get array proxy for ScImmutableUint8Array specified by key + getUint8Array(key: MapKey): ScImmutableUint8Array { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT8 | host.TYPE_ARRAY); + return new ScImmutableUint8Array(arrID); + } + + // get value proxy for immutable Uint16 field specified by key + getUint16(key: MapKey): ScImmutableUint16 { + return new ScImmutableUint16(this.objID, key.getKeyID()); + } + + // get array proxy for ScImmutableUint16Array specified by key + getUint16Array(key: MapKey): ScImmutableUint16Array { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT16 | host.TYPE_ARRAY); + return new ScImmutableUint16Array(arrID); + } + + // get value proxy for immutable Uint32 field specified by key + getUint32(key: MapKey): ScImmutableUint32 { + return new ScImmutableUint32(this.objID, key.getKeyID()); + } + + // get array proxy for ScImmutableUint32Array specified by key + getUint32Array(key: MapKey): ScImmutableUint32Array { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT32 | host.TYPE_ARRAY); + return new ScImmutableUint32Array(arrID); + } + + // get value proxy for immutable Uint64 field specified by key + getUint64(key: MapKey): ScImmutableUint64 { + return new ScImmutableUint64(this.objID, key.getKeyID()); + } + + // get array proxy for ScImmutableUint64Array specified by key + getUint64Array(key: MapKey): ScImmutableUint64Array { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT64 | host.TYPE_ARRAY); + return new ScImmutableUint64Array(arrID); + } + mapID(): i32 { return this.objID; } @@ -676,13 +841,13 @@ export class ScImmutableMapArray { // get value proxy for item at index, index can be 0..length()-1 getMap(index: i32): ScImmutableMap { - let mapID = getObjectID(this.objID, new Key32(index), host.TYPE_MAP); + let mapID = host.getObjectID(this.objID, new Key32(index), host.TYPE_MAP); return new ScImmutableMap(mapID); } // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -698,7 +863,7 @@ export class ScImmutableRequestID { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_REQUEST_ID); + return host.exists(this.objID, this.keyID, host.TYPE_REQUEST_ID); } // human-readable string representation @@ -708,7 +873,7 @@ export class ScImmutableRequestID { // get value from host container value(): ScRequestID { - return ScRequestID.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_REQUEST_ID)); + return ScRequestID.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_REQUEST_ID)); } } @@ -729,7 +894,7 @@ export class ScImmutableRequestIDArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -747,7 +912,7 @@ export class ScImmutableString { // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_STRING); + return host.exists(this.objID, this.keyID, host.TYPE_STRING); } // human-readable string representation @@ -757,7 +922,7 @@ export class ScImmutableString { // get value from host container value(): string { - let bytes = getBytes(this.objID, this.keyID, host.TYPE_STRING); + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_STRING); return Convert.toString(bytes); } } @@ -779,6 +944,206 @@ export class ScImmutableStringArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Uint8 in host container +export class ScImmutableUint8 { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_INT8); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // get value from host container + value(): u8 { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT8); + return bytes[0] as u8; + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for immutable array of Uint8 +export class ScImmutableUint8Array { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // get value proxy for item at index, index can be 0..length()-1 + getUint8(index: i32): ScImmutableUint8 { + return new ScImmutableUint8(this.objID, new Key32(index)); + } + + // number of items in array + length(): u32 { + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Uint16 in host container +export class ScImmutableUint16 { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_INT16); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // get value from host container + value(): u16 { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT16); + return Convert.toI16(bytes) as u16; + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for immutable array of Uint16 +export class ScImmutableUint16Array { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // get value proxy for item at index, index can be 0..length()-1 + getUint16(index: i32): ScImmutableUint16 { + return new ScImmutableUint16(this.objID, new Key32(index)); + } + + // number of items in array + length(): i32 { + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Uint32 in host container +export class ScImmutableUint32 { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_INT32); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // get value from host container + value(): u32 { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT32); + return Convert.toI32(bytes) as u32; + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for immutable array of Uint32 +export class ScImmutableUint32Array { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // get value proxy for item at index, index can be 0..length()-1 + getUint32(index: i32): ScImmutableUint32 { + return new ScImmutableUint32(this.objID, new Key32(index)); + } + + // number of items in array + length(): i32 { + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for immutable Uint64 in host container +export class ScImmutableUint64 { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_INT64); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // get value from host container + value(): u64 { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT64); + return Convert.toI64(bytes) as u64; + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for immutable array of Uint64 +export class ScImmutableUint64Array { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // get value proxy for item at index, index can be 0..length()-1 + getUint64(index: i32): ScImmutableUint64 { + return new ScImmutableUint64(this.objID, new Key32(index)); + } + + // number of items in array + length(): i32 { + return host.getLength(this.objID); } } diff --git a/packages/vm/wasmlib/ts/wasmlib/index.ts b/packages/vm/wasmlib/ts/wasmlib/index.ts index 15311b1cb6..bb10d93cda 100644 --- a/packages/vm/wasmlib/ts/wasmlib/index.ts +++ b/packages/vm/wasmlib/ts/wasmlib/index.ts @@ -2,6 +2,7 @@ export * from "./bytes" export * from "./context" export * from "./contract" export * from "./convert" +export * from "./events" export * from "./exports" export * from "./hashtypes" export * from "./host" diff --git a/packages/vm/wasmlib/ts/wasmlib/mutable.ts b/packages/vm/wasmlib/ts/wasmlib/mutable.ts index 0162310e97..6bb0923a10 100644 --- a/packages/vm/wasmlib/ts/wasmlib/mutable.ts +++ b/packages/vm/wasmlib/ts/wasmlib/mutable.ts @@ -7,22 +7,27 @@ import {base58Encode, ROOT} from "./context"; import {Convert} from "./convert"; import {ScAddress, ScAgentID, ScChainID, ScColor, ScHash, ScHname, ScRequestID} from "./hashtypes"; import * as host from "./host"; -import {callFunc, clear, exists, getBytes, getLength, getObjectID, setBytes} from "./host"; import { ScImmutableAddressArray, ScImmutableAgentIDArray, + ScImmutableBoolArray, ScImmutableBytesArray, ScImmutableChainIDArray, ScImmutableColorArray, ScImmutableHashArray, ScImmutableHnameArray, + ScImmutableInt8Array, ScImmutableInt16Array, ScImmutableInt32Array, ScImmutableInt64Array, ScImmutableMap, ScImmutableMapArray, ScImmutableRequestIDArray, - ScImmutableStringArray + ScImmutableStringArray, + ScImmutableUint8Array, + ScImmutableUint16Array, + ScImmutableUint32Array, + ScImmutableUint64Array, } from "./immutable"; import {Key32, KEY_MAPS, MapKey} from "./keys"; @@ -38,14 +43,19 @@ export class ScMutableAddress { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_ADDRESS); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_ADDRESS); + return host.exists(this.objID, this.keyID, host.TYPE_ADDRESS); } // set value in host container setValue(val: ScAddress): void { - setBytes(this.objID, this.keyID, host.TYPE_ADDRESS, val.toBytes()); + host.setBytes(this.objID, this.keyID, host.TYPE_ADDRESS, val.toBytes()); } // human-readable string representation @@ -55,7 +65,7 @@ export class ScMutableAddress { // retrieve value from host container value(): ScAddress { - return ScAddress.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_ADDRESS)); + return ScAddress.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_ADDRESS)); } } @@ -71,7 +81,7 @@ export class ScMutableAddressArray { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -87,7 +97,7 @@ export class ScMutableAddressArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -103,14 +113,19 @@ export class ScMutableAgentID { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_AGENT_ID); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_AGENT_ID); + return host.exists(this.objID, this.keyID, host.TYPE_AGENT_ID); } // set value in host container setValue(val: ScAgentID): void { - setBytes(this.objID, this.keyID, host.TYPE_AGENT_ID, val.toBytes()); + host.setBytes(this.objID, this.keyID, host.TYPE_AGENT_ID, val.toBytes()); } // human-readable string representation @@ -120,7 +135,7 @@ export class ScMutableAgentID { // retrieve value from host container value(): ScAgentID { - return ScAgentID.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_AGENT_ID)); + return ScAgentID.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_AGENT_ID)); } } @@ -136,7 +151,7 @@ export class ScMutableAgentIDArray { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -152,7 +167,79 @@ export class ScMutableAgentIDArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Bool in host container +export class ScMutableBool { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_BOOL); + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_BOOL); + } + + // set value in host container + setValue(val: boolean): void { + let bytes: u8[] = [(val ? 1 : 0) as u8] + host.setBytes(this.objID, this.keyID, host.TYPE_BOOL, bytes); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // retrieve value from host container + value(): boolean { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_BOOL); + return bytes[0] != 0; + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for mutable array of Bool +export class ScMutableBoolArray { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // empty the array + clear(): void { + host.clear(this.objID); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + getBool(index: i32): ScMutableBool { + return new ScMutableBool(this.objID, new Key32(index)); + } + + // get immutable version of array proxy + immutable(): ScImmutableBoolArray { + return new ScImmutableBoolArray(this.objID); + } + + // number of items in array + length(): i32 { + return host.getLength(this.objID); } } @@ -168,14 +255,19 @@ export class ScMutableBytes { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_BYTES); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_BYTES); + return host.exists(this.objID, this.keyID, host.TYPE_BYTES); } // set value in host container setValue(val: u8[]): void { - setBytes(this.objID, this.keyID, host.TYPE_BYTES, val); + host.setBytes(this.objID, this.keyID, host.TYPE_BYTES, val); } // human-readable string representation @@ -185,7 +277,7 @@ export class ScMutableBytes { // retrieve value from host container value(): u8[] { - return getBytes(this.objID, this.keyID, host.TYPE_BYTES); + return host.getBytes(this.objID, this.keyID, host.TYPE_BYTES); } } @@ -201,7 +293,7 @@ export class ScMutableBytesArray { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -217,7 +309,7 @@ export class ScMutableBytesArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -233,14 +325,19 @@ export class ScMutableChainID { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_CHAIN_ID); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_CHAIN_ID); + return host.exists(this.objID, this.keyID, host.TYPE_CHAIN_ID); } // set value in host container setValue(val: ScChainID): void { - setBytes(this.objID, this.keyID, host.TYPE_CHAIN_ID, val.toBytes()); + host.setBytes(this.objID, this.keyID, host.TYPE_CHAIN_ID, val.toBytes()); } // human-readable string representation @@ -250,7 +347,7 @@ export class ScMutableChainID { // retrieve value from host container value(): ScChainID { - return ScChainID.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_CHAIN_ID)); + return ScChainID.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_CHAIN_ID)); } } @@ -266,7 +363,7 @@ export class ScMutableChainIDArray { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -282,7 +379,7 @@ export class ScMutableChainIDArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -298,14 +395,19 @@ export class ScMutableColor { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_COLOR); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_COLOR); + return host.exists(this.objID, this.keyID, host.TYPE_COLOR); } // set value in host container setValue(val: ScColor): void { - setBytes(this.objID, this.keyID, host.TYPE_COLOR, val.toBytes()); + host.setBytes(this.objID, this.keyID, host.TYPE_COLOR, val.toBytes()); } // human-readable string representation @@ -315,7 +417,7 @@ export class ScMutableColor { // retrieve value from host container value(): ScColor { - return ScColor.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_COLOR)); + return ScColor.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_COLOR)); } } @@ -331,7 +433,7 @@ export class ScMutableColorArray { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -347,7 +449,7 @@ export class ScMutableColorArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -363,14 +465,19 @@ export class ScMutableHash { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_HASH); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_HASH); + return host.exists(this.objID, this.keyID, host.TYPE_HASH); } // set value in host container setValue(val: ScHash): void { - setBytes(this.objID, this.keyID, host.TYPE_HASH, val.toBytes()); + host.setBytes(this.objID, this.keyID, host.TYPE_HASH, val.toBytes()); } // human-readable string representation @@ -380,7 +487,7 @@ export class ScMutableHash { // retrieve value from host container value(): ScHash { - return ScHash.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_HASH)); + return ScHash.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_HASH)); } } @@ -396,7 +503,7 @@ export class ScMutableHashArray { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -412,7 +519,7 @@ export class ScMutableHashArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -428,14 +535,19 @@ export class ScMutableHname { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_HNAME); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_HNAME); + return host.exists(this.objID, this.keyID, host.TYPE_HNAME); } // set value in host container setValue(val: ScHname): void { - setBytes(this.objID, this.keyID, host.TYPE_HNAME, val.toBytes()); + host.setBytes(this.objID, this.keyID, host.TYPE_HNAME, val.toBytes()); } // human-readable string representation @@ -445,7 +557,7 @@ export class ScMutableHname { // retrieve value from host container value(): ScHname { - return ScHname.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_HNAME)); + return ScHname.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_HNAME)); } } @@ -461,7 +573,7 @@ export class ScMutableHnameArray { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -477,13 +589,85 @@ export class ScMutableHnameArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Int8 in host container +export class ScMutableInt8 { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_INT8); + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_INT8); + } + + // set value in host container + setValue(val: i8): void { + let bytes: u8[] = [val as u8]; + host.setBytes(this.objID, this.keyID, host.TYPE_INT8, bytes); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // retrieve value from host container + value(): i8 { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT8); + return bytes[0] as i8; + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for mutable array of Int8 +export class ScMutableInt8Array { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // empty the array + clear(): void { + host.clear(this.objID); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + getInt8(index: i32): ScMutableInt8 { + return new ScMutableInt8(this.objID, new Key32(index)); + } + + // get immutable version of array proxy + immutable(): ScImmutableInt8Array { + return new ScImmutableInt8Array(this.objID); + } + + // number of items in array + length(): i32 { + return host.getLength(this.objID); } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for mutable int16 in host container +// value proxy for mutable Int16 in host container export class ScMutableInt16 { objID: i32; keyID: Key32; @@ -493,14 +677,19 @@ export class ScMutableInt16 { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_INT16); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_INT16); + return host.exists(this.objID, this.keyID, host.TYPE_INT16); } // set value in host container setValue(val: i16): void { - setBytes(this.objID, this.keyID, host.TYPE_INT16, Convert.fromI16(val)); + host.setBytes(this.objID, this.keyID, host.TYPE_INT16, Convert.fromI16(val)); } // human-readable string representation @@ -510,13 +699,13 @@ export class ScMutableInt16 { // retrieve value from host container value(): i16 { - return Convert.toI16(getBytes(this.objID, this.keyID, host.TYPE_INT16)); + return Convert.toI16(host.getBytes(this.objID, this.keyID, host.TYPE_INT16)); } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for mutable array of int16 +// array proxy for mutable array of Int16 export class ScMutableInt16Array { objID: i32; @@ -526,7 +715,7 @@ export class ScMutableInt16Array { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -542,13 +731,13 @@ export class ScMutableInt16Array { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for mutable int32 in host container +// value proxy for mutable Int32 in host container export class ScMutableInt32 { objID: i32; keyID: Key32; @@ -558,14 +747,19 @@ export class ScMutableInt32 { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_INT32); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_INT32); + return host.exists(this.objID, this.keyID, host.TYPE_INT32); } // set value in host container setValue(val: i32): void { - setBytes(this.objID, this.keyID, host.TYPE_INT32, Convert.fromI32(val)); + host.setBytes(this.objID, this.keyID, host.TYPE_INT32, Convert.fromI32(val)); } // human-readable string representation @@ -575,13 +769,13 @@ export class ScMutableInt32 { // retrieve value from host container value(): i32 { - return Convert.toI32(getBytes(this.objID, this.keyID, host.TYPE_INT32)); + return Convert.toI32(host.getBytes(this.objID, this.keyID, host.TYPE_INT32)); } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for mutable array of int32 +// array proxy for mutable array of Int32 export class ScMutableInt32Array { objID: i32; @@ -591,7 +785,7 @@ export class ScMutableInt32Array { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -607,13 +801,13 @@ export class ScMutableInt32Array { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// value proxy for mutable int64 in host container +// value proxy for mutable Int64 in host container export class ScMutableInt64 { objID: i32; keyID: Key32; @@ -623,14 +817,19 @@ export class ScMutableInt64 { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_INT64); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_INT64); + return host.exists(this.objID, this.keyID, host.TYPE_INT64); } // set value in host container setValue(val: i64): void { - setBytes(this.objID, this.keyID, host.TYPE_INT64, Convert.fromI64(val)); + host.setBytes(this.objID, this.keyID, host.TYPE_INT64, Convert.fromI64(val)); } // human-readable string representation @@ -640,13 +839,13 @@ export class ScMutableInt64 { // retrieve value from host container value(): i64 { - return Convert.toI64(getBytes(this.objID, this.keyID, host.TYPE_INT64)); + return Convert.toI64(host.getBytes(this.objID, this.keyID, host.TYPE_INT64)); } } // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ -// array proxy for mutable array of int64 +// array proxy for mutable array of Int64 export class ScMutableInt64Array { objID: i32; @@ -656,7 +855,7 @@ export class ScMutableInt64Array { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -672,7 +871,7 @@ export class ScMutableInt64Array { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -693,12 +892,12 @@ export class ScMutableMap { } callFunc(keyID: Key32, params: u8[]): u8[] { - return callFunc(this.objID, keyID, params); + return host.callFunc(this.objID, keyID, params); } // empty the map clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for mutable ScAddress field specified by key @@ -708,7 +907,7 @@ export class ScMutableMap { // get array proxy for ScMutableAddressArray specified by key getAddressArray(key: MapKey): ScMutableAddressArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_ADDRESS | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_ADDRESS | host.TYPE_ARRAY); return new ScMutableAddressArray(arrID); } @@ -719,18 +918,29 @@ export class ScMutableMap { // get array proxy for ScMutableAgentIDArray specified by key getAgentIDArray(key: MapKey): ScMutableAgentIDArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_AGENT_ID | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_AGENT_ID | host.TYPE_ARRAY); return new ScMutableAgentIDArray(arrID); } - // get value proxy for mutable bytes array field specified by key + // get value proxy for mutable Bool field specified by key + getBool(key: MapKey): ScMutableBool { + return new ScMutableBool(this.objID, key.getKeyID()); + } + + // get array proxy for ScMutableBoolArray specified by key + getBoolArray(key: MapKey): ScMutableBoolArray { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_BOOL | host.TYPE_ARRAY); + return new ScMutableBoolArray(arrID); + } + + // get value proxy for mutable Bytes array field specified by key getBytes(key: MapKey): ScMutableBytes { return new ScMutableBytes(this.objID, key.getKeyID()); } // get array proxy for ScMutableBytesArray specified by key getBytesArray(key: MapKey): ScMutableBytesArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_BYTES | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_BYTES | host.TYPE_ARRAY); return new ScMutableBytesArray(arrID); } @@ -741,7 +951,7 @@ export class ScMutableMap { // get array proxy for ScMutableChainIDArray specified by key getChainIDArray(key: MapKey): ScMutableChainIDArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_CHAIN_ID | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_CHAIN_ID | host.TYPE_ARRAY); return new ScMutableChainIDArray(arrID); } @@ -752,7 +962,7 @@ export class ScMutableMap { // get array proxy for ScMutableColorArray specified by key getColorArray(key: MapKey): ScMutableColorArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_COLOR | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_COLOR | host.TYPE_ARRAY); return new ScMutableColorArray(arrID); } @@ -763,7 +973,7 @@ export class ScMutableMap { // get array proxy for ScMutableHashArray specified by key getHashArray(key: MapKey): ScMutableHashArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_HASH | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_HASH | host.TYPE_ARRAY); return new ScMutableHashArray(arrID); } @@ -774,52 +984,63 @@ export class ScMutableMap { // get array proxy for ScMutableHnameArray specified by key getHnameArray(key: MapKey): ScMutableHnameArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_HNAME | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_HNAME | host.TYPE_ARRAY); return new ScMutableHnameArray(arrID); } - // get value proxy for mutable int16 field specified by key + // get value proxy for mutable Int8 field specified by key + getInt8(key: MapKey): ScMutableInt8 { + return new ScMutableInt8(this.objID, key.getKeyID()); + } + + // get array proxy for ScMutableInt8Array specified by key + getInt8Array(key: MapKey): ScMutableInt8Array { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT8 | host.TYPE_ARRAY); + return new ScMutableInt8Array(arrID); + } + + // get value proxy for mutable Int16 field specified by key getInt16(key: MapKey): ScMutableInt16 { return new ScMutableInt16(this.objID, key.getKeyID()); } // get array proxy for ScMutableInt16Array specified by key getInt16Array(key: MapKey): ScMutableInt16Array { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_INT16 | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT16 | host.TYPE_ARRAY); return new ScMutableInt16Array(arrID); } - // get value proxy for mutable int64 field specified by key - getInt64(key: MapKey): ScMutableInt64 { - return new ScMutableInt64(this.objID, key.getKeyID()); + // get value proxy for mutable Int32 field specified by key + getInt32(key: MapKey): ScMutableInt32 { + return new ScMutableInt32(this.objID, key.getKeyID()); } // get array proxy for ScMutableInt32Array specified by key getInt32Array(key: MapKey): ScMutableInt32Array { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_INT32 | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT32 | host.TYPE_ARRAY); return new ScMutableInt32Array(arrID); } - // get value proxy for mutable int32 field specified by key - getInt32(key: MapKey): ScMutableInt32 { - return new ScMutableInt32(this.objID, key.getKeyID()); + // get value proxy for mutable Int64 field specified by key + getInt64(key: MapKey): ScMutableInt64 { + return new ScMutableInt64(this.objID, key.getKeyID()); } // get array proxy for ScMutableInt64Array specified by key getInt64Array(key: MapKey): ScMutableInt64Array { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_INT64 | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT64 | host.TYPE_ARRAY); return new ScMutableInt64Array(arrID); } // get map proxy for ScMutableMap specified by key getMap(key: MapKey): ScMutableMap { - let mapID = getObjectID(this.objID, key.getKeyID(), host.TYPE_MAP); + let mapID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_MAP); return new ScMutableMap(mapID); } // get array proxy for ScMutableMapArray specified by key getMapArray(key: MapKey): ScMutableMapArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_MAP | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_MAP | host.TYPE_ARRAY); return new ScMutableMapArray(arrID); } @@ -830,7 +1051,7 @@ export class ScMutableMap { // get array proxy for ScMutableRequestIDArray specified by key getRequestIDArray(key: MapKey): ScMutableRequestIDArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_REQUEST_ID | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_REQUEST_ID | host.TYPE_ARRAY); return new ScMutableRequestIDArray(arrID); } @@ -841,10 +1062,54 @@ export class ScMutableMap { // get array proxy for ScMutableStringArray specified by key getStringArray(key: MapKey): ScMutableStringArray { - let arrID = getObjectID(this.objID, key.getKeyID(), host.TYPE_STRING | host.TYPE_ARRAY); + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_STRING | host.TYPE_ARRAY); return new ScMutableStringArray(arrID); } + // get value proxy for mutable Uint8 field specified by key + getUint8(key: MapKey): ScMutableUint8 { + return new ScMutableUint8(this.objID, key.getKeyID()); + } + + // get array proxy for ScMutableUint8Array specified by key + getUint8Array(key: MapKey): ScMutableUint8Array { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT8 | host.TYPE_ARRAY); + return new ScMutableUint8Array(arrID); + } + + // get value proxy for mutable Uint16 field specified by key + getUint16(key: MapKey): ScMutableUint16 { + return new ScMutableUint16(this.objID, key.getKeyID()); + } + + // get array proxy for ScMutableUint16Array specified by key + getUint16Array(key: MapKey): ScMutableUint16Array { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT16 | host.TYPE_ARRAY); + return new ScMutableUint16Array(arrID); + } + + // get value proxy for mutable Uint32 field specified by key + getUint32(key: MapKey): ScMutableUint32 { + return new ScMutableUint32(this.objID, key.getKeyID()); + } + + // get array proxy for ScMutableUint32Array specified by key + getUint32Array(key: MapKey): ScMutableUint32Array { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT32 | host.TYPE_ARRAY); + return new ScMutableUint32Array(arrID); + } + + // get value proxy for mutable Uint64 field specified by key + getUint64(key: MapKey): ScMutableUint64 { + return new ScMutableUint64(this.objID, key.getKeyID()); + } + + // get array proxy for ScMutableUint64Array specified by key + getUint64Array(key: MapKey): ScMutableUint64Array { + let arrID = host.getObjectID(this.objID, key.getKeyID(), host.TYPE_INT64 | host.TYPE_ARRAY); + return new ScMutableUint64Array(arrID); + } + // get immutable version of map proxy immutable(): ScImmutableMap { return new ScImmutableMap(this.objID); @@ -867,13 +1132,13 @@ export class ScMutableMapArray { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() // when index equals length() a new item is appended getMap(index: i32): ScMutableMap { - let mapID = getObjectID(this.objID, new Key32(index), host.TYPE_MAP); + let mapID = host.getObjectID(this.objID, new Key32(index), host.TYPE_MAP); return new ScMutableMap(mapID); } @@ -884,7 +1149,7 @@ export class ScMutableMapArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -900,14 +1165,19 @@ export class ScMutableRequestID { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_REQUEST_ID); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_REQUEST_ID); + return host.exists(this.objID, this.keyID, host.TYPE_REQUEST_ID); } // set value in host container setValue(val: ScRequestID): void { - setBytes(this.objID, this.keyID, host.TYPE_REQUEST_ID, val.toBytes()); + host.setBytes(this.objID, this.keyID, host.TYPE_REQUEST_ID, val.toBytes()); } // human-readable string representation @@ -917,7 +1187,7 @@ export class ScMutableRequestID { // retrieve value from host container value(): ScRequestID { - return ScRequestID.fromBytes(getBytes(this.objID, this.keyID, host.TYPE_REQUEST_ID)); + return ScRequestID.fromBytes(host.getBytes(this.objID, this.keyID, host.TYPE_REQUEST_ID)); } } @@ -933,7 +1203,7 @@ export class ScMutableRequestIDArray { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -949,7 +1219,7 @@ export class ScMutableRequestIDArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); } } @@ -965,14 +1235,19 @@ export class ScMutableString { this.keyID = keyID; } + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_STRING); + } + // check if value exists in host container exists(): boolean { - return exists(this.objID, this.keyID, host.TYPE_STRING); + return host.exists(this.objID, this.keyID, host.TYPE_STRING); } // set value in host container setValue(val: string): void { - setBytes(this.objID, this.keyID, host.TYPE_STRING, Convert.fromString(val)); + host.setBytes(this.objID, this.keyID, host.TYPE_STRING, Convert.fromString(val)); } // human-readable string representation @@ -982,7 +1257,7 @@ export class ScMutableString { // retrieve value from host container value(): string { - let bytes = getBytes(this.objID, this.keyID, host.TYPE_STRING); + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_STRING); return Convert.toString(bytes); } } @@ -999,7 +1274,7 @@ export class ScMutableStringArray { // empty the array clear(): void { - clear(this.objID); + host.clear(this.objID); } // get value proxy for item at index, index can be 0..length() @@ -1015,6 +1290,291 @@ export class ScMutableStringArray { // number of items in array length(): i32 { - return getLength(this.objID); + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Uint8 in host container +export class ScMutableUint8 { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_INT8); + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_INT8); + } + + // set value in host container + setValue(val: u8): void { + let bytes: u8[] = [val as u8]; + host.setBytes(this.objID, this.keyID, host.TYPE_INT8, bytes); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // retrieve value from host container + value(): u8 { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT8); + return bytes[0] as u8; + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for mutable array of Uint8 +export class ScMutableUint8Array { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // empty the array + clear(): void { + host.clear(this.objID); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + getUint8(index: i32): ScMutableUint8 { + return new ScMutableUint8(this.objID, new Key32(index)); + } + + // get immutable version of array proxy + immutable(): ScImmutableUint8Array { + return new ScImmutableUint8Array(this.objID); + } + + // number of items in array + length(): i32 { + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Uint16 in host container +export class ScMutableUint16 { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_INT16); + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_INT16); + } + + // set value in host container + setValue(val: u16): void { + host.setBytes(this.objID, this.keyID, host.TYPE_INT16, Convert.fromI16(val)); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // retrieve value from host container + value(): u16 { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT16); + return Convert.toI16(bytes) as u16; + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for mutable array of Uint16 +export class ScMutableUint16Array { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // empty the array + clear(): void { + host.clear(this.objID); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + getUint16(index: i32): ScMutableUint16 { + return new ScMutableUint16(this.objID, new Key32(index)); + } + + // get immutable version of array proxy + immutable(): ScImmutableUint16Array { + return new ScImmutableUint16Array(this.objID); + } + + // number of items in array + length(): i32 { + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Uint32 in host container +export class ScMutableUint32 { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_INT32); + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_INT32); + } + + // set value in host container + setValue(val: u32): void { + host.setBytes(this.objID, this.keyID, host.TYPE_INT32, Convert.fromI32(val)); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // retrieve value from host container + value(): u32 { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT32); + return Convert.toI32(bytes) as u32; + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for mutable array of Uint32 +export class ScMutableUint32Array { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // empty the array + clear(): void { + host.clear(this.objID); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + getUint32(index: i32): ScMutableUint32 { + return new ScMutableUint32(this.objID, new Key32(index)); + } + + // get immutable version of array proxy + immutable(): ScImmutableUint32Array { + return new ScImmutableUint32Array(this.objID); + } + + // number of items in array + length(): i32 { + return host.getLength(this.objID); + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// value proxy for mutable Uint64 in host container +export class ScMutableUint64 { + objID: i32; + keyID: Key32; + + constructor(objID: i32, keyID: Key32) { + this.objID = objID; + this.keyID = keyID; + } + + // delete value from host container + delete(): void { + host.delKey(this.objID, this.keyID, host.TYPE_INT64); + } + + // check if value exists in host container + exists(): boolean { + return host.exists(this.objID, this.keyID, host.TYPE_INT64); + } + + // set value in host container + setValue(val: u64): void { + host.setBytes(this.objID, this.keyID, host.TYPE_INT64, Convert.fromI64(val)); + } + + // human-readable string representation + toString(): string { + return this.value().toString(); + } + + // retrieve value from host container + value(): u64 { + let bytes = host.getBytes(this.objID, this.keyID, host.TYPE_INT64); + return Convert.toI64(bytes) as u64; + } +} + +// \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ + +// array proxy for mutable array of Uint64 +export class ScMutableUint64Array { + objID: i32; + + constructor(id: i32) { + this.objID = id; + } + + // empty the array + clear(): void { + host.clear(this.objID); + } + + // get value proxy for item at index, index can be 0..length() + // when index equals length() a new item is appended + getUint64(index: i32): ScMutableUint64 { + return new ScMutableUint64(this.objID, new Key32(index)); + } + + // get immutable version of array proxy + immutable(): ScImmutableUint64Array { + return new ScImmutableUint64Array(this.objID); + } + + // number of items in array + length(): i32 { + return host.getLength(this.objID); } } diff --git a/packages/vm/wasmproc/bytes.go b/packages/vm/wasmproc/bytes.go index cbc334b2bf..e05b2a6488 100644 --- a/packages/vm/wasmproc/bytes.go +++ b/packages/vm/wasmproc/bytes.go @@ -11,6 +11,10 @@ func NewBytesDecoder(data []byte) *BytesDecoder { return &BytesDecoder{data: data} } +func (d *BytesDecoder) Bool() bool { + return d.Int8() != 0 +} + func (d *BytesDecoder) Bytes() []byte { size := int(d.Int32()) if len(d.data) < size { @@ -21,6 +25,15 @@ func (d *BytesDecoder) Bytes() []byte { return value } +func (d *BytesDecoder) Int8() int8 { + if len(d.data) == 0 { + panic("insufficient bytes") + } + value := d.data[0] + d.data = d.data[1:] + return int8(value) +} + func (d *BytesDecoder) Int16() int16 { return int16(d.leb128Decode(16)) } @@ -62,6 +75,22 @@ func (d *BytesDecoder) leb128Decode(bits int) int64 { } } +func (d *BytesDecoder) Uint8() uint8 { + return uint8(d.Int8()) +} + +func (d *BytesDecoder) Uint16() uint16 { + return uint16(d.Int16()) +} + +func (d *BytesDecoder) Uint32() uint32 { + return uint32(d.Int32()) +} + +func (d *BytesDecoder) Uint64() uint64 { + return uint64(d.Int64()) +} + // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ // \\ type BytesEncoder struct { @@ -72,6 +101,13 @@ func NewBytesEncoder() *BytesEncoder { return &BytesEncoder{data: make([]byte, 0, 128)} } +func (e *BytesEncoder) Bool(value bool) *BytesEncoder { + if value { + return e.Int8(1) + } + return e.Int8(0) +} + func (e *BytesEncoder) Bytes(value []byte) *BytesEncoder { e.Int32(int32(len(value))) e.data = append(e.data, value...) @@ -82,6 +118,11 @@ func (e *BytesEncoder) Data() []byte { return e.data } +func (e *BytesEncoder) Int8(value int8) *BytesEncoder { + e.data = append(e.data, byte(value)) + return e +} + func (e *BytesEncoder) Int16(value int16) *BytesEncoder { return e.leb128Encode(int64(value)) } @@ -107,3 +148,19 @@ func (e *BytesEncoder) leb128Encode(value int64) *BytesEncoder { e.data = append(e.data, b|0x80) } } + +func (e *BytesEncoder) Uint8(value uint8) *BytesEncoder { + return e.Int8(int8(value)) +} + +func (e *BytesEncoder) Uint16(value uint16) *BytesEncoder { + return e.Int16(int16(value)) +} + +func (e *BytesEncoder) Uint32(value uint32) *BytesEncoder { + return e.Int32(int32(value)) +} + +func (e *BytesEncoder) Uint64(value uint64) *BytesEncoder { + return e.Int64(int64(value)) +} diff --git a/packages/vm/wasmproc/scbalances.go b/packages/vm/wasmproc/scbalances.go index 1821c6ed7e..ee02afb615 100644 --- a/packages/vm/wasmproc/scbalances.go +++ b/packages/vm/wasmproc/scbalances.go @@ -20,12 +20,12 @@ func NewScBalances(wc *WasmContext, keyID int32) *ScDict { switch keyID { case wasmhost.KeyIncoming: if wc.ctx == nil { - o.Panic("no incoming() on views") + o.Panicf("no incoming() on views") } return loadBalances(o, wc.ctx.IncomingTransfer()) case wasmhost.KeyMinted: if wc.ctx == nil { - o.Panic("no minted() on views") + o.Panicf("no minted() on views") } return loadBalances(o, wc.ctx.Minted()) @@ -35,7 +35,7 @@ func NewScBalances(wc *WasmContext, keyID int32) *ScDict { } return loadBalances(o, wc.ctxView.Balances()) } - o.Panic("unknown balances: %s", wc.GetKeyStringFromID(keyID)) + o.Panicf("unknown balances: %s", wc.GetKeyStringFromID(keyID)) return nil } diff --git a/packages/vm/wasmproc/sccontext.go b/packages/vm/wasmproc/sccontext.go index e6dd4df4e4..c0556303aa 100644 --- a/packages/vm/wasmproc/sccontext.go +++ b/packages/vm/wasmproc/sccontext.go @@ -35,6 +35,7 @@ var typeIds = map[int32]int32{ wasmhost.KeyPanic: wasmhost.OBJTYPE_STRING, wasmhost.KeyParams: wasmhost.OBJTYPE_MAP, wasmhost.KeyPost: wasmhost.OBJTYPE_BYTES, + wasmhost.KeyRandom: wasmhost.OBJTYPE_BYTES, wasmhost.KeyRequestID: wasmhost.OBJTYPE_REQUEST_ID, wasmhost.KeyResults: wasmhost.OBJTYPE_MAP, wasmhost.KeyReturn: wasmhost.OBJTYPE_MAP, @@ -70,7 +71,7 @@ func (o *ScContext) Exists(keyID, typeID int32) bool { func (o *ScContext) GetBytes(keyID, typeID int32) []byte { if o.wc == nil { - o.Panic("missing context") + o.Panicf("missing context") } ctx := o.wc.ctx if ctx == nil { @@ -89,6 +90,8 @@ func (o *ScContext) GetBytes(keyID, typeID int32) []byte { return ctx.Contract().Bytes() case wasmhost.KeyContractCreator: return ctx.ContractCreator().Bytes() + case wasmhost.KeyRandom: + return ctx.GetEntropy().Bytes() case wasmhost.KeyRequestID: return ctx.Request().ID().Bytes() case wasmhost.KeyTimestamp: @@ -102,7 +105,7 @@ func (o *ScContext) GetBytes(keyID, typeID int32) []byte { func (o *ScContext) getBytesForView(keyID, typeID int32) []byte { ctx := o.wc.ctxView if ctx == nil { - o.Panic("missing context") + o.Panicf("missing context") } switch keyID { case wasmhost.KeyAccountID: @@ -140,7 +143,7 @@ func (o *ScContext) GetObjectID(keyID, typeID int32) int32 { wasmhost.KeyReturn: func() WaspObject { return NewScDict(o.host, dict.New()) }, wasmhost.KeyState: func() WaspObject { return NewScDict(o.host, o.wc.state()) }, wasmhost.KeyTransfers: func() WaspObject { return NewScTransfers(o.wc) }, - wasmhost.KeyUtility: func() WaspObject { return NewScUtility(o.wc) }, + wasmhost.KeyUtility: func() WaspObject { return NewScUtility(o.wc, nil) }, }) } @@ -173,11 +176,11 @@ func (o *ScContext) processCall(bytes []byte) { decode := NewBytesDecoder(bytes) contract, err := iscp.HnameFromBytes(decode.Bytes()) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } function, err := iscp.HnameFromBytes(decode.Bytes()) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } params := o.getParams(decode.Int32()) transfer := o.getTransfer(decode.Int32()) @@ -185,7 +188,7 @@ func (o *ScContext) processCall(bytes []byte) { o.Tracef("CALL c'%s' f'%s'", contract.String(), function.String()) results, err := o.processCallUnlocked(contract, function, params, transfer) if err != nil { - o.Panic("failed to invoke call: %v", err) + o.Panicf("failed to invoke call: %v", err) } resultsID := o.GetObjectID(wasmhost.KeyReturn, wasmhost.OBJTYPE_MAP) o.host.FindObject(resultsID).(*ScDict).kvStore = results @@ -205,7 +208,7 @@ func (o *ScContext) processDeploy(bytes []byte) { decode := NewBytesDecoder(bytes) programHash, err := hashing.HashValueFromBytes(decode.Bytes()) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } name := string(decode.Bytes()) description := string(decode.Bytes()) @@ -213,7 +216,7 @@ func (o *ScContext) processDeploy(bytes []byte) { o.Tracef("DEPLOY c'%s' f'%s'", name, description) err = o.processDeployUnlocked(programHash, name, description, params) if err != nil { - o.Panic("failed to deploy: %v", err) + o.Panicf("failed to deploy: %v", err) } } @@ -228,21 +231,21 @@ func (o *ScContext) processPost(bytes []byte) { decode := NewBytesDecoder(bytes) chainID, err := iscp.ChainIDFromBytes(decode.Bytes()) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } contract, err := iscp.HnameFromBytes(decode.Bytes()) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } function, err := iscp.HnameFromBytes(decode.Bytes()) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } o.Tracef("POST c'%s' f'%s'", contract.String(), function.String()) params := o.getParams(decode.Int32()) transferID := decode.Int32() if transferID == 0 { - o.Panic("transfer is required for post") + o.Panicf("transfer is required for post") } transfer := o.getTransfer(transferID) metadata := &iscp.SendMetadata{ @@ -253,13 +256,13 @@ func (o *ScContext) processPost(bytes []byte) { delay := decode.Int32() if delay == 0 { if !o.wc.ctx.Send(chainID.AsAddress(), transfer, metadata) { - o.Panic("failed to send to %s", chainID.AsAddress().String()) + o.Panicf("failed to send to %s", chainID.AsAddress().String()) } return } if delay < 0 { - o.Panic("invalid delay: %d", delay) + o.Panicf("invalid delay: %d", delay) } timeLock := time.Unix(0, o.wc.ctx.GetTimestamp()) @@ -268,7 +271,7 @@ func (o *ScContext) processPost(bytes []byte) { TimeLock: uint32(timeLock.Unix()), } if !o.wc.ctx.Send(chainID.AsAddress(), transfer, metadata, options) { - o.Panic("failed to send to %s", chainID.AsAddress().String()) + o.Panicf("failed to send to %s", chainID.AsAddress().String()) } } @@ -293,11 +296,11 @@ func (o *ScContext) getTransfer(transferID int32) colored.Balances { transferDict.MustIterate("", func(key kv.Key, value []byte) bool { col, err := codec.DecodeColor([]byte(key)) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } amount, err := codec.DecodeUint64(value) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } o.Tracef(" XFER %d '%s'", amount, col.String()) transfer.Set(col, amount) diff --git a/packages/vm/wasmproc/scdict.go b/packages/vm/wasmproc/scdict.go index dbab9ee07a..1ddd454dd1 100644 --- a/packages/vm/wasmproc/scdict.go +++ b/packages/vm/wasmproc/scdict.go @@ -8,7 +8,6 @@ import ( "fmt" "strings" - "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/wasp/packages/kv" "github.com/iotaledger/wasp/packages/kv/codec" "github.com/iotaledger/wasp/packages/vm/wasmhost" @@ -22,7 +21,7 @@ type ( type WaspObject interface { wasmhost.HostObject InitObj(id int32, keyID int32, owner *ScDict) - Panic(format string, args ...interface{}) + Panicf(format string, args ...interface{}) FindOrMakeObjectID(keyID int32, factory ObjFactory) int32 NestedKey() string Suffix(keyID int32) string @@ -30,10 +29,10 @@ type WaspObject interface { func GetArrayObjectID(arrayObj WaspObject, index, typeID int32, factory ObjFactory) int32 { if !arrayObj.Exists(index, typeID) { - arrayObj.Panic("GetArrayObjectID: invalid index") + arrayObj.Panicf("GetArrayObjectID: invalid index") } if typeID != arrayObj.GetTypeID(index) { - arrayObj.Panic("GetArrayObjectID: invalid type") + arrayObj.Panicf("GetArrayObjectID: invalid type") } return arrayObj.FindOrMakeObjectID(index, factory) } @@ -41,10 +40,10 @@ func GetArrayObjectID(arrayObj WaspObject, index, typeID int32, factory ObjFacto func GetMapObjectID(mapObj WaspObject, keyID, typeID int32, factories ObjFactories) int32 { factory, ok := factories[keyID] if !ok { - mapObj.Panic("GetMapObjectID: invalid key") + mapObj.Panicf("GetMapObjectID: invalid key") } if typeID != mapObj.GetTypeID(keyID) { - mapObj.Panic("GetMapObjectID: invalid type") + mapObj.Panicf("GetMapObjectID: invalid type") } return mapObj.FindOrMakeObjectID(keyID, factory) } @@ -69,8 +68,6 @@ type ScDict struct { var _ WaspObject = &ScDict{} -var typeSizes = [...]int{0, 33, 37, 0, 33, 32, 32, 4, 2, 4, 8, 0, 34, 0} - func NewScDict(host *wasmhost.KvStoreHost, kvStore kv.KVStore) *ScDict { return &ScDict{host: host, kvStore: kvStore} } @@ -104,7 +101,7 @@ func (o *ScDict) InitObj(id, keyID int32, owner *ScDict) { if (o.typeID&wasmhost.OBJTYPE_ARRAY) != 0 && o.kvStore != nil { err := o.getArrayLength() if err != nil { - o.Panic("InitObj: %v", err) + o.Panicf("InitObj: %v", err) } } o.Tracef("InitObj %s", o.name) @@ -113,10 +110,20 @@ func (o *ScDict) InitObj(id, keyID int32, owner *ScDict) { } func (o *ScDict) CallFunc(keyID int32, params []byte) []byte { - o.Panic("CallFunc: invalid call") + o.Panicf("CallFunc: invalid call") return nil } +func (o *ScDict) DelKey(keyID, typeID int32) { + if (typeID & wasmhost.OBJTYPE_ARRAY) != 0 { + o.Panicf("DelKey: cannot delete array") + } + if typeID == wasmhost.OBJTYPE_MAP { + o.Panicf("DelKey: cannot delete map") + } + o.kvStore.Del(o.key(keyID, typeID)) +} + func (o *ScDict) Exists(keyID, typeID int32) bool { if keyID == wasmhost.KeyLength && (o.typeID&wasmhost.OBJTYPE_ARRAY) != 0 { return true @@ -166,14 +173,14 @@ func (o *ScDict) GetBytes(keyID, typeID int32) []byte { return codec.EncodeInt32(o.length) } bytes := o.kvStore.MustGet(o.key(keyID, typeID)) - o.typeCheck(typeID, bytes) + o.host.TypeCheck(typeID, bytes) return bytes } func (o *ScDict) GetObjectID(keyID, typeID int32) int32 { o.validate(keyID, typeID) if (typeID&wasmhost.OBJTYPE_ARRAY) == 0 && typeID != wasmhost.OBJTYPE_MAP { - o.Panic("GetObjectID: invalid type") + o.Panicf("GetObjectID: invalid type") } return GetMapObjectID(o, keyID, typeID, ObjFactories{ keyID: func() WaspObject { return &ScDict{} }, @@ -193,7 +200,7 @@ func (o *ScDict) GetTypeID(keyID int32) int32 { } func (o *ScDict) InvalidKey(keyID int32) { - o.Panic("invalid key: %d", keyID) + o.Panicf("invalid key: %d", keyID) } func (o *ScDict) key(keyID, typeID int32) kv.Key { @@ -221,11 +228,8 @@ func (o *ScDict) Owner() WaspObject { return o.host.FindObject(o.ownerID).(WaspObject) } -//nolint:goprintffuncname -func (o *ScDict) Panic(format string, args ...interface{}) { - err := o.name + "." + fmt.Sprintf(format, args...) - o.Tracef(err) - panic(err) +func (o *ScDict) Panicf(format string, args ...interface{}) { + o.host.Panicf(o.name+"."+format, args...) } func (o *ScDict) SetBytes(keyID, typeID int32, bytes []byte) { @@ -244,7 +248,7 @@ func (o *ScDict) SetBytes(keyID, typeID int32, bytes []byte) { } key := o.key(keyID, typeID) - o.typeCheck(typeID, bytes) + o.host.TypeCheck(typeID, bytes) o.kvStore.Set(key, bytes) } @@ -268,38 +272,9 @@ func (o *ScDict) Tracef(format string, a ...interface{}) { o.host.Tracef(format, a...) } -func (o *ScDict) typeCheck(typeID int32, bytes []byte) { - typeSize := typeSizes[typeID] - if typeSize != 0 && typeSize != len(bytes) { - o.Panic("typeCheck: invalid type size") - } - switch typeID { - case wasmhost.OBJTYPE_ADDRESS: - // address bytes must start with valid address type - if ledgerstate.AddressType(bytes[0]) > ledgerstate.AliasAddressType { - o.Panic("typeCheck: invalid address type") - } - case wasmhost.OBJTYPE_AGENT_ID: - // address bytes in agent id must start with valid address type - if ledgerstate.AddressType(bytes[0]) > ledgerstate.AliasAddressType { - o.Panic("typeCheck: invalid agent id address type") - } - case wasmhost.OBJTYPE_CHAIN_ID: - // chain id must be alias address - if ledgerstate.AddressType(bytes[0]) != ledgerstate.AliasAddressType { - o.Panic("typeCheck: invalid chain id address type") - } - case wasmhost.OBJTYPE_REQUEST_ID: - outputIndex := binary.LittleEndian.Uint16(bytes[ledgerstate.TransactionIDLength:]) - if outputIndex > ledgerstate.MaxOutputCount { - o.Panic("typeCheck: invalid request id output index") - } - } -} - func (o *ScDict) validate(keyID, typeID int32) { if o.kvStore == nil { - o.Panic("validate: Missing kvstore") + o.Panicf("validate: Missing kvstore") } if typeID == -1 { return @@ -315,10 +290,10 @@ func (o *ScDict) validate(keyID, typeID int32) { case wasmhost.OBJTYPE_COLOR: case wasmhost.OBJTYPE_HASH: default: - o.Panic("validate: Invalid byte type") + o.Panicf("validate: Invalid byte type") } } else if arrayTypeID != typeID { - o.Panic("validate: Invalid type") + o.Panicf("validate: Invalid type") } if keyID == o.length { switch o.kvStore.(type) { @@ -332,7 +307,7 @@ func (o *ScDict) validate(keyID, typeID int32) { } } if keyID < 0 || keyID >= o.length { - o.Panic("validate: Invalid index") + o.Panicf("validate: Invalid index") } return } @@ -344,7 +319,7 @@ func (o *ScDict) validate(keyID, typeID int32) { return } if fieldType != typeID { - o.Panic("validate: Invalid access") + o.Panicf("validate: Invalid access") } } diff --git a/packages/vm/wasmproc/scsandbox.go b/packages/vm/wasmproc/scsandbox.go index 1671bbcbf5..d0b7311e5a 100644 --- a/packages/vm/wasmproc/scsandbox.go +++ b/packages/vm/wasmproc/scsandbox.go @@ -8,6 +8,10 @@ type ScSandboxObject struct { ScDict } +func (o *ScSandboxObject) DelKey(keyID, typeID int32) { + o.Panicf("DelKey: cannot delete predefined key") +} + func (o *ScSandboxObject) GetBytes(keyID, typeID int32) []byte { if keyID == wasmhost.KeyLength && (o.typeID&wasmhost.OBJTYPE_ARRAY) != 0 { return o.ScDict.GetBytes(keyID, typeID) diff --git a/packages/vm/wasmproc/sctransfer.go b/packages/vm/wasmproc/sctransfer.go index 567624cd28..30ff36e3c4 100644 --- a/packages/vm/wasmproc/sctransfer.go +++ b/packages/vm/wasmproc/sctransfer.go @@ -50,18 +50,18 @@ func (o *ScTransferInfo) Invoke(balances int32) { } col, err := codec.DecodeColor([]byte(key)) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } amount, err := codec.DecodeUint64(value) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } o.Tracef("TRANSFER #%d c'%s' a'%s'", value, col.String(), o.address.Base58()) transfer.Set(col, amount) return true }) if !o.wc.ctx.Send(o.address, transfer, nil) { - o.Panic("failed to send to %s", o.address.Base58()) + o.Panicf("failed to send to %s", o.address.Base58()) } } @@ -71,12 +71,12 @@ func (o *ScTransferInfo) SetBytes(keyID, typeID int32, bytes []byte) { var err error o.address, _, err = ledgerstate.AddressFromBytes(bytes) if err != nil { - o.Panic("SetBytes: invalid address: " + err.Error()) + o.Panicf("SetBytes: invalid address: " + err.Error()) } case wasmhost.KeyBalances: balanceMapID, err := codec.DecodeInt32(bytes, 0) if err != nil { - o.Panic("SetBytes: invalid balance map id: " + err.Error()) + o.Panicf("SetBytes: invalid balance map id: " + err.Error()) } o.Invoke(balanceMapID) default: diff --git a/packages/vm/wasmproc/scutility.go b/packages/vm/wasmproc/scutility.go index e9e5657e89..2cf6c16d4a 100644 --- a/packages/vm/wasmproc/scutility.go +++ b/packages/vm/wasmproc/scutility.go @@ -4,46 +4,37 @@ package wasmproc import ( - "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/kv/codec" "github.com/iotaledger/wasp/packages/vm/sandbox/sandbox_utils" "github.com/iotaledger/wasp/packages/vm/wasmhost" ) -var TestMode = false - type ScUtility struct { ScSandboxObject - nextRandom int - random []byte - utils iscp.Utils - wc *WasmContext + utils iscp.Utils + wc *WasmContext } -func NewScUtility(wc *WasmContext) *ScUtility { +func NewScUtility(wc *WasmContext, gasProcessor interface{}) *ScUtility { + //if gasProcessor == nil { + // if wc.ctx != nil { + // gasProcessor = wc.ctx.Gas() + // } else { + // gasProcessor = wc.ctxView.Gas() + // } + //} + //return &ScUtility{utils: sandbox.NewUtils(gasProcessor), wc: wc} return &ScUtility{utils: sandbox_utils.NewUtils(), wc: wc} } -func (o *ScUtility) InitObj(id, keyID int32, owner *ScDict) { - o.ScSandboxObject.InitObj(id, keyID, owner) - if TestMode { - // preset randomizer to generate sequence 1..8 before - // continuing with proper hashed values - o.random = make([]byte, 8*8) - for i := 0; i < len(o.random); i += 8 { - o.random[i] = byte(i + 1) - } - } -} - func (o *ScUtility) CallFunc(keyID int32, bytes []byte) []byte { utils := o.utils switch keyID { case wasmhost.KeyBase58Decode: base58Decoded, err := utils.Base58().Decode(string(bytes)) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } return base58Decoded case wasmhost.KeyBase58Encode: @@ -51,7 +42,7 @@ func (o *ScUtility) CallFunc(keyID int32, bytes []byte) []byte { case wasmhost.KeyBlsAddress: address, err := utils.BLS().AddressFromPublicKey(bytes) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } return address.Bytes() case wasmhost.KeyBlsAggregate: @@ -65,7 +56,7 @@ func (o *ScUtility) CallFunc(keyID int32, bytes []byte) []byte { case wasmhost.KeyEd25519Address: address, err := utils.ED25519().AddressFromPublicKey(bytes) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } return address.Bytes() case wasmhost.KeyEd25519Valid: @@ -80,8 +71,6 @@ func (o *ScUtility) CallFunc(keyID int32, bytes []byte) []byte { return utils.Hashing().Sha3(bytes).Bytes() case wasmhost.KeyHname: return codec.EncodeHname(utils.Hashing().Hname(string(bytes))) - case wasmhost.KeyRandom: - return o.getRandom8Bytes() } o.InvalidKey(keyID) return nil @@ -91,24 +80,6 @@ func (o *ScUtility) Exists(keyID, typeID int32) bool { return o.GetTypeID(keyID) > 0 } -func (o *ScUtility) getRandom8Bytes() []byte { - if o.random == nil { - // need to initialize pseudo-random generator with - // a sufficiently random, yet deterministic, value - id := o.wc.ctx.GetEntropy() - o.random = id[:] - } - i := o.nextRandom - if i+8 > len(o.random) { - // not enough bytes left, generate more bytes - h := hashing.HashData(o.random) - o.random = h[:] - i = 0 - } - o.nextRandom = i + 8 - return o.random[i : i+8] -} - func (o *ScUtility) GetTypeID(keyID int32) int32 { return wasmhost.OBJTYPE_BYTES } @@ -127,7 +98,7 @@ func (o *ScUtility) aggregateBLSSignatures(bytes []byte) []byte { } pubKeyBin, sigBin, err := o.utils.BLS().AggregateBLSSignatures(pubKeysBin, sigsBin) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } return NewBytesEncoder().Bytes(pubKeyBin).Bytes(sigBin).Data() } diff --git a/packages/vm/wasmproc/wasmcontext.go b/packages/vm/wasmproc/wasmcontext.go index 326193746d..20b416e657 100644 --- a/packages/vm/wasmproc/wasmcontext.go +++ b/packages/vm/wasmproc/wasmcontext.go @@ -9,8 +9,7 @@ import ( ) const ( - FuncDefault = "_default" - ViewCopyAllState = "copy_all_state" + FuncDefault = "_default" ) type WasmContext struct { @@ -88,18 +87,6 @@ func (wc *WasmContext) Call(ctx interface{}) (dict.Dict, error) { return nil, nil } - // TODO decide if we want be able to examine state directly from tests - //if wc.function == ViewCopyAllState { - // // dump copy of entire state into result - // state := wc.ctxView.State() - // results := dict.New() - // state.MustIterate("", func(key kv.Key, value []byte) bool { - // results.Set(key, value) - // return true - // }) - // return results, nil - //} - wc.Tracef("Calling " + wc.function) err := wc.callFunction() if err != nil { diff --git a/packages/vm/wasmproc/wasmprocessor.go b/packages/vm/wasmproc/wasmprocessor.go index 511d3d53ef..d06e8db726 100644 --- a/packages/vm/wasmproc/wasmprocessor.go +++ b/packages/vm/wasmproc/wasmprocessor.go @@ -18,34 +18,41 @@ type WasmProcessor struct { currentContextID int32 instanceLock sync.Mutex log *logger.Logger + mainProcessor *WasmProcessor nextContextID int32 scContext *WasmContext + wasmVM func() wasmhost.WasmVM } var _ iscp.VMProcessor = &WasmProcessor{} -var GoWasmVM wasmhost.WasmVM +var GoWasmVM func() wasmhost.WasmVM // GetProcessor creates a new Wasm VM processor. -func GetProcessor(binaryCode []byte, log *logger.Logger) (iscp.VMProcessor, error) { - vm := GoWasmVM - GoWasmVM = nil - if vm == nil { - vm = wasmhost.NewWasmTimeVM() +func GetProcessor(wasmBytes []byte, log *logger.Logger) (iscp.VMProcessor, error) { + proc := &WasmProcessor{log: log, contexts: make(map[int32]*WasmContext), wasmVM: wasmhost.NewWasmTimeVM} + proc.Init() + + // By default we will use WasmTimeVM, but this can be overruled by setting GoWasmVm + // This setting will also be propagated to all the sub-processors of this processor + if GoWasmVM != nil { + proc.wasmVM = GoWasmVM + GoWasmVM = nil } - proc := &WasmProcessor{log: log, contexts: make(map[int32]*WasmContext)} - err := proc.InitVM(vm, proc) + // Run setup on main processor, because we will be sharing stuff with the sub-processors + err := proc.InitVM(proc.wasmVM(), proc) if err != nil { return nil, err } - proc.Init() - // TODO decide if we want be able to examine state directly from tests - // proc.SetExport(0x8fff, ViewCopyAllState) proc.scContext = NewWasmContext("", proc) wasmhost.Connect(proc.scContext) - err = proc.LoadWasm(binaryCode) + err = proc.LoadWasm(wasmBytes) + if err != nil { + return nil, err + } + err = proc.RunFunction("on_load") if err != nil { return nil, err } @@ -68,18 +75,6 @@ func (proc *WasmProcessor) GetDefaultEntryPoint() iscp.VMProcessorEntryPoint { return proc.wasmContext(FuncDefault) } -func (proc *WasmProcessor) wasmContext(function string) *WasmContext { - wc := NewWasmContext(function, proc) - - proc.contextLock.Lock() - defer proc.contextLock.Unlock() - - proc.nextContextID++ - wc.id = proc.nextContextID - proc.contexts[wc.id] = wc - return wc -} - func (proc *WasmProcessor) GetKvStore(id int32) *wasmhost.KvStoreHost { if id == 0 { id = proc.currentContextID @@ -89,15 +84,58 @@ func (proc *WasmProcessor) GetKvStore(id int32) *wasmhost.KvStoreHost { return &proc.scContext.KvStoreHost } - proc.contextLock.Lock() - defer proc.contextLock.Unlock() + mainProcessor := proc + if proc.mainProcessor != nil { + mainProcessor = proc.mainProcessor + } + mainProcessor.contextLock.Lock() + defer mainProcessor.contextLock.Unlock() - return &proc.contexts[id].KvStoreHost + return &mainProcessor.contexts[id].KvStoreHost } func (proc *WasmProcessor) KillContext(id int32) { proc.contextLock.Lock() defer proc.contextLock.Unlock() - delete(proc.contexts, id) } + +func (proc *WasmProcessor) wasmContext(function string) *WasmContext { + processor := proc + vmInstance := proc.NewInstance() + if vmInstance != nil { + processor = proc.getSubProcessor(vmInstance) + } + wc := NewWasmContext(function, processor) + + proc.contextLock.Lock() + defer proc.contextLock.Unlock() + + proc.nextContextID++ + wc.id = proc.nextContextID + proc.contexts[wc.id] = wc + return wc +} + +func (proc *WasmProcessor) getSubProcessor(vmInstance wasmhost.WasmVM) *WasmProcessor { + processor := &WasmProcessor{log: proc.log, mainProcessor: proc, wasmVM: proc.wasmVM} + processor.Init() + err := processor.InitVM(vmInstance, processor) + if err != nil { + panic("Cannot clone processor: " + err.Error()) + } + + processor.scContext = NewWasmContext("", processor) + wasmhost.Connect(processor.scContext) + err = processor.Instantiate() + if err != nil { + panic("Cannot instantiate: " + err.Error()) + } + + // TODO reuse on_load data from main processor + err = processor.RunFunction("on_load") + if err != nil { + panic("Cannot run on_load: " + err.Error()) + } + return processor +} diff --git a/packages/vm/wasmsolo/solocontext.go b/packages/vm/wasmsolo/solocontext.go index 3cec105f40..479ce39b22 100644 --- a/packages/vm/wasmsolo/solocontext.go +++ b/packages/vm/wasmsolo/solocontext.go @@ -30,9 +30,10 @@ const ( ) var ( - GoDebug = flag.Bool("godebug", false, "debug go smart contract code") - GoWasm = flag.Bool("gowasm", false, "prefer go wasm smart contract code") - TsWasm = flag.Bool("tswasm", false, "prefer typescript wasm smart contract code") + GoDebug = flag.Bool("godebug", false, "debug go smart contract code") + GoWasm = flag.Bool("gowasm", false, "prefer go wasm smart contract code") + GoWasmEdge = flag.Bool("gowasmedge", false, "use WasmEdge instead of WasmTime") + TsWasm = flag.Bool("tswasm", false, "prefer typescript wasm smart contract code") ) type SoloContext struct { @@ -52,10 +53,24 @@ type SoloContext struct { } var ( + //_ iscp.Gas = &SoloContext{} _ wasmlib.ScFuncCallContext = &SoloContext{} _ wasmlib.ScViewCallContext = &SoloContext{} ) +func (ctx *SoloContext) Burn(i int64) { + // ignore gas for now +} + +func (ctx *SoloContext) Budget() int64 { + // ignore gas for now + return 0 +} + +func (ctx *SoloContext) SetBudget(i int64) { + // ignore gas for now +} + // NewSoloContext can be used to create a SoloContext associated with a smart contract // with minimal information and will verify successful creation before returning ctx. // It will start a default chain "chain1" before initializing the smart contract. @@ -96,8 +111,13 @@ func NewSoloContextForChain(t *testing.T, chain *solo.Chain, creator *SoloAgent, params = init[0].Params() } if *GoDebug { - wasmproc.GoWasmVM = wasmhost.NewWasmGoVM(ctx.scName, onLoad) + wasmproc.GoWasmVM = func() wasmhost.WasmVM { + return wasmhost.NewWasmGoVM(ctx.scName, onLoad) + } } + //if *GoWasmEdge && wasmproc.GoWasmVM == nil { + // wasmproc.GoWasmVM = wasmhost.NewWasmEdgeVM + //} ctx.Err = ctx.Chain.DeployContract(keyPair, ctx.scName, ctx.Hprog, params...) if *GoDebug { // just in case deploy failed we don't want to leave this around @@ -150,6 +170,10 @@ func soloContext(t *testing.T, chain *solo.Chain, scName string, creator *SoloAg // StartChain starts a new chain named chainName. func StartChain(t *testing.T, chainName string, env ...*solo.Solo) *solo.Chain { + if SoloDebug { + // avoid pesky timeouts during debugging + wasmhost.DisableWasmTimeout = true + } wasmhost.HostTracing = SoloHostTracing // wasmhost.HostTracingAll = SoloHostTracing @@ -320,27 +344,31 @@ func (ctx *SoloContext) upload(keyPair *ed25519.KeyPair) { return } + // start with file in test folder wasmFile := ctx.scName + "_bg.wasm" - // try Rust first - exists, _ := util.ExistsFilePath("../pkg/" + wasmFile) + // try (newer?) Rust Wasm file first + rsFile := "../pkg/" + wasmFile + exists, _ := util.ExistsFilePath(rsFile) if exists { - wasmFile = "../pkg/" + wasmFile + wasmFile = rsFile } - if *GoWasm { - wasmFile = ctx.scName + "_go.wasm" - exists, _ = util.ExistsFilePath("../go/pkg/" + wasmFile) + // try Go Wasm file? + if !exists || *GoWasm { + goFile := "../go/pkg/" + ctx.scName + "_go.wasm" + exists, _ = util.ExistsFilePath(goFile) if exists { - wasmFile = "../go/pkg/" + wasmFile + wasmFile = goFile } } - if *TsWasm { - wasmFile = ctx.scName + "_ts.wasm" - exists, _ = util.ExistsFilePath("../ts/pkg/" + wasmFile) + // try TypeScript Wasm file? + if !exists || *TsWasm { + tsFile := "../ts/pkg/" + ctx.scName + "_ts.wasm" + exists, _ = util.ExistsFilePath(tsFile) if exists { - wasmFile = "../ts/pkg/" + wasmFile + wasmFile = tsFile } } diff --git a/packages/vm/wasmsolo/solosccontext.go b/packages/vm/wasmsolo/solosccontext.go index a1053a0be8..b355b0232f 100644 --- a/packages/vm/wasmsolo/solosccontext.go +++ b/packages/vm/wasmsolo/solosccontext.go @@ -51,7 +51,7 @@ func (o *SoloScContext) GetObjectID(keyID, typeID int32) int32 { wasmhost.KeyReturn: func() wasmproc.WaspObject { return wasmproc.NewScDict(&host.KvStoreHost, dict.New()) }, // wasmhost.KeyState: func() wasmproc.WaspObject { return wasmproc.NewScDict(o.host, o.vm.state()) }, // wasmhost.KeyTransfers: func() wasmproc.WaspObject { return wasmproc.NewScTransfers(o.vm) }, - wasmhost.KeyUtility: func() wasmproc.WaspObject { return wasmproc.NewScUtility(nil) }, + wasmhost.KeyUtility: func() wasmproc.WaspObject { return wasmproc.NewScUtility(nil, o.ctx) }, }) } @@ -74,11 +74,11 @@ func (o *SoloScContext) processCall(bytes []byte) { decode := wasmproc.NewBytesDecoder(bytes) contract, err := iscp.HnameFromBytes(decode.Bytes()) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } function, err := iscp.HnameFromBytes(decode.Bytes()) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } paramsID := decode.Int32() transferID := decode.Int32() @@ -90,7 +90,7 @@ func (o *SoloScContext) processCall(bytes []byte) { ctx := o.ctx funcName := ctx.wc.FunctionFromCode(uint32(function)) if funcName == "" { - o.Panic("unknown function") + o.Panicf("unknown function") } o.Tracef("CALL %s.%s", ctx.scName, funcName) params := o.getParams(paramsID) @@ -99,7 +99,7 @@ func (o *SoloScContext) processCall(bytes []byte) { _ = wasmhost.Connect(ctx.wc) ctx.Err = err if err != nil { - // o.Panic("failed to invoke call: " + err.Error()) + // o.Panicf("failed to invoke call: " + err.Error()) return } returnID := o.GetObjectID(wasmhost.KeyReturn, wasmhost.OBJTYPE_MAP) @@ -110,18 +110,18 @@ func (o *SoloScContext) processPost(bytes []byte) { decode := wasmproc.NewBytesDecoder(bytes) chainID, err := iscp.ChainIDFromBytes(decode.Bytes()) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } if !chainID.Equals(o.ctx.Chain.ChainID) { - o.Panic("invalid chainID") + o.Panicf("invalid chainID") } contract, err := iscp.HnameFromBytes(decode.Bytes()) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } function, err := iscp.HnameFromBytes(decode.Bytes()) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } paramsID := decode.Int32() transferID := decode.Int32() @@ -135,13 +135,13 @@ func (o *SoloScContext) processPost(bytes []byte) { //delay := decode.Int32() //if delay == 0 { // if !o.vm.ctx.Send(chainID.AsAddress(), transfer, metadata) { - // o.Panic("failed to send to %s", chainID.AsAddress().String()) + // o.Panicf("failed to send to %s", chainID.AsAddress().String()) // } // return //} // //if delay < -1 { - // o.Panic("invalid delay: %d", delay) + // o.Panicf("invalid delay: %d", delay) //} // //timeLock := time.Unix(0, o.vm.ctx.GetTimestamp()) @@ -150,7 +150,7 @@ func (o *SoloScContext) processPost(bytes []byte) { // TimeLock: uint32(timeLock.Unix()), //} //if !o.vm.ctx.Send(chainID.AsAddress(), transfer, metadata, options) { - // o.Panic("failed to send to %s", chainID.AsAddress().String()) + // o.Panicf("failed to send to %s", chainID.AsAddress().String()) //} } @@ -175,11 +175,11 @@ func (o *SoloScContext) getTransfer(transferID int32) colored.Balances { transferDict.MustIterate("", func(key kv.Key, value []byte) bool { color, err := codec.DecodeColor([]byte(key)) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } amount, err := codec.DecodeUint64(value) if err != nil { - o.Panic(err.Error()) + o.Panicf(err.Error()) } o.Tracef(" XFER %d '%s'", amount, color.String()) transfer[color] = amount @@ -190,15 +190,15 @@ func (o *SoloScContext) getTransfer(transferID int32) colored.Balances { func (o *SoloScContext) postSync(contract, function iscp.Hname, paramsID, transferID, delay int32) { if delay != 0 { - o.Panic("unsupported nonzero delay for SoloContext") + o.Panicf("unsupported nonzero delay for SoloContext") } ctx := o.ctx if contract != iscp.Hn(ctx.scName) { - o.Panic("invalid contract") + o.Panicf("invalid contract") } funcName := ctx.wc.FunctionFromCode(uint32(function)) if funcName == "" { - o.Panic("unknown function") + o.Panicf("unknown function") } o.Tracef("POST %s.%s", ctx.scName, funcName) params := o.getParams(paramsID) diff --git a/packages/wasp/constants.go b/packages/wasp/constants.go index 9536098605..265409ec52 100644 --- a/packages/wasp/constants.go +++ b/packages/wasp/constants.go @@ -4,7 +4,7 @@ var VersionHash string const ( // Version version number - Version = "0.2.2" + Version = "0.2.3" // Name app code name Name = "Wasp" diff --git a/packages/webapi/admapi/chainnodeconnmetrics.go b/packages/webapi/admapi/chainnodeconnmetrics.go new file mode 100644 index 0000000000..cc7f442458 --- /dev/null +++ b/packages/webapi/admapi/chainnodeconnmetrics.go @@ -0,0 +1,105 @@ +package admapi + +import ( + "fmt" + "net/http" + "time" + + "github.com/iotaledger/wasp/packages/chains" + "github.com/iotaledger/wasp/packages/iscp" + "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 addChainStatsEndpoints(adm echoswagger.ApiGroup, chainsProvider chains.Provider) { + chainExample := &model.NodeConnectionMessagesMetrics{ + OutPullState: &model.NodeConnectionMessageMetrics{ + Total: 15, + LastEvent: time.Now().Add(-10 * time.Second), + LastMessage: "Last sent PullState message structure", + }, + OutPullTransactionInclusionState: &model.NodeConnectionMessageMetrics{ + Total: 28, + LastEvent: time.Now().Add(-5 * time.Second), + LastMessage: "Last sent PullTransactionInclusionState message structure", + }, + OutPullConfirmedOutput: &model.NodeConnectionMessageMetrics{ + Total: 132, + LastEvent: time.Now().Add(100 * time.Second), + LastMessage: "Last sent PullConfirmedOutput message structure", + }, + OutPostTransaction: &model.NodeConnectionMessageMetrics{ + Total: 3, + LastEvent: time.Now().Add(-2 * time.Millisecond), + LastMessage: "Last sent PostTransaction message structure", + }, + InTransaction: &model.NodeConnectionMessageMetrics{ + Total: 101, + LastEvent: time.Now().Add(-8 * time.Second), + LastMessage: "Last received Transaction message structure", + }, + InInclusionState: &model.NodeConnectionMessageMetrics{ + Total: 203, + LastEvent: time.Now().Add(-123 * time.Millisecond), + LastMessage: "Last received InclusionState message structure", + }, + InOutput: &model.NodeConnectionMessageMetrics{ + Total: 85, + LastEvent: time.Now().Add(-2 * time.Second), + LastMessage: "Last received Output message structure", + }, + InUnspentAliasOutput: &model.NodeConnectionMessageMetrics{ + Total: 999, + LastEvent: time.Now().Add(-1 * time.Second), + LastMessage: "Last received UnspentAliasOutput message structure", + }, + } + + example := &model.NodeConnectionMetrics{ + NodeConnectionMessagesMetrics: *chainExample, + Subscribed: []model.Address{ + model.NewAddress(iscp.RandomChainID().AsAddress()), + model.NewAddress(iscp.RandomChainID().AsAddress()), + }, + } + + s := &chainStatsService{chainsProvider} + + adm.GET(routes.GetChainsNodeConnectionMetrics(), s.handleGetChainsStats). + SetSummary("Get cummulative chains state statistics"). + AddResponse(http.StatusOK, "Chains Stats", example, nil) + + adm.GET(routes.GetChainNodeConnectionMetrics(":chainID"), s.handleGetChainStats). + SetSummary("Get chain state statistics for the given chain ID"). + AddParamPath("", "chainID", "ChainID (base58)"). + AddResponse(http.StatusOK, "Chain Stats", chainExample, nil) +} + +type chainStatsService struct { + chains chains.Provider +} + +func (cssT *chainStatsService) handleGetChainsStats(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 { + chainID, err := iscp.ChainIDFromBase58(c.Param("chainID")) + if err != nil { + return httperrors.BadRequest(err.Error()) + } + theChain := cssT.chains().Get(chainID) + if theChain == nil { + return httperrors.NotFound(fmt.Sprintf("Active chain %s not found", chainID)) + } + metrics := theChain.GetNodeConnectionMetrics() + metricsModel := model.NewNodeConnectionMessagesMetrics(metrics) + + return c.JSON(http.StatusOK, metricsModel) +} diff --git a/packages/webapi/admapi/committeerecord.go b/packages/webapi/admapi/committeerecord.go index b144987424..998f6bb2a7 100644 --- a/packages/webapi/admapi/committeerecord.go +++ b/packages/webapi/admapi/committeerecord.go @@ -3,6 +3,7 @@ package admapi import ( "fmt" "net/http" + "strconv" "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/wasp/packages/chains" @@ -91,7 +92,8 @@ func (s *committeeRecordService) handleGetCommitteeForChain(c echo.Context) erro if err != nil { return httperrors.BadRequest(err.Error()) } - chain := s.chains().Get(chainID) + 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)) } diff --git a/packages/webapi/admapi/endpoints.go b/packages/webapi/admapi/endpoints.go index 29fd066b48..83df3e783b 100644 --- a/packages/webapi/admapi/endpoints.go +++ b/packages/webapi/admapi/endpoints.go @@ -11,6 +11,7 @@ import ( "github.com/iotaledger/wasp/packages/chains" "github.com/iotaledger/wasp/packages/dkg" metricspkg "github.com/iotaledger/wasp/packages/metrics" + "github.com/iotaledger/wasp/packages/parameters" "github.com/iotaledger/wasp/packages/peering" "github.com/iotaledger/wasp/packages/registry" "github.com/labstack/echo/v4" @@ -36,10 +37,17 @@ func AddEndpoints( ) { initLogger() - adm.EchoGroup().Use(protected(adminWhitelist)) + isWhitelistEnabled := !parameters.GetBool(parameters.WebAPIAdminWhitelistDisabled) + + echoGroup := adm.EchoGroup() + + if isWhitelistEnabled { + echoGroup.Use(protected(adminWhitelist)) + } addShutdownEndpoint(adm, shutdown) addChainRecordEndpoints(adm, registryProvider) + addChainStatsEndpoints(adm, chainsProvider) addCommitteeRecordEndpoints(adm, registryProvider, chainsProvider) addChainEndpoints(adm, registryProvider, chainsProvider, metrics) addDKSharesEndpoints(adm, registryProvider, nodeProvider) diff --git a/packages/webapi/model/node_connection_metrics.go b/packages/webapi/model/node_connection_metrics.go new file mode 100644 index 0000000000..e4a9044711 --- /dev/null +++ b/packages/webapi/model/node_connection_metrics.go @@ -0,0 +1,66 @@ +package model + +import ( + "fmt" + "time" + + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" +) + +type NodeConnectionMessageMetrics struct { + Total uint32 `swagger:"desc(Total number of messages sent/received)"` + LastEvent time.Time `swagger:"desc(Last time the message was sent/received)"` + LastMessage string `swagger:"desc(The print out of the last message)"` +} + +type NodeConnectionMessagesMetrics struct { + OutPullState *NodeConnectionMessageMetrics `swagger:"desc(Stats of sent out PullState messages)"` + OutPullTransactionInclusionState *NodeConnectionMessageMetrics `swagger:"desc(Stats of sent out PullTransactionInclusionState messages)"` + OutPullConfirmedOutput *NodeConnectionMessageMetrics `swagger:"desc(Stats of sent out PullConfirmedOutput messages)"` + OutPostTransaction *NodeConnectionMessageMetrics `swagger:"desc(Stats of sent out PostTransaction messages)"` + + InTransaction *NodeConnectionMessageMetrics `swagger:"desc(Stats of received Transaction messages)"` + InInclusionState *NodeConnectionMessageMetrics `swagger:"desc(Stats of received InclusionState messages)"` + InOutput *NodeConnectionMessageMetrics `swagger:"desc(Stats of received Output messages)"` + InUnspentAliasOutput *NodeConnectionMessageMetrics `swagger:"desc(Stats of received UnspentAliasOutput messages)"` +} + +type NodeConnectionMetrics struct { + NodeConnectionMessagesMetrics + Subscribed []Address +} + +func NewNodeConnectionMetrics(metrics nodeconnmetrics.NodeConnectionMetrics) *NodeConnectionMetrics { + ncmm := NewNodeConnectionMessagesMetrics(metrics) + subscribed := metrics.GetSubscribed() + s := make([]Address, len(subscribed)) + for i := range s { + s[i] = NewAddress(subscribed[i]) + } + return &NodeConnectionMetrics{ + NodeConnectionMessagesMetrics: *ncmm, + Subscribed: s, + } +} + +func NewNodeConnectionMessagesMetrics(metrics nodeconnmetrics.NodeConnectionMessagesMetrics) *NodeConnectionMessagesMetrics { + return &NodeConnectionMessagesMetrics{ + OutPullState: NewNodeConnectionMessageMetrics(metrics.GetOutPullState()), + OutPullTransactionInclusionState: NewNodeConnectionMessageMetrics(metrics.GetOutPullTransactionInclusionState()), + OutPullConfirmedOutput: NewNodeConnectionMessageMetrics(metrics.GetOutPullConfirmedOutput()), + OutPostTransaction: NewNodeConnectionMessageMetrics(metrics.GetOutPostTransaction()), + + InTransaction: NewNodeConnectionMessageMetrics(metrics.GetInTransaction()), + InInclusionState: NewNodeConnectionMessageMetrics(metrics.GetInInclusionState()), + InOutput: NewNodeConnectionMessageMetrics(metrics.GetInOutput()), + InUnspentAliasOutput: NewNodeConnectionMessageMetrics(metrics.GetInUnspentAliasOutput()), + } +} + +func NewNodeConnectionMessageMetrics(metrics nodeconnmetrics.NodeConnectionMessageMetrics) *NodeConnectionMessageMetrics { + return &NodeConnectionMessageMetrics{ + Total: metrics.GetMessageTotal(), + LastEvent: metrics.GetLastEvent(), + LastMessage: fmt.Sprintf("%v", metrics.GetLastMessage()), + } +} diff --git a/packages/webapi/reqstatus/reqstatus.go b/packages/webapi/reqstatus/reqstatus.go index 0515662b3f..ffcfeb86e4 100644 --- a/packages/webapi/reqstatus/reqstatus.go +++ b/packages/webapi/reqstatus/reqstatus.go @@ -5,7 +5,6 @@ import ( "net/http" "time" - "github.com/iotaledger/hive.go/events" "github.com/iotaledger/wasp/packages/chain" "github.com/iotaledger/wasp/packages/chains" "github.com/iotaledger/wasp/packages/iscp" @@ -77,13 +76,12 @@ func (r *reqstatusWebAPI) handleWaitRequestProcessed(c echo.Context) error { // subscribe to event requestProcessed := make(chan bool) - handler := events.NewClosure(func(rid iscp.RequestID) { + attachID := ch.AttachToRequestProcessed(func(rid iscp.RequestID) { if rid == reqID { requestProcessed <- true } }) - ch.EventRequestProcessed().Attach(handler) - defer ch.EventRequestProcessed().Detach(handler) + defer ch.DetachFromRequestProcessed(attachID) select { case <-requestProcessed: diff --git a/packages/webapi/reqstatus/reqstatus_test.go b/packages/webapi/reqstatus/reqstatus_test.go index a935191289..30d7e919d2 100644 --- a/packages/webapi/reqstatus/reqstatus_test.go +++ b/packages/webapi/reqstatus/reqstatus_test.go @@ -16,11 +16,17 @@ import ( type mockChain struct{} +var _ chain.ChainRequests = &mockChain{} + func (m *mockChain) GetRequestProcessingStatus(id iscp.RequestID) chain.RequestProcessingStatus { return chain.RequestProcessingStatusCompleted } -func (m *mockChain) EventRequestProcessed() *events.Event { +func (m *mockChain) AttachToRequestProcessed(func(iscp.RequestID)) (attachID *events.Closure) { + panic("not implemented") +} + +func (m *mockChain) DetachFromRequestProcessed(attachID *events.Closure) { panic("not implemented") } diff --git a/packages/webapi/request/request.go b/packages/webapi/request/request.go index fb9bd3d377..385fbb039a 100644 --- a/packages/webapi/request/request.go +++ b/packages/webapi/request/request.go @@ -10,6 +10,7 @@ import ( "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/marshalutil" "github.com/iotaledger/wasp/packages/chain" + "github.com/iotaledger/wasp/packages/chain/messages" "github.com/iotaledger/wasp/packages/chains" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/iscp/colored" @@ -67,23 +68,30 @@ func (o *offLedgerReqAPI) handleNewRequest(c echo.Context) error { return err } + reqID := offLedgerReq.ID() + + if o.requestsCache.Get(reqID) != nil { + return httperrors.BadRequest("request already processed") + } + // check req signature if !offLedgerReq.VerifySignature() { + o.requestsCache.Set(reqID, true) return httperrors.BadRequest("Invalid signature.") } + // check req is for the correct chain + if !offLedgerReq.ChainID().Equals(chainID) { + // do not add to cache, it can still be sent to the correct chain + return httperrors.BadRequest("Request is for a different chain") + } + // check chain exists ch := o.getChain(chainID) if ch == nil { return httperrors.NotFound(fmt.Sprintf("Unknown chain: %s", chainID.Base58())) } - reqID := offLedgerReq.ID() - - if o.requestsCache.Get(reqID) != nil { - return httperrors.BadRequest("request already processed") - } - alreadyProcessed, err := o.hasRequestBeenProcessed(ch, reqID) if err != nil { o.log.Errorf("webapi.offledger - check if already processed: %w", err) @@ -91,6 +99,7 @@ func (o *offLedgerReqAPI) handleNewRequest(c echo.Context) error { } if alreadyProcessed { + o.requestsCache.Set(reqID, true) return httperrors.BadRequest("request already processed") } @@ -106,7 +115,13 @@ func (o *offLedgerReqAPI) handleNewRequest(c echo.Context) error { if len(balances) == 0 { return httperrors.BadRequest(fmt.Sprintf("No balance on account %s", offLedgerReq.SenderAccount().Base58())) } - ch.ReceiveOffLedgerRequest(offLedgerReq, "") + ch.EnqueueOffLedgerRequestMsg(&messages.OffLedgerRequestMsgIn{ + OffLedgerRequestMsg: messages.OffLedgerRequestMsg{ + ChainID: ch.ID(), + Req: offLedgerReq, + }, + SenderNetID: "", + }) return c.NoContent(http.StatusAccepted) } diff --git a/packages/webapi/request/request_test.go b/packages/webapi/request/request_test.go index 1924ea0e91..028c8295e6 100644 --- a/packages/webapi/request/request_test.go +++ b/packages/webapi/request/request_test.go @@ -8,14 +8,13 @@ import ( "github.com/iotaledger/goshimmer/packages/ledgerstate" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/wasp/packages/chain" + "github.com/iotaledger/wasp/packages/chain/messages" "github.com/iotaledger/wasp/packages/chains" "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/dict" + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" + util "github.com/iotaledger/wasp/packages/testutil" "github.com/iotaledger/wasp/packages/testutil/testchain" - "github.com/iotaledger/wasp/packages/testutil/testkey" "github.com/iotaledger/wasp/packages/testutil/testlogger" "github.com/iotaledger/wasp/packages/util/expiringcache" "github.com/iotaledger/wasp/packages/webapi/model" @@ -27,19 +26,31 @@ type mockedChain struct { *testchain.MockedChainCore } +var ( + _ chain.Chain = &mockedChain{} + _ chain.ChainCore = &mockedChain{} // from testchain.MockedChainCore + _ chain.ChainEntry = &mockedChain{} + _ chain.ChainRequests = &mockedChain{} + _ chain.ChainMetrics = &mockedChain{} +) + +// chain.ChainRequests implementation + func (m *mockedChain) GetRequestProcessingStatus(_ iscp.RequestID) chain.RequestProcessingStatus { panic("implement me") } -func (m *mockedChain) EventRequestProcessed() *events.Event { +func (m *mockedChain) AttachToRequestProcessed(func(iscp.RequestID)) (attachID *events.Closure) { panic("implement me") } -func (m *mockedChain) ReceiveTransaction(_ *ledgerstate.Transaction) { +func (m *mockedChain) DetachFromRequestProcessed(attachID *events.Closure) { panic("implement me") } -func (m *mockedChain) ReceiveInclusionState(_ ledgerstate.TransactionID, _ ledgerstate.InclusionState) { +// chain.ChainEntry implementation + +func (m *mockedChain) ReceiveTransaction(_ *ledgerstate.Transaction) { panic("implement me") } @@ -47,23 +58,29 @@ func (m *mockedChain) ReceiveState(_ *ledgerstate.AliasOutput, _ time.Time) { panic("implement me") } -func (m *mockedChain) ReceiveOutput(_ ledgerstate.Output) { +func (m *mockedChain) Dismiss(_ string) { panic("implement me") } -func (m *mockedChain) Dismiss(_ string) { +func (m *mockedChain) IsDismissed() bool { panic("implement me") } -func (m *mockedChain) IsDismissed() bool { +// chain.ChainMetrics implementation + +func (m *mockedChain) GetNodeConnectionMetrics() nodeconnmetrics.NodeConnectionMessagesMetrics { panic("implement me") } +// private methods + func createMockedGetChain(t *testing.T) chains.ChainProvider { return func(chainID *iscp.ChainID) chain.Chain { - return &mockedChain{ - testchain.NewMockedChainCore(t, chainID, testlogger.NewLogger(t)), - } + chainCore := testchain.NewMockedChainCore(t, chainID, testlogger.NewLogger(t)) + chainCore.OnOffLedgerRequest(func(msg *messages.OffLedgerRequestMsgIn) { + t.Logf("Offledger request %v received", msg) + }) + return &mockedChain{chainCore} } } @@ -77,72 +94,55 @@ func hasRequestBeenProcessedMocked(ret bool) hasRequestBeenProcessedFn { } } -func dummyOffledgerRequest() *request.OffLedger { - contract := iscp.Hn("somecontract") - entrypoint := iscp.Hn("someentrypoint") - args := requestargs.New(dict.Dict{}) - req := request.NewOffLedger(contract, entrypoint, args) - keys, _ := testkey.GenKeyAddr() - req.Sign(keys) - return req -} - -func TestNewRequestBase64(t *testing.T) { - instance := &offLedgerReqAPI{ +func newMockedAPI(t *testing.T) *offLedgerReqAPI { + return &offLedgerReqAPI{ getChain: createMockedGetChain(t), getAccountBalance: getAccountBalanceMocked, hasRequestBeenProcessed: hasRequestBeenProcessedMocked(false), requestsCache: expiringcache.New(10 * time.Second), } +} +func testRequest(t *testing.T, instance *offLedgerReqAPI, chainID *iscp.ChainID, body interface{}, expectedStatus int) { testutil.CallWebAPIRequestHandler( t, instance.handleNewRequest, http.MethodPost, routes.NewRequest(":chainID"), - map[string]string{"chainID": iscp.RandomChainID().Base58()}, - model.OffLedgerRequestBody{Request: model.NewBytes(dummyOffledgerRequest().Bytes())}, + map[string]string{"chainID": chainID.Base58()}, + body, nil, - http.StatusAccepted, + expectedStatus, ) } -func TestNewRequestBinary(t *testing.T) { - instance := &offLedgerReqAPI{ - getChain: createMockedGetChain(t), - getAccountBalance: getAccountBalanceMocked, - hasRequestBeenProcessed: hasRequestBeenProcessedMocked(false), - requestsCache: expiringcache.New(10 * time.Second), - } +// Tests - testutil.CallWebAPIRequestHandler( - t, - instance.handleNewRequest, - http.MethodPost, - routes.NewRequest(":chainID"), - map[string]string{"chainID": iscp.RandomChainID().Base58()}, - dummyOffledgerRequest().Bytes(), - nil, - http.StatusAccepted, - ) +func TestNewRequestBase64(t *testing.T) { + instance := newMockedAPI(t) + chainID := iscp.RandomChainID() + body := model.OffLedgerRequestBody{Request: model.NewBytes(util.DummyOffledgerRequest(chainID).Bytes())} + testRequest(t, instance, chainID, body, http.StatusAccepted) +} + +func TestNewRequestBinary(t *testing.T) { + instance := newMockedAPI(t) + chainID := iscp.RandomChainID() + body := util.DummyOffledgerRequest(chainID).Bytes() + testRequest(t, instance, chainID, body, http.StatusAccepted) } func TestRequestAlreadyProcessed(t *testing.T) { - instance := &offLedgerReqAPI{ - getChain: createMockedGetChain(t), - getAccountBalance: getAccountBalanceMocked, - hasRequestBeenProcessed: hasRequestBeenProcessedMocked(true), - requestsCache: expiringcache.New(10 * time.Second), - } + instance := newMockedAPI(t) + instance.hasRequestBeenProcessed = hasRequestBeenProcessedMocked(true) - testutil.CallWebAPIRequestHandler( - t, - instance.handleNewRequest, - http.MethodPost, - routes.NewRequest(":chainID"), - map[string]string{"chainID": iscp.RandomChainID().Base58()}, - dummyOffledgerRequest().Bytes(), - nil, - http.StatusBadRequest, - ) + chainID := iscp.RandomChainID() + body := util.DummyOffledgerRequest(chainID).Bytes() + testRequest(t, instance, chainID, body, http.StatusBadRequest) +} + +func TestWrongChainID(t *testing.T) { + instance := newMockedAPI(t) + body := util.DummyOffledgerRequest(iscp.RandomChainID()).Bytes() + testRequest(t, instance, iscp.RandomChainID(), body, http.StatusBadRequest) } diff --git a/packages/webapi/routes/routes.go b/packages/webapi/routes/routes.go index 630e052cbd..1cbcc0e815 100644 --- a/packages/webapi/routes/routes.go +++ b/packages/webapi/routes/routes.go @@ -55,6 +55,14 @@ func GetCommitteeRecord(addr string) string { return "/adm/committeerecord/" + addr } +func GetChainsNodeConnectionMetrics() string { + return "/adm/chain/nodeconn/metrics" +} + +func GetChainNodeConnectionMetrics(chainID string) string { + return "/adm/chain/" + chainID + "/nodeconn/metrics" +} + func GetCommitteeForChain(chainID string) string { return "/adm/chain/" + chainID + "/committeerecord" } diff --git a/packages/webapi/state/callview.go b/packages/webapi/state/callview.go index a5c67d9669..2e206c9fb5 100644 --- a/packages/webapi/state/callview.go +++ b/packages/webapi/state/callview.go @@ -31,6 +31,14 @@ func AddEndpoints(server echoswagger.ApiRouter, allChains chains.Provider) { s := &callViewService{allChains} + server.POST(routes.CallView(":chainID", ":contractHname", ":fname"), s.handleCallView). + SetSummary("Call a view function on a contract"). + AddParamPath("", "chainID", "ChainID (base58-encoded)"). + AddParamPath("", "contractHname", "Contract Hname"). + AddParamPath("getInfo", "fname", "Function name"). + AddParamBody(dictExample, "params", "Parameters", false). + AddResponse(http.StatusOK, "Result", dictExample, nil) + server.GET(routes.CallView(":chainID", ":contractHname", ":fname"), s.handleCallView). SetSummary("Call a view function on a contract"). AddParamPath("", "chainID", "ChainID (base58-encoded)"). diff --git a/plugins/banner/plugin.go b/plugins/banner/plugin.go index 7a29e572ef..5c9aa22038 100644 --- a/plugins/banner/plugin.go +++ b/plugins/banner/plugin.go @@ -24,8 +24,8 @@ func configure(ctx *node.Plugin) { \/ \/ \__,_|___/ |__/ | | |_| - %s -`, wasp.Version) + %s (commit: %s) +`, wasp.Version, wasp.VersionHash) fmt.Println() // TODO embed build time see https://stackoverflow.com/questions/53031035/generate-build-timestamp-in-go/53045029 diff --git a/plugins/chains/plugin.go b/plugins/chains/plugin.go index b3ec790996..252423ff76 100644 --- a/plugins/chains/plugin.go +++ b/plugins/chains/plugin.go @@ -7,6 +7,7 @@ import ( "github.com/iotaledger/hive.go/logger" "github.com/iotaledger/hive.go/node" _ "github.com/iotaledger/wasp/packages/chain/chainimpl" + "github.com/iotaledger/wasp/packages/chain/nodeconnimpl" "github.com/iotaledger/wasp/packages/chains" metricspkg "github.com/iotaledger/wasp/packages/metrics" "github.com/iotaledger/wasp/packages/parameters" @@ -47,10 +48,10 @@ func run(_ *node.Plugin) { database.GetOrCreateKVStore, ) err := daemon.BackgroundWorker(PluginName, func(shutdownSignal <-chan struct{}) { - allChains.Attach(nodeconn.NodeConnection()) if parameters.GetBool(parameters.MetricsEnabled) { allMetrics = metrics.AllMetrics() } + allChains.SetNodeConn(nodeconnimpl.NewNodeConnection(nodeconn.NodeConnection(), allMetrics.GetNodeConnectionMetrics(), log)) if err := allChains.ActivateAllFromRegistry(registry.DefaultRegistry, allMetrics); err != nil { log.Errorf("failed to read chain activation records from registry: %v", err) return diff --git a/plugins/dashboard/plugin.go b/plugins/dashboard/plugin.go index a4bc09c3f4..ce99ef1522 100644 --- a/plugins/dashboard/plugin.go +++ b/plugins/dashboard/plugin.go @@ -18,6 +18,7 @@ import ( "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/kv/dict" "github.com/iotaledger/wasp/packages/kv/optimism" + "github.com/iotaledger/wasp/packages/metrics/nodeconnmetrics" "github.com/iotaledger/wasp/packages/parameters" registry_pkg "github.com/iotaledger/wasp/packages/registry" "github.com/iotaledger/wasp/packages/util/auth" @@ -109,6 +110,19 @@ func (w *waspServices) GetChainCommitteeInfo(chainID *iscp.ChainID) (*chain.Comm return ch.GetCommitteeInfo(), nil } +func (w *waspServices) GetChainNodeConnectionMetrics(chainID *iscp.ChainID) (nodeconnmetrics.NodeConnectionMessagesMetrics, error) { + ch := chains.AllChains().Get(chainID) + if ch == nil { + return nil, echo.NewHTTPError(http.StatusNotFound, "Chain not found") + } + return ch.GetNodeConnectionMetrics(), nil +} + +func (w *waspServices) GetNodeConnectionMetrics() (nodeconnmetrics.NodeConnectionMetrics, error) { + chs := chains.AllChains() + return chs.GetNodeConnectionMetrics(), 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/metrics/plugin.go b/plugins/metrics/plugin.go index e27d5f443b..21f681684e 100644 --- a/plugins/metrics/plugin.go +++ b/plugins/metrics/plugin.go @@ -16,7 +16,7 @@ var ( ) func Init() *node.Plugin { - return node.NewPlugin(PluginName, node.Disabled, configure, run) + return node.NewPlugin(PluginName, node.Enabled, configure, run) } func configure(_ *node.Plugin) { diff --git a/tools/cluster/tests/missing_requests_test.go b/tools/cluster/tests/missing_requests_test.go index d774fcd6d5..ab2375d160 100644 --- a/tools/cluster/tests/missing_requests_test.go +++ b/tools/cluster/tests/missing_requests_test.go @@ -47,7 +47,7 @@ func TestMissingRequests(t *testing.T) { require.NoError(t, err) // send off-ledger request to all nodes except #3 - req := request.NewOffLedger(incCounterSCHname, inccounter.FuncIncCounter.Hname(), requestargs.RequestArgs{}) //.WithTransfer(par.Tokens) + req := request.NewOffLedger(chainID, incCounterSCHname, inccounter.FuncIncCounter.Hname(), requestargs.RequestArgs{}) //.WithTransfer(par.Tokens) req.Sign(userWallet) err = clu.WaspClient(0).PostOffLedgerRequest(chainID, req) @@ -63,7 +63,7 @@ func TestMissingRequests(t *testing.T) { //------ // send a dummy request to node #3, so that it proposes a batch and the consensus hang is broken - req2 := request.NewOffLedger(iscp.Hn("foo"), iscp.Hn("bar"), nil) + req2 := request.NewOffLedger(chainID, iscp.Hn("foo"), iscp.Hn("bar"), nil) req2.Sign(userWallet) err = clu.WaspClient(3).PostOffLedgerRequest(chainID, req2) require.NoError(t, err) diff --git a/tools/cluster/tests/wasm/inccounter_bg.wasm b/tools/cluster/tests/wasm/inccounter_bg.wasm index bb828e396a..c577e6e18f 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/cluster/tests/wasp-cli_test.go b/tools/cluster/tests/wasp-cli_test.go index 2d368ea6b7..612c7662eb 100644 --- a/tools/cluster/tests/wasp-cli_test.go +++ b/tools/cluster/tests/wasp-cli_test.go @@ -1,6 +1,7 @@ package tests import ( + "encoding/hex" "fmt" "regexp" "strconv" @@ -178,19 +179,22 @@ func TestWaspCLIBlockLog(t *testing.T) { require.Equal(t, "Block index: 2", out[0]) out = w.Run("chain", "request", reqID) - t.Logf("%+v", out) + found = false for _, line := range out { - if strings.Contains(line, "Error:") { - t.Fail() + if strings.Contains(line, "Error: (empty)") { + found = true + break } } + require.True(t, found) // try an unsuccessful request (missing params) - out = w.Run("chain", "post-request", "root", "deployContract") + out = w.Run("chain", "post-request", "root", "deployContract", "string", "foo", "string", "bar") reqID = findRequestIDInOutput(out) require.NotEmpty(t, reqID) out = w.Run("chain", "request", reqID) + found = false for _, line := range out { if strings.Contains(line, "Error: ") { @@ -200,6 +204,16 @@ func TestWaspCLIBlockLog(t *testing.T) { } } require.True(t, found) + + found = false + for _, line := range out { + if strings.Contains(line, "foo") { + found = true + require.Contains(t, line, hex.EncodeToString([]byte("bar"))) + break + } + } + require.True(t, found) } func TestWaspCLIBlobContract(t *testing.T) { @@ -295,3 +309,48 @@ func TestWaspCLIBalance(t *testing.T) { require.EqualValues(t, utxodb.RequestFundsAmount-1000, bals["IOTA"]) require.EqualValues(t, 1000, bals[mintedColor]) } + +func TestWaspCLIRejoinChain(t *testing.T) { + w := newWaspCLITest(t) + + w.Run("init") + w.Run("request-funds") + + alias := "chain1" + + committee, quorum := w.CommitteeConfig() + + // test chain deploy command + w.Run("chain", "deploy", "--chain="+alias, committee, quorum) + + // test chain info command + out := w.Run("chain", "info") + chainID := regexp.MustCompile(`(?m)Chain ID:\s+([[:alnum:]]+)$`).FindStringSubmatch(out[0])[1] + require.NotEmpty(t, chainID) + t.Logf("Chain ID: %s", chainID) + + // test chain list command + out = w.Run("chain", "list") + require.Contains(t, out[0], "Total 1 chain(s)") + require.Contains(t, out[4], chainID) + + // deactivate chain and check that the chain was deactivated + w.Run("chain", "deactivate") + out = w.Run("chain", "list") + require.Contains(t, out[0], "Total 1 chain(s)") + require.Contains(t, out[4], chainID) + + chOut := strings.Fields(out[4]) + active, _ := strconv.ParseBool(chOut[1]) + require.False(t, active) + + // activate chain and check that it was activated + w.Run("chain", "activate") + out = w.Run("chain", "list") + require.Contains(t, out[0], "Total 1 chain(s)") + require.Contains(t, out[4], chainID) + + chOut = strings.Fields(out[4]) + active, _ = strconv.ParseBool(chOut[1]) + require.True(t, active) +} diff --git a/tools/devnet/docker-compose.yml b/tools/devnet/docker-compose.yml new file mode 100644 index 0000000000..c2b370017e --- /dev/null +++ b/tools/devnet/docker-compose.yml @@ -0,0 +1,65 @@ +version: "3.4" + +services: + devnet_wasp: + build: + context: ../../ + dockerfile: Dockerfile + container_name: devnet_wasp + networks: + - wasp-devnet + volumes: + - wasp-db:/wasp/waspdb + - ./wasp.config.json:/etc/wasp_config.json + expose: + - "4000/udp" # Peering + - "5550/tcp" # Nano MSG + - "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 + devnet_goshimmer: + restart: always + container_name: devnet_goshimmer + #https://github.com/lmoe/goshimmer + image: lukasmoe/goshimmer:wasp-testnet-additions + stop_grace_period: 1m + networks: + - wasp-devnet + command: > + --config=/tmp/config.json + --database.directory=/tmp/devnetdb + --mana.snapshotResetTime=true + --node.seed=base58:3YX6e7AL28hHihZewKdq6CMkEYVsTJBLgRiprUNiNq5E + --messageLayer.snapshot.file=/tmp/snapshot.bin + --messageLayer.snapshot.genesisNode= + --messageLayer.startSynced=true + volumes: + - goshimmer-db:/tmp/devnetdb + - ./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 + expose: + - "1888/tcp" # Analysis Server (within Docker network) + - "5000/tcp" # TXStream + - "8080/tcp" # GoShimmer API + - "8081/tcp" # GoShimmer Dashboard + - "9000/tcp" # Analysis Dashboard + - "9312/tcp" # Prometheus + +volumes: + goshimmer-db: + name: goshimmer-db + wasp-db: + name: wasp-db + +networks: + wasp-devnet: {} diff --git a/tools/devnet/goshimmer.config.json b/tools/devnet/goshimmer.config.json new file mode 100644 index 0000000000..8126e4196e --- /dev/null +++ b/tools/devnet/goshimmer.config.json @@ -0,0 +1,87 @@ +{ + "analysis": { + "client": { + "serverAddress": "devnet_goshimmer:1888" + }, + "server": { + "bindAddress": "0.0.0.0:1888" + }, + "dashboard": { + "bindAddress": "0.0.0.0:9000", + "dev": false + } + }, + "prometheus": { + "bindAddress": "0.0.0.0:9312", + "processMetrics": true + }, + "manualpeering": { + "knownPeers": [] + }, + "autopeering": { + "enabled": false, + "enableGossipIntegration": false, + "port": 14626 + }, + "dashboard": { + "bindAddress": "0.0.0.0:8081", + "dev": false, + "basic_auth": { + "enabled": false, + "username": "goshimmer", + "password": "goshimmer" + } + }, + "database": { + "directory": "/tmp/devnetdb" + }, + "logger": { + "level": "info", + "disableCaller": false, + "disableStacktrace": false, + "encoding": "console", + "outputPaths": [ + "stdout" + ], + "disableEvents": true + }, + "metrics":{ + "manaUpdateInterval": 5, + "local": false, + "global": true + }, + "network": { + "bindAddress": "0.0.0.0", + "externalAddress": "auto" + }, + "messageLayer" : { + "startSynced": true, + "snapshot": { + "genesisNode": "", + "file": "/tmp/snapshot.bin" + } + }, + "node": { + "disablePlugins": ["portcheck"], + "enablePlugins": ["analysis-server","snapshot","analysis-dashboard","prometheus","txstream","webapi tools endpoint","faucet","activity","spammer"] + }, + "pow": { + "difficulty": 2, + "numThreads": 1, + "timeout": "10s", + "parentsRefreshInterval": "300ms" + }, + "webapi": { + "basic_auth": { + "enabled": false, + "username": "goshimmer", + "password": "goshimmer" + }, + "bindAddress": "0.0.0.0:8080" + }, + "faucet": { + "powDifficulty": 12, + "seed": "7R1itJx5hVuo9w9hjg5cwKFmek4HMSoBDgJZN8hKGxih" + } + } + \ No newline at end of file diff --git a/tools/devnet/snapshot.bin b/tools/devnet/snapshot.bin new file mode 100644 index 0000000000..b0e1caa152 Binary files /dev/null and b/tools/devnet/snapshot.bin differ diff --git a/tools/devnet/wasp.config.json b/tools/devnet/wasp.config.json new file mode 100644 index 0000000000..5e390495b3 --- /dev/null +++ b/tools/devnet/wasp.config.json @@ -0,0 +1,46 @@ +{ + "database": { + "directory": "/wasp/waspdb" + }, + "logger": { + "level": "debug", + "disableCaller": false, + "disableStacktrace": true, + "encoding": "console", + "outputPaths": [ + "stdout", + "wasp.log" + ], + "disableEvents": true + }, + "network": { + "bindAddress": "0.0.0.0", + "externalAddress": "auto" + }, + "node": { + "disablePlugins": [], + "enablePlugins": [] + }, + "webapi": { + "bindAddress": "0.0.0.0:9090", + "adminWhitelistDisabled": true + }, + "dashboard": { + "auth": { + "scheme": "basic", + "username": "wasp", + "password": "wasp" + }, + "bindAddress": "0.0.0.0:7000" + }, + "peering":{ + "port": 4000, + "netid": "127.0.0.1:4000" + }, + "nodeconn": { + "address": "devnet_goshimmer:5000" + }, + "nanomsg":{ + "port": 5550 + } +} diff --git a/tools/evm/evmcli/deploy.go b/tools/evm/evmcli/deploy.go index 6ddeb9351b..eaeb1850e6 100644 --- a/tools/evm/evmcli/deploy.go +++ b/tools/evm/evmcli/deploy.go @@ -20,13 +20,16 @@ import ( ) type DeployParams struct { - evmFlavor string - ChainID int - name string - description string - alloc []string - allocBase64 string - GasPerIOTA uint64 + evmFlavor string + ChainID int + name string + description string + alloc []string + allocBase64 string + GasPerIOTA uint64 + GasLimit uint64 + blockTime uint32 + blockKeepAmount int32 } func (d *DeployParams) InitFlags(cmd *cobra.Command) { @@ -37,6 +40,9 @@ func (d *DeployParams) InitFlags(cmd *cobra.Command) { cmd.Flags().StringSliceVarP(&d.alloc, "alloc", "", nil, "Genesis allocation (format:
:,
:,...)") cmd.Flags().StringVarP(&d.allocBase64, "alloc-bytes", "", "", "Genesis allocation (base64-encoded)") cmd.Flags().Uint64VarP(&d.GasPerIOTA, "gas-per-iota", "", evm.DefaultGasPerIota, "Gas per IOTA charged as fee") + cmd.Flags().Uint32VarP(&d.blockTime, "block-time", "", 0, "Average block time (0: disabled) [evmlight only]") + cmd.Flags().Uint64VarP(&d.GasLimit, "gas-limit", "", evm.GasLimitDefault, "Block gas limit") + cmd.Flags().Int32VarP(&d.blockKeepAmount, "block-keep-amount", "", evm.BlockKeepAmountDefault, "Amount of blocks to keep in DB (-1: keep all blocks) [evmlight only]") } func (d *DeployParams) Name() string { @@ -61,6 +67,20 @@ func (d *DeployParams) EVMFlavor() *coreutil.ContractInfo { return r } +func (d *DeployParams) BlockTime() uint32 { + if d.blockTime > 0 && d.evmFlavor != "evmlight" { + log.Fatalf("block time is only supported by evmlight flavor") + } + return d.blockTime +} + +func (d *DeployParams) BlockKeepAmount() int32 { + if d.blockKeepAmount > 0 && d.evmFlavor != "evmlight" { + log.Fatalf("block-keep-amount is only supported by evmlight flavor") + } + return d.blockKeepAmount +} + func (d *DeployParams) GetGenesis(def core.GenesisAlloc) core.GenesisAlloc { if len(d.alloc) != 0 && d.allocBase64 != "" { log.Fatalf("--alloc and --alloc-bytes are mutually exclusive") diff --git a/tools/evm/evmemulator/main.go b/tools/evm/evmemulator/main.go index 378acf6204..f5755b851c 100644 --- a/tools/evm/evmemulator/main.go +++ b/tools/evm/evmemulator/main.go @@ -6,10 +6,12 @@ package main import ( "encoding/hex" "fmt" + "time" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/crypto" "github.com/iotaledger/wasp/contracts/native/evm" + "github.com/iotaledger/wasp/packages/evm/evmflavors" "github.com/iotaledger/wasp/packages/evm/evmtest" "github.com/iotaledger/wasp/packages/evm/evmtypes" "github.com/iotaledger/wasp/packages/evm/jsonrpc" @@ -66,19 +68,43 @@ By default the server has no unlocked accounts. To send transactions, either: } func start(cmd *cobra.Command, args []string) { - env := solo.New(nil, log.DebugFlag, log.DebugFlag) + blockTime := deployParams.BlockTime() + blockKeepAmount := deployParams.BlockKeepAmount() + evmFlavor := deployParams.EVMFlavor() + + env := solo.New(solo.NewTestContext("evmemulator"), log.DebugFlag, log.DebugFlag). + WithNativeContract(evmflavors.Processors[evmFlavor.Name]) chainOwner, _ := env.NewKeyPairWithFunds() chain := env.NewChain(chainOwner, "iscpchain") - err := chain.DeployContract(chainOwner, deployParams.Name(), deployParams.EVMFlavor().ProgramHash, + err := chain.DeployContract(chainOwner, deployParams.Name(), evmFlavor.ProgramHash, evm.FieldChainID, codec.EncodeUint16(uint16(deployParams.ChainID)), evm.FieldGenesisAlloc, evmtypes.EncodeGenesisAlloc(deployParams.GetGenesis(core.GenesisAlloc{ evmtest.FaucetAddress: {Balance: evmtest.FaucetSupply}, })), evm.FieldGasPerIota, deployParams.GasPerIOTA, + evm.FieldGasLimit, deployParams.GasLimit, + evm.FieldBlockKeepAmount, blockKeepAmount, ) log.Check(err) + if blockTime > 0 { + _, err := chain.PostRequestSync( + solo.NewCallParams(deployParams.Name(), evm.FuncSetBlockTime.Name, + evm.FieldBlockTime, blockTime, + ).WithIotas(1), + chain.OriginatorKeyPair, + ) + log.Check(err) + go func() { + const step = 1 * time.Second + for { + time.Sleep(step) + env.AdvanceClockBy(step) + } + }() + } + signer, _ := env.NewKeyPairWithFunds() backend := jsonrpc.NewSoloBackend(env, chain, signer) diff --git a/tools/schema/generator/clienttemplates/alltemplates.go b/tools/schema/generator/clienttemplates/alltemplates.go new file mode 100644 index 0000000000..2fca82b07b --- /dev/null +++ b/tools/schema/generator/clienttemplates/alltemplates.go @@ -0,0 +1,87 @@ +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 new file mode 100644 index 0000000000..cee2726e7a --- /dev/null +++ b/tools/schema/generator/clienttemplates/app.go @@ -0,0 +1,22 @@ +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 new file mode 100644 index 0000000000..ca14b503d1 --- /dev/null +++ b/tools/schema/generator/clienttemplates/events.go @@ -0,0 +1,58 @@ +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 new file mode 100644 index 0000000000..f67dc8de6d --- /dev/null +++ b/tools/schema/generator/clienttemplates/service.go @@ -0,0 +1,82 @@ +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 new file mode 100644 index 0000000000..7f965c837c --- /dev/null +++ b/tools/schema/generator/emitter.go @@ -0,0 +1,461 @@ +package generator + +import ( + "fmt" + "regexp" + "strconv" + "strings" + + "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/tools/schema/model" +) + +const enableLog = false + +const ( + KeyArray = "array" + KeyBaseType = "basetype" + KeyCore = "core" + KeyEvent = "event" + KeyEvents = "events" + KeyExist = "exist" + KeyFunc = "func" + KeyInit = "init" + KeyMandatory = "mandatory" + KeyMap = "map" + KeyMut = "mut" + KeyParam = "param" + KeyParams = "params" + KeyProxy = "proxy" + KeyPtrs = "ptrs" + KeyResult = "result" + KeyResults = "results" + KeyState = "state" + KeyStruct = "struct" + KeyStructs = "structs" + KeyThis = "this" + KeyTypeDef = "typedef" + KeyTypeDefs = "typedefs" + KeyView = "view" +) + +var emitKeyRegExp = regexp.MustCompile(`\$[a-zA-Z_][a-zA-Z_0-9]*`) + +func (g *GenBase) indent() { + g.tab++ +} + +func (g *GenBase) undent() { + g.tab-- +} + +func (g *GenBase) log(text string) { + if !enableLog { + return + } + + for i := 0; i < g.tab; i++ { + fmt.Print(" ") + } + fmt.Println(text) +} + +// emit processes "$#emit template" +// It processes all lines in the named template +// If the template is non-existent nothing will happen +// Any line starting with a special "$#" directive will recursively be processed +// An unknown directive will result in an error +func (g *GenBase) emit(template string) { + g.log("$#emit " + template) + g.indent() + defer g.undent() + + lines := strings.Split(g.templates[template], "\n") + for i := 1; i < len(lines)-1; i++ { + // replace any placeholder keys + line := emitKeyRegExp.ReplaceAllStringFunc(lines[i], func(key string) string { + text, ok := g.keys[key[1:]] + if ok { + return text + } + return "???:" + key + }) + + // remove concatenation markers + line = strings.ReplaceAll(line, "$+", "") + + // line contains special directive? + space := strings.Index(line, " ") + if space <= 2 || line[:2] != "$#" { + // no special directive, just emit line + g.println(line) + continue + } + + // now process special directive + switch line[2:space] { + case "emit": + g.emit(strings.TrimSpace(line[7:])) + case "each": + g.emitEach(line) + case "func": + g.emitFunc(line) + case "if": + g.emitIf(line) + case "set": + g.emitSet(line) + default: + g.error(line) + } + } +} + +// emitEach processes "$#each array template" +// It processes the template for each item in the array +// Produces an error if the array key is unknown +func (g *GenBase) emitEach(line string) { + g.log(line) + g.indent() + defer g.undent() + + parts := strings.Split(line, " ") + if len(parts) != 3 { + g.error(line) + return + } + + template := parts[2] + switch parts[1] { + case KeyEvent: + g.emitEachField(g.currentEvent.Fields, template) + case KeyEvents: + g.emitEachEvent(g.s.Events, template) + case KeyFunc: + g.emitEachFunc(g.s.Funcs, template) + case KeyMandatory: + g.emitEachMandatoryField(template) + case KeyParam: + g.emitEachField(g.currentFunc.Params, template) + case KeyParams: + g.emitEachField(g.s.Params, template) + case KeyResult: + g.emitEachField(g.currentFunc.Results, template) + case KeyResults: + g.emitEachField(g.s.Results, template) + case KeyState: + g.emitEachField(g.s.StateVars, template) + case KeyStruct: + g.emitEachField(g.currentStruct.Fields, template) + case KeyStructs: + g.emitEachStruct(g.s.Structs, template) + case KeyTypeDef: + g.emitEachField(g.s.Typedefs, template) + default: + g.error(line) + } +} + +func (g *GenBase) emitEachEvent(events []*model.Struct, template string) { + for _, g.currentEvent = range events { + g.log("currentEvent: " + g.currentEvent.Name) + g.setMultiKeyValues("evtName", g.currentEvent.Name) + g.emit(template) + } +} + +func (g *GenBase) emitEachField(fields []*model.Field, template string) { + maxCamelLength := 0 + maxSnakeLength := 0 + for _, g.currentField = range fields { + camelLen := len(g.currentField.Name) + if maxCamelLength < camelLen { + maxCamelLength = camelLen + } + snakeLen := len(snake(g.currentField.Name)) + if maxSnakeLength < snakeLen { + maxSnakeLength = snakeLen + } + } + + for _, g.currentField = range fields { + g.log("currentField: " + g.currentField.Name) + g.setFieldKeys(true, maxCamelLength, maxSnakeLength) + g.emit(template) + } +} + +func (g *GenBase) emitEachFunc(funcs []*model.Func, template string) { + maxCamelLength := 0 + maxSnakeLength := 0 + for _, g.currentFunc = range funcs { + camelLen := len(g.currentFunc.Name) + if maxCamelLength < camelLen { + maxCamelLength = camelLen + } + snakeLen := len(snake(g.currentFunc.Name)) + if maxSnakeLength < snakeLen { + maxSnakeLength = snakeLen + } + } + + for _, g.currentFunc = range funcs { + g.log("currentFunc: " + g.currentFunc.Name) + g.setFuncKeys(true, maxCamelLength, maxSnakeLength) + g.emit(template) + } +} + +func (g *GenBase) emitEachMandatoryField(template string) { + mandatoryFields := make([]*model.Field, 0) + for _, g.currentField = range g.currentFunc.Params { + if !g.currentField.Optional { + mandatoryFields = append(mandatoryFields, g.currentField) + } + } + g.emitEachField(mandatoryFields, template) +} + +func (g *GenBase) emitEachStruct(structs []*model.Struct, template string) { + for _, g.currentStruct = range structs { + g.log("currentStruct: " + g.currentStruct.Name) + g.setMultiKeyValues("strName", g.currentStruct.Name) + g.emit(template) + } +} + +// emitFunc processes "$#func emitter" +// It can call back into go code to emit more complex stuff +// Produces an error if emitter is unknown +func (g *GenBase) emitFunc(line string) { + g.log(line) + g.indent() + defer g.undent() + + parts := strings.Split(line, " ") + if len(parts) != 2 { + g.error(line) + return + } + + emitter, ok := g.emitters[parts[1]] + if ok { + emitter(g) + return + } + g.error(line) +} + +// emitIf processes "$#if condition template [elseTemplate]" +// It processes template when the named condition is true +// It processes the optional elseTemplate when the named condition is false +// Produces an error if named condition is unknown +//nolint:funlen +func (g *GenBase) emitIf(line string) { + g.log(line) + g.indent() + defer g.undent() + + parts := strings.Split(line, " ") + if len(parts) < 3 || len(parts) > 4 { + g.error(line) + return + } + + condition := false + switch parts[1] { + case KeyArray: + condition = g.currentField.Array + case KeyBaseType: + condition = g.currentField.TypeID != 0 + case KeyCore: + condition = g.s.CoreContracts + case KeyEvent: + condition = len(g.currentEvent.Fields) != 0 + case KeyEvents: + condition = len(g.s.Events) != 0 + case KeyExist: + condition = g.newTypes[g.keys[KeyProxy]] + case KeyFunc: + condition = g.keys["kind"] == KeyFunc + case KeyInit: + condition = g.currentFunc.Name == KeyInit + case KeyMap: + condition = g.currentField.MapKey != "" + case KeyMut: + condition = g.keys[KeyMut] == "Mutable" + case KeyParam: + condition = len(g.currentFunc.Params) != 0 + case KeyParams: + condition = len(g.s.Params) != 0 + case KeyPtrs: + condition = len(g.currentFunc.Params) != 0 || len(g.currentFunc.Results) != 0 + case KeyResult: + condition = len(g.currentFunc.Results) != 0 + case KeyResults: + condition = len(g.s.Results) != 0 + case KeyState: + condition = len(g.s.StateVars) != 0 + case KeyStructs: + condition = len(g.s.Structs) != 0 + case KeyThis: + condition = g.currentField.Alias == KeyThis + case KeyTypeDef: + condition = g.fieldIsTypeDef() + case KeyTypeDefs: + condition = len(g.s.Typedefs) != 0 + case KeyView: + condition = g.keys["kind"] == KeyView + default: + key, ok := g.keys[parts[1]] + if !ok { + g.error(line) + return + } + condition = key != "" + } + + if condition { + g.emit(parts[2]) + return + } + + // else branch? + if len(parts) == 4 { + g.emit(parts[3]) + } +} + +// emitSet processes "$#set key value" +// It sets the specified key to value, which can be anything +// Just make sure there is a space after the key name +// The special key "exist" is used to add a newly generated type +// It can be used to prevent duplicate types from being generated +func (g *GenBase) emitSet(line string) { + g.log(line) + + parts := strings.Split(line, " ") + if len(parts) < 3 { + g.error(line) + return + } + + key := parts[1] + value := line[len(parts[0])+len(key)+2:] + g.keys[key] = value + + if key == KeyExist { + g.newTypes[value] = true + } +} + +func (g *GenBase) fieldIsTypeDef() bool { + for _, typeDef := range g.s.Typedefs { + if typeDef.Name == g.currentField.Type { + g.currentField = typeDef + g.setFieldKeys(false, 0, 0) + return true + } + } + return false +} + +func (g *GenBase) setCommonKeys() { + g.keys["false"] = "" + g.keys["true"] = "true" + g.keys["empty"] = "" + g.keys["space"] = " " + g.keys["package"] = g.s.PackageName + g.keys["Package"] = g.s.ContractName + g.setMultiKeyValues("pkgName", g.s.ContractName) + g.keys["module"] = moduleName + strings.Replace(moduleCwd[len(modulePath):], "\\", "/", -1) + scName := g.s.PackageName + if g.s.CoreContracts { + // strip off "core" prefix + scName = scName[4:] + } + g.keys["scName"] = scName + g.keys["hscName"] = iscp.Hn(scName).String() + g.keys["scDesc"] = g.s.Description + g.keys["maxIndex"] = strconv.Itoa(g.s.KeyID) +} + +func (g *GenBase) setFieldKeys(pad bool, maxCamelLength, maxSnakeLength int) { + tmp := make(model.StringMap) + for k, v := range g.keys { + if len(k) < 3 { + continue + } + switch k[:3] { + case "fld": + tmp["old"+k[3:]] = v + case "Fld": + tmp["Old"+k[3:]] = v + case "FLD": + tmp["OLD"+k[3:]] = v + } + } + for k, v := range tmp { + g.keys[k] = v + } + g.setMultiKeyValues("fldName", g.currentField.Name) + g.setMultiKeyValues("fldType", g.currentField.Type) + + g.keys["fldAlias"] = g.currentField.Alias + g.keys["fldComment"] = g.currentField.Comment + g.keys["fldMapKey"] = g.currentField.MapKey + g.keys["fldIndex"] = strconv.Itoa(g.currentField.KeyID) + + if pad { + g.keys["fldPad"] = spaces[:maxCamelLength-len(g.keys["fldName"])] + g.keys["fld_pad"] = spaces[:maxSnakeLength-len(g.keys["fld_name"])] + } + + for fieldName, typeValues := range g.typeDependent { + fieldValue := typeValues[g.currentField.Type] + if fieldValue == "" { + // get default value for this field + // TODO make this smarter w.r.t. maps and arrays? + fieldValue = typeValues[""] + } + g.keys[fieldName] = fieldValue + + if fieldName[:3] == "fld" { + // we also want the 'fldKey' variant to facilitate the map key type + fieldValue = typeValues[g.currentField.MapKey] + if fieldValue == "" { + // get default value for this field + // TODO make this smarter w.r.t. maps and arrays? + fieldValue = typeValues[""] + } + g.keys["fldKey"+fieldName[3:]] = fieldValue + } + } +} + +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() + grant := g.currentFunc.Access + comment := "" + index := strings.Index(grant, "//") + if index >= 0 { + comment = grant[index:] + grant = strings.TrimSpace(grant[:index]) + } + g.keys["funcAccess"] = grant + g.keys["funcAccessComment"] = comment + + if pad { + g.keys["funcPad"] = spaces[:maxCamelLength-len(g.keys["funcName"])] + g.keys["func_pad"] = spaces[:maxSnakeLength-len(g.keys["func_name"])] + } +} + +func (g *GenBase) setMultiKeyValues(key, value string) { + value = uncapitalize(value) + g.keys[key] = value + g.keys[capitalize(key)] = capitalize(value) + g.keys[snake(key)] = snake(value) + g.keys[upper(snake(key))] = upper(snake(value)) +} diff --git a/tools/schema/generator/generator.go b/tools/schema/generator/generator.go index b6746acdfa..221813c841 100644 --- a/tools/schema/generator/generator.go +++ b/tools/schema/generator/generator.go @@ -9,132 +9,127 @@ import ( "os" "regexp" "strings" + + "github.com/iotaledger/wasp/tools/schema/model" ) // TODO nested structs // TODO handle case where owner is type AgentID[] +// TODO take copyright from schema? -const ( - AccessChain = "chain" - AccessCreator = "creator" - AccessSelf = "self" - AliasThis = "this" - InitFunc = "Init" - KindFunc = "Func" - KindView = "View" - PropImmutable = "Immutable" - PropMutable = "Mutable" - SpecialFuncInit = "funcInit" - SpecialFuncSetOwner = "setOwner" - SpecialViewGetOwner = "getOwner" -) +type GenBase struct { + currentEvent *model.Struct + currentField *model.Field + currentFunc *model.Func + currentStruct *model.Struct + emitters map[string]func(g *GenBase) + extension string + file *os.File + folder string + funcRegexp *regexp.Regexp + keys model.StringMap + language string + newTypes map[string]bool + rootFolder string + s *model.Schema + tab int + templates model.StringMap + typeDependent model.StringMapMap +} -var ( - ModuleCwd = "???" - ModuleName = "???" - ModulePath = "???" -) +const spaces = " " + +func (g *GenBase) init(s *model.Schema, typeDependent model.StringMapMap, templates []map[string]string) { + g.s = s + g.typeDependent = typeDependent + + g.emitters = map[string]func(g *GenBase){} + g.keys = model.StringMap{} + g.newTypes = map[string]bool{} + g.templates = model.StringMap{} + + config := templates[0] + g.language = config["language"] + g.extension = config["extension"] + g.rootFolder = config["rootFolder"] + g.funcRegexp = regexp.MustCompile(config["funcRegexp"]) + + g.addTemplates(commonTemplates) + for _, template := range templates { + g.addTemplates(template) + } -type Generator interface { - funcName(f *Func) string - generateFuncSignature(f *Func) - generateLanguageSpecificFiles() error - generateProxyArray(field *Field, mutability, arrayType, proxyType string) - generateProxyMap(field *Field, mutability, mapType, proxyType string) - generateProxyReference(field *Field, mutability, typeName string) - writeConsts() - writeContract() - writeInitialFuncs() - writeKeys() - writeLib() - writeParams() - writeResults() - writeState() - writeStructs() - writeTypeDefs() + g.setCommonKeys() } -type GenBase struct { - extension string - file *os.File - Folder string - funcRegexp *regexp.Regexp - gen Generator - language string - NewTypes map[string]bool - rootFolder string - s *Schema - skipDisclaimer bool +func (g *GenBase) addTemplates(t model.StringMap) { + for k, v := range t { + g.templates[k] = v + } } func (g *GenBase) close() { _ = g.file.Close() } -// TODO take copyright from schema? -func (g *GenBase) copyright() string { - text := "// Copyright 2020 IOTA Stiftung\n" + - "// SPDX-License-Identifier: Apache-2.0\n" - if !g.skipDisclaimer { - text += "\n// (Re-)generated by schema tool\n" + - "// >>>> DO NOT CHANGE THIS FILE! <<<<\n" + - "// Change the json schema instead\n" +func (g *GenBase) createFile(path string, overwrite bool, generator func()) (err error) { + if !overwrite && g.exists(path) == nil { + return nil } - return text -} - -func (g *GenBase) create(path string) (err error) { g.file, err = os.Create(path) - return err -} - -func (g *GenBase) createSourceFile(name string, generator func()) error { - err := g.create(g.Folder + name + g.extension) if err != nil { return err } defer g.close() - - // always add copyright to source file - g.println(g.copyright()) - g.skipDisclaimer = false generator() return nil } +func (g *GenBase) createSourceFile(name string, condition bool) error { + if !condition { + return nil + } + return g.createFile(g.folder+name+g.extension, true, func() { + g.emit("copyright") + g.emit("warning") + g.emit(name + g.extension) + }) +} + +func (g *GenBase) error(what string) { + g.println("???:" + what) +} + func (g *GenBase) exists(path string) (err error) { _, err = os.Stat(path) return err } -func (g *GenBase) formatter(on bool) { - if on { - g.printf("\n// @formatter:%s\n", "on") - return +func (g *GenBase) funcName(f *model.Func) string { + name := f.Kind + capitalize(f.Name) + if g.language == "Rust" { + name = snake(name) } - g.printf("// @formatter:%s\n\n", "off") + return name } -func (g *GenBase) Generate(s *Schema) error { - g.s = s - g.NewTypes = make(map[string]bool) - - g.Folder = g.rootFolder + "/" +func (g *GenBase) generateCommonFiles() error { + g.folder = g.rootFolder + "/" if g.rootFolder != "src" { - module := strings.ReplaceAll(ModuleCwd, "\\", "/") + module := strings.ReplaceAll(moduleCwd, "\\", "/") module = module[strings.LastIndex(module, "/")+1:] - g.Folder += module + "/" + g.folder += module + "/" } if g.s.CoreContracts { - g.Folder += g.s.Name + "/" + g.folder += g.s.PackageName + "/" } - err := os.MkdirAll(g.Folder, 0o755) + err := os.MkdirAll(g.folder, 0o755) if err != nil { return err } - info, err := os.Stat(g.Folder + "consts" + g.extension) - if err == nil && info.ModTime().After(s.SchemaTime) { + info, err := os.Stat(g.folder + "consts" + g.extension) + if err == nil && info.ModTime().After(g.s.SchemaTime) { fmt.Printf("skipping %s code generation\n", g.language) return nil } @@ -154,126 +149,97 @@ func (g *GenBase) Generate(s *Schema) error { } func (g *GenBase) generateCode() error { - err := g.createSourceFile("consts", g.gen.writeConsts) + err := g.createSourceFile("consts", true) if err != nil { return err } - if len(g.s.Structs) != 0 { - err = g.createSourceFile("structs", g.gen.writeStructs) - if err != nil { - return err - } + err = g.createSourceFile("keys", !g.s.CoreContracts) + if err != nil { + return err } - if len(g.s.Typedefs) != 0 { - err = g.createSourceFile("typedefs", g.gen.writeTypeDefs) - if err != nil { - return err - } + err = g.createSourceFile("events", len(g.s.Events) != 0) + if err != nil { + return err } - if len(g.s.Params) != 0 { - err = g.createSourceFile("params", g.gen.writeParams) - if err != nil { - return err - } + err = g.createSourceFile("structs", len(g.s.Structs) != 0) + if err != nil { + return err } - if len(g.s.Results) != 0 { - err = g.createSourceFile("results", g.gen.writeResults) - if err != nil { - return err - } + err = g.createSourceFile("typedefs", len(g.s.Typedefs) != 0) + if err != nil { + return err } - err = g.createSourceFile("contract", g.gen.writeContract) + err = g.createSourceFile("params", len(g.s.Params) != 0) + if err != nil { + return err + } + err = g.createSourceFile("results", len(g.s.Results) != 0) + if err != nil { + return err + } + err = g.createSourceFile("state", !g.s.CoreContracts) + if err != nil { + return err + } + err = g.createSourceFile("contract", true) + if err != nil { + return err + } + err = g.createSourceFile("lib", !g.s.CoreContracts) if err != nil { return err } - if !g.s.CoreContracts { - err = g.createSourceFile("keys", g.gen.writeKeys) - if err != nil { - return err - } - err = g.createSourceFile("state", g.gen.writeState) - if err != nil { - return err - } - err = g.createSourceFile("lib", g.gen.writeLib) - if err != nil { - return err - } - err = g.generateFuncs() - if err != nil { - return err - } + return g.generateFuncs() } - - return g.gen.generateLanguageSpecificFiles() + return nil } func (g *GenBase) generateFuncs() error { - scFileName := g.Folder + g.s.Name + g.extension - err := g.open(g.Folder + g.s.Name + g.extension) - if err != nil { + scFileName := g.folder + g.s.PackageName + g.extension + if g.exists(scFileName) != nil { // generate initial SC function file - g.skipDisclaimer = true - return g.createSourceFile(g.s.Name, g.gen.writeInitialFuncs) + return g.createFile(scFileName, false, func() { + g.emit("copyright") + g.emit("funcs" + g.extension) + }) } - // append missing function signatures to existing code file + // append missing SC functions to existing code file - // scan existing file for signatures - lines, existing, err := g.scanExistingCode() + // scan existing file for function names + existing := make(model.StringMap) + lines := make([]string, 0) + err := g.scanExistingCode(scFileName, &existing, &lines) if err != nil { return err } // save old one from overwrite - scOriginal := g.Folder + g.s.Name + ".bak" + scOriginal := g.folder + g.s.PackageName + ".bak" err = os.Rename(scFileName, scOriginal) if err != nil { return err } - err = g.create(scFileName) - if err != nil { - return err - } - defer g.close() - // make copy of file - for _, line := range lines { - g.println(line) - } - - // append any new funcs - for _, f := range g.s.Funcs { - if existing[g.gen.funcName(f)] == "" { - g.gen.generateFuncSignature(f) + err = g.createFile(scFileName, false, func() { + // make copy of original file + for _, line := range lines { + g.println(line) } - } - return os.Remove(scOriginal) -} - -func (g *GenBase) generateProxy(field *Field, mutability string) { - if field.Array { - proxyType := mutability + field.Type - arrayType := "ArrayOf" + proxyType - if !g.NewTypes[arrayType] { - g.NewTypes[arrayType] = true - g.gen.generateProxyArray(field, mutability, arrayType, proxyType) + // 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") + } } - g.gen.generateProxyReference(field, mutability, arrayType) - return - } - - if field.MapKey != "" { - proxyType := mutability + field.Type - mapType := "Map" + field.MapKey + "To" + proxyType - if !g.NewTypes[mapType] { - g.NewTypes[mapType] = true - g.gen.generateProxyMap(field, mutability, mapType, proxyType) - } - g.gen.generateProxyReference(field, mutability, mapType) + }) + if err != nil { + return err } + return os.Remove(scOriginal) } func (g *GenBase) generateTests() error { @@ -283,67 +249,37 @@ func (g *GenBase) generateTests() error { } // do not overwrite existing file - name := strings.ToLower(g.s.Name) + name := strings.ToLower(g.s.PackageName) filename := "test/" + name + "_test.go" - err = g.exists(filename) - if err == nil { - return nil - } + return g.createFile(filename, false, func() { + g.emit("test.go") + }) +} - err = g.create(filename) +func (g *GenBase) openFile(path string, processor func() error) (err error) { + g.file, err = os.Open(path) if err != nil { return err } defer g.close() - - module := ModuleName + strings.ReplaceAll(ModuleCwd[len(ModulePath):], "\\", "/") - g.println("package test") - g.println() - g.println("import (") - g.println("\t\"testing\"") - g.println() - g.printf("\t\"%s/go/%s\"\n", module, g.s.Name) - g.println("\t\"github.com/iotaledger/wasp/packages/vm/wasmsolo\"") - g.println("\t\"github.com/stretchr/testify/require\"") - g.println(")") - g.println() - g.println("func TestDeploy(t *testing.T) {") - g.printf("\tctx := wasmsolo.NewSoloContext(t, %s.ScName, %s.OnLoad)\n", name, name) - g.printf("\trequire.NoError(t, ctx.ContractExists(%s.ScName))\n", name) - g.println("}") - - return nil -} - -func (g *GenBase) open(path string) (err error) { - g.file, err = os.Open(path) - return err -} - -func (g *GenBase) printf(format string, a ...interface{}) { - _, _ = fmt.Fprintf(g.file, format, a...) + return processor() } func (g *GenBase) println(a ...interface{}) { _, _ = fmt.Fprintln(g.file, a...) } -func (g *GenBase) scanExistingCode() ([]string, StringMap, error) { - defer g.close() - existing := make(StringMap) - lines := make([]string, 0) - scanner := bufio.NewScanner(g.file) - for scanner.Scan() { - line := scanner.Text() - matches := g.funcRegexp.FindStringSubmatch(line) - if matches != nil { - existing[matches[1]] = line +func (g *GenBase) scanExistingCode(path string, existing *model.StringMap, lines *[]string) error { + return g.openFile(path, func() error { + scanner := bufio.NewScanner(g.file) + for scanner.Scan() { + line := scanner.Text() + matches := g.funcRegexp.FindStringSubmatch(line) + if matches != nil { + (*existing)[matches[1]] = line + } + *lines = append(*lines, line) } - lines = append(lines, line) - } - err := scanner.Err() - if err != nil { - return nil, nil, err - } - return lines, existing, nil + return scanner.Err() + }) } diff --git a/tools/schema/generator/generator_client.go b/tools/schema/generator/generator_client.go new file mode 100644 index 0000000000..bc48b6369f --- /dev/null +++ b/tools/schema/generator/generator_client.go @@ -0,0 +1,54 @@ +// 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_go.go b/tools/schema/generator/generator_go.go index ff7c9c3648..a7b93dd141 100644 --- a/tools/schema/generator/generator_go.go +++ b/tools/schema/generator/generator_go.go @@ -4,711 +4,27 @@ package generator import ( - "fmt" - "regexp" - "strconv" - "strings" - - "github.com/iotaledger/wasp/packages/iscp" -) - -const ( - goImportWasmLib = "import \"github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib\"" - goImportWasmClient = "import \"github.com/iotaledger/wasp/packages/vm/wasmclient\"" -) - -var goTypes = StringMap{ - "Address": "wasmlib.ScAddress", - "AgentID": "wasmlib.ScAgentID", - "ChainID": "wasmlib.ScChainID", - "Color": "wasmlib.ScColor", - "Hash": "wasmlib.ScHash", - "Hname": "wasmlib.ScHname", - "Int16": "int16", - "Int32": "int32", - "Int64": "int64", - "RequestID": "wasmlib.ScRequestID", - "String": "string", -} - -var goKeys = StringMap{ - "Address": "key", - "AgentID": "key", - "ChainID": "key", - "Color": "key", - "Hash": "key", - "Hname": "key", - "Int16": "??TODO", - "Int32": "wasmlib.Key32(key)", - "Int64": "??TODO", - "RequestID": "key", - "String": "wasmlib.Key(key)", -} - -var goTypeIds = StringMap{ - "Address": "wasmlib.TYPE_ADDRESS", - "AgentID": "wasmlib.TYPE_AGENT_ID", - "ChainID": "wasmlib.TYPE_CHAIN_ID", - "Color": "wasmlib.TYPE_COLOR", - "Hash": "wasmlib.TYPE_HASH", - "Hname": "wasmlib.TYPE_HNAME", - "Int16": "wasmlib.TYPE_INT16", - "Int32": "wasmlib.TYPE_INT32", - "Int64": "wasmlib.TYPE_INT64", - "RequestID": "wasmlib.TYPE_REQUEST_ID", - "String": "wasmlib.TYPE_STRING", -} - -const ( - goTypeBytes = "wasmlib.TYPE_BYTES" - goTypeMap = "wasmlib.TYPE_MAP" + "github.com/iotaledger/wasp/tools/schema/generator/gotemplates" + "github.com/iotaledger/wasp/tools/schema/model" ) type GoGenerator struct { GenBase } -func NewGoGenerator() *GoGenerator { +func NewGoGenerator(s *model.Schema) *GoGenerator { g := &GoGenerator{} - g.extension = ".go" - g.funcRegexp = regexp.MustCompile(`^func (\w+).+$`) - g.language = "Go" - g.rootFolder = "go" - g.gen = g + g.init(s, gotemplates.TypeDependent, gotemplates.Templates) return g } -func (g *GoGenerator) flushConsts() { - if len(g.s.ConstNames) == 0 { - return - } - - if len(g.s.ConstNames) == 1 { - name := g.s.ConstNames[0] - value := g.s.ConstValues[0] - g.printf("\nconst %s = %s\n", name, value) - g.s.flushConsts(func(name string, value string, padLen int) {}) - return - } - - g.printf("\nconst (\n") - g.s.flushConsts(func(name string, value string, padLen int) { - g.printf("\t%s = %s\n", pad(name, padLen), value) - }) - g.printf(")\n") -} - -func (g *GoGenerator) funcName(f *Func) string { - return f.FuncName -} - -func (g *GoGenerator) generateArrayType(varType string) string { - // native core contracts use Array16 instead of our nested array type - if g.s.CoreContracts { - return "wasmlib.TYPE_ARRAY16|" + varType - } - return "wasmlib.TYPE_ARRAY|" + varType -} - -func (g *GoGenerator) generateConstsFields(fields []*Field, prefix string) { - if len(fields) != 0 { - for _, field := range fields { - if field.Alias == AliasThis { - continue - } - name := prefix + capitalize(field.Name) - value := "wasmlib.Key(\"" + field.Alias + "\")" - g.s.appendConst(name, value) - } - g.flushConsts() - } -} - -func (g *GoGenerator) generateContractFuncs() { - g.println("\ntype Funcs struct{}") - g.println("\nvar ScFuncs Funcs") - for _, f := range g.s.Funcs { - assign := "return" - paramsID := "nil" - if len(f.Params) != 0 { - assign = "f :=" - paramsID = "&f.Params.id" - } - resultsID := "nil" - if len(f.Results) != 0 { - assign = "f :=" - resultsID = "&f.Results.id" - } - kind := f.Kind - keyMap := "" - if f.Type == InitFunc { - kind = f.Type + f.Kind - keyMap = ", keyMap[:], idxMap[:]" - } - g.printf("\nfunc (sc Funcs) %s(ctx wasmlib.Sc%sCallContext) *%sCall {\n", f.Type, f.Kind, f.Type) - g.printf("\t%s &%sCall{Func: wasmlib.NewSc%s(ctx, HScName, H%s%s%s)}\n", assign, f.Type, kind, f.Kind, f.Type, keyMap) - if len(f.Params) != 0 || len(f.Results) != 0 { - g.printf("\tf.Func.SetPtrs(%s, %s)\n", paramsID, resultsID) - g.printf("\treturn f\n") - } - g.printf("}\n") - } -} - -func (g *GoGenerator) generateFuncSignature(f *Func) { - g.printf("\nfunc %s(ctx wasmlib.Sc%sContext, f *%sContext) {\n", f.FuncName, f.Kind, f.Type) - switch f.FuncName { - case SpecialFuncInit: - g.printf(" if f.Params.Owner().Exists() {\n") - g.printf(" f.State.Owner().SetValue(f.Params.Owner().Value())\n") - g.printf(" return\n") - g.printf(" }\n") - g.printf(" f.State.Owner().SetValue(ctx.ContractCreator())\n") - case SpecialFuncSetOwner: - g.printf(" f.State.Owner().SetValue(f.Params.Owner().Value())\n") - case SpecialViewGetOwner: - g.printf(" f.Results.Owner().SetValue(f.State.Owner().Value())\n") - default: - } - g.printf("}\n") -} - -func (g *GoGenerator) generateKeysArray(fields []*Field, prefix string) { - for _, field := range fields { - if field.Alias == AliasThis { - continue - } - name := prefix + capitalize(field.Name) - g.printf("\t%s,\n", name) - g.s.KeyID++ - } -} - -func (g *GoGenerator) generateKeysIndexes(fields []*Field, prefix string) { - for _, field := range fields { - if field.Alias == AliasThis { - continue - } - name := "Idx" + prefix + capitalize(field.Name) - field.KeyID = g.s.KeyID - value := strconv.Itoa(field.KeyID) - g.s.KeyID++ - g.s.appendConst(name, value) - } -} - -func (g *GoGenerator) generateLanguageSpecificFiles() error { - if g.s.CoreContracts { - return nil - } - return g.createSourceFile("../main", g.writeSpecialMain) -} - -func (g *GoGenerator) generateProxyArray(field *Field, mutability, arrayType, proxyType string) { - g.printf("\ntype %s struct {\n", arrayType) - g.printf("\tobjID int32\n") - g.printf("}\n") - - if mutability == PropMutable { - g.printf("\nfunc (a %s) Clear() {\n", arrayType) - g.printf("\twasmlib.Clear(a.objID)\n") - g.printf("}\n") - } - - g.printf("\nfunc (a %s) Length() int32 {\n", arrayType) - g.printf("\treturn wasmlib.GetLength(a.objID)\n") - g.printf("}\n") - - if field.TypeID == 0 { - g.generateProxyArrayNewType(field, proxyType, arrayType) - return - } - - // array of predefined type - g.printf("\nfunc (a %s) Get%s(index int32) wasmlib.Sc%s {\n", arrayType, field.Type, proxyType) - g.printf("\treturn wasmlib.NewSc%s(a.objID, wasmlib.Key32(index))\n", proxyType) - g.printf("}\n") -} - -func (g *GoGenerator) generateProxyArrayNewType(field *Field, proxyType, arrayType string) { - for _, subtype := range g.s.Typedefs { - if subtype.Name != field.Type { - continue - } - varType := goTypeMap - if subtype.Array { - varType = goTypeIds[subtype.Type] - if varType == "" { - varType = goTypeBytes - } - varType = g.generateArrayType(varType) - } - g.printf("\nfunc (a %s) Get%s(index int32) %s {\n", arrayType, field.Type, proxyType) - g.printf("\tsubID := wasmlib.GetObjectID(a.objID, wasmlib.Key32(index), %s)\n", varType) - g.printf("\treturn %s{objID: subID}\n", proxyType) - g.printf("}\n") - return - } - - g.printf("\nfunc (a %s) Get%s(index int32) %s {\n", arrayType, field.Type, proxyType) - g.printf("\treturn %s{objID: a.objID, keyID: wasmlib.Key32(index)}\n", proxyType) - g.printf("}\n") -} - -func (g *GoGenerator) generateProxyMap(field *Field, mutability, mapType, proxyType string) { - keyType := goTypes[field.MapKey] - keyValue := goKeys[field.MapKey] - - g.printf("\ntype %s struct {\n", mapType) - g.printf("\tobjID int32\n") - g.printf("}\n") - - if mutability == PropMutable { - g.printf("\nfunc (m %s) Clear() {\n", mapType) - g.printf("\twasmlib.Clear(m.objID)\n") - g.printf("}\n") - } - - if field.TypeID == 0 { - g.generateProxyMapNewType(field, proxyType, mapType, keyType, keyValue) - return - } - - // map of predefined type - g.printf("\nfunc (m %s) Get%s(key %s) wasmlib.Sc%s {\n", mapType, field.Type, keyType, proxyType) - g.printf("\treturn wasmlib.NewSc%s(m.objID, %s.KeyID())\n", proxyType, keyValue) - g.printf("}\n") -} - -func (g *GoGenerator) generateProxyMapNewType(field *Field, proxyType, mapType, keyType, keyValue string) { - for _, subtype := range g.s.Typedefs { - if subtype.Name != field.Type { - continue - } - varType := goTypeMap - if subtype.Array { - varType = goTypeIds[subtype.Type] - if varType == "" { - varType = goTypeBytes - } - varType = g.generateArrayType(varType) - } - g.printf("\nfunc (m %s) Get%s(key %s) %s {\n", mapType, field.Type, keyType, proxyType) - g.printf("\tsubID := wasmlib.GetObjectID(m.objID, %s.KeyID(), %s)\n", keyValue, varType) - g.printf("\treturn %s{objID: subID}\n", proxyType) - g.printf("}\n") - return - } - - g.printf("\nfunc (m %s) Get%s(key %s) %s {\n", mapType, field.Type, keyType, proxyType) - g.printf("\treturn %s{objID: m.objID, keyID: %s.KeyID()}\n", proxyType, keyValue) - g.printf("}\n") -} - -func (g *GoGenerator) generateProxyReference(field *Field, mutability, typeName string) { - if field.Name[0] >= 'A' && field.Name[0] <= 'Z' { - g.printf("\ntype %s%s = %s\n", mutability, field.Name, typeName) - } -} - -func (g *GoGenerator) generateProxyStruct(fields []*Field, mutability, typeName, kind string) { - typeName = mutability + typeName + kind - kind = strings.TrimSuffix(kind, "s") - - // first generate necessary array and map types - for _, field := range fields { - g.generateProxy(field, mutability) - } - - g.printf("\ntype %s struct {\n", typeName) - g.printf("\tid int32\n") - g.printf("}\n") - - for _, field := range fields { - varName := capitalize(field.Name) - varID := "idxMap[Idx" + kind + varName + "]" - if g.s.CoreContracts { - varID = kind + varName + ".KeyID()" - } - varType := goTypeIds[field.Type] - if varType == "" { - varType = goTypeBytes - } - if field.Array { - varType = g.generateArrayType(varType) - arrayType := "ArrayOf" + mutability + field.Type - g.printf("\nfunc (s %s) %s() %s {\n", typeName, varName, arrayType) - g.printf("\tarrID := wasmlib.GetObjectID(s.id, %s, %s)\n", varID, varType) - g.printf("\treturn %s{objID: arrID}\n", arrayType) - g.printf("}\n") - continue - } - if field.MapKey != "" { - varType = goTypeMap - mapType := "Map" + field.MapKey + "To" + mutability + field.Type - g.printf("\nfunc (s %s) %s() %s {\n", typeName, varName, mapType) - mapID := "s.id" - if field.Alias != AliasThis { - mapID = "mapID" - g.printf("\tmapID := wasmlib.GetObjectID(s.id, %s, %s)\n", varID, varType) - } - g.printf("\treturn %s{objID: %s}\n", mapType, mapID) - g.printf("}\n") - continue - } - - proxyType := mutability + field.Type - if field.TypeID == 0 { - g.printf("\nfunc (s %s) %s() %s {\n", typeName, varName, proxyType) - g.printf("\treturn %s{objID: s.id, keyID: %s}\n", proxyType, varID) - g.printf("}\n") - continue - } - - g.printf("\nfunc (s %s) %s() wasmlib.Sc%s {\n", typeName, varName, proxyType) - g.printf("\treturn wasmlib.NewSc%s(s.id, %s)\n", proxyType, varID) - g.printf("}\n") - } -} - -func (g *GoGenerator) generateStruct(typeDef *Struct) { - nameLen, typeLen := calculatePadding(typeDef.Fields, goTypes, false) - - g.printf("\ntype %s struct {\n", typeDef.Name) - for _, field := range typeDef.Fields { - fldName := pad(capitalize(field.Name), nameLen) - fldType := goTypes[field.Type] - if field.Comment != "" { - fldType = pad(fldType, typeLen) - } - g.printf("\t%s %s%s\n", fldName, fldType, field.Comment) - } - g.printf("}\n") - - // write encoder and decoder for struct - g.printf("\nfunc New%sFromBytes(bytes []byte) *%s {\n", typeDef.Name, typeDef.Name) - g.printf("\tdecode := wasmlib.NewBytesDecoder(bytes)\n") - g.printf("\tdata := &%s{}\n", typeDef.Name) - for _, field := range typeDef.Fields { - name := capitalize(field.Name) - g.printf("\tdata.%s = decode.%s()\n", name, field.Type) - } - g.printf("\tdecode.Close()\n") - g.printf("\treturn data\n}\n") - - g.printf("\nfunc (o *%s) Bytes() []byte {\n", typeDef.Name) - g.printf("\treturn wasmlib.NewBytesEncoder().\n") - for _, field := range typeDef.Fields { - name := capitalize(field.Name) - g.printf("\t\t%s(o.%s).\n", field.Type, name) - } - g.printf("\t\tData()\n}\n") - - g.generateStructProxy(typeDef, false) - g.generateStructProxy(typeDef, true) -} - -func (g *GoGenerator) generateStructProxy(typeDef *Struct, mutable bool) { - typeName := PropImmutable + typeDef.Name - if mutable { - typeName = PropMutable + typeDef.Name - } - - g.printf("\ntype %s struct {\n", typeName) - g.printf("\tobjID int32\n") - g.printf("\tkeyID wasmlib.Key32\n") - g.printf("}\n") - - g.printf("\nfunc (o %s) Exists() bool {\n", typeName) - g.printf("\treturn wasmlib.Exists(o.objID, o.keyID, wasmlib.TYPE_BYTES)\n") - g.printf("}\n") - - if mutable { - g.printf("\nfunc (o %s) SetValue(value *%s) {\n", typeName, typeDef.Name) - g.printf("\twasmlib.SetBytes(o.objID, o.keyID, wasmlib.TYPE_BYTES, value.Bytes())\n") - g.printf("}\n") - } - - g.printf("\nfunc (o %s) Value() *%s {\n", typeName, typeDef.Name) - g.printf("\treturn New%sFromBytes(wasmlib.GetBytes(o.objID, o.keyID, wasmlib.TYPE_BYTES))\n", typeDef.Name) - g.printf("}\n") -} - -func (g *GoGenerator) generateThunk(f *Func) { - nameLen := f.nameLen(5) - mutability := PropMutable - if f.Kind == KindView { - mutability = PropImmutable - } - g.printf("\ntype %sContext struct {\n", f.Type) - if len(f.Params) != 0 { - g.printf("\t%s Immutable%sParams\n", pad("Params", nameLen), f.Type) - } - if len(f.Results) != 0 { - g.printf("\tResults Mutable%sResults\n", f.Type) - } - g.printf("\t%s %s%sState\n", pad("State", nameLen), mutability, g.s.FullName) - g.printf("}\n") - - g.printf("\nfunc %sThunk(ctx wasmlib.Sc%sContext) {\n", f.FuncName, f.Kind) - g.printf("\tctx.Log(\"%s.%s\")\n", g.s.Name, f.FuncName) - - if f.Access != "" { - g.generateThunkAccessCheck(f) - } - - g.printf("\tf := &%sContext{\n", f.Type) - - if len(f.Params) != 0 { - g.printf("\t\tParams: Immutable%sParams{\n", f.Type) - g.printf("\t\t\tid: wasmlib.OBJ_ID_PARAMS,\n") - g.printf("\t\t},\n") - } - - if len(f.Results) != 0 { - g.printf("\t\tResults: Mutable%sResults{\n", f.Type) - g.printf("\t\t\tid: wasmlib.OBJ_ID_RESULTS,\n") - g.printf("\t\t},\n") - } - - g.printf("\t\tState: %s%sState{\n", mutability, g.s.FullName) - g.printf("\t\t\tid: wasmlib.OBJ_ID_STATE,\n") - g.printf("\t\t},\n") - - g.printf("\t}\n") - - for _, param := range f.Params { - if !param.Optional { - name := capitalize(param.Name) - g.printf("\tctx.Require(f.Params.%s().Exists(), \"missing mandatory %s\")\n", name, param.Name) - } - } - - g.printf("\t%s(ctx, f)\n", f.FuncName) - g.printf("\tctx.Log(\"%s.%s ok\")\n", g.s.Name, f.FuncName) - g.printf("}\n") -} - -func (g *GoGenerator) generateThunkAccessCheck(f *Func) { - grant := f.Access - index := strings.Index(grant, "//") - if index >= 0 { - g.printf("\t%s\n", grant[index:]) - grant = strings.TrimSpace(grant[:index]) - } - switch grant { - case AccessSelf: - grant = "ctx.AccountID()" - case AccessChain: - grant = "ctx.ChainOwnerID()" - case AccessCreator: - grant = "ctx.ContractCreator()" - default: - g.printf("\taccess := ctx.State().GetAgentID(wasmlib.Key(\"%s\"))\n", grant) - g.printf("\tctx.Require(access.Exists(), \"access not set: %s\")\n", grant) - grant = "access.Value()" - } - g.printf("\tctx.Require(ctx.Caller() == %s, \"no permission\")\n\n", grant) -} - -func (g *GoGenerator) packageName() string { - return fmt.Sprintf("package %s\n", g.s.Name) -} - -func (g *GoGenerator) writeConsts() { - g.println(g.packageName()) - g.println(goImportWasmLib) - - scName := g.s.Name - if g.s.CoreContracts { - // remove 'core' prefix - scName = scName[4:] - } - g.s.appendConst("ScName", "\""+scName+"\"") - if g.s.Description != "" { - g.s.appendConst("ScDescription", "\""+g.s.Description+"\"") - } - hName := iscp.Hn(scName) - hNameType := "wasmlib.ScHname" - g.s.appendConst("HScName", hNameType+"(0x"+hName.String()+")") - g.flushConsts() - - g.generateConstsFields(g.s.Params, "Param") - g.generateConstsFields(g.s.Results, "Result") - g.generateConstsFields(g.s.StateVars, "State") - - if len(g.s.Funcs) != 0 { - for _, f := range g.s.Funcs { - constName := capitalize(f.FuncName) - g.s.appendConst(constName, "\""+f.String+"\"") - } - g.flushConsts() - - for _, f := range g.s.Funcs { - constHname := "H" + capitalize(f.FuncName) - g.s.appendConst(constHname, hNameType+"(0x"+f.Hname.String()+")") - } - g.flushConsts() - } -} - -func (g *GoGenerator) writeContract() { - g.println(g.packageName()) - g.println(goImportWasmLib) - - for _, f := range g.s.Funcs { - nameLen := f.nameLen(4) - kind := f.Kind - if f.Type == InitFunc { - kind = f.Type + f.Kind - } - g.printf("\ntype %sCall struct {\n", f.Type) - g.printf("\t%s *wasmlib.Sc%s\n", pad(KindFunc, nameLen), kind) - if len(f.Params) != 0 { - g.printf("\t%s Mutable%sParams\n", pad("Params", nameLen), f.Type) - } - if len(f.Results) != 0 { - g.printf("\tResults Immutable%sResults\n", f.Type) - } - g.printf("}\n") - } - - g.generateContractFuncs() - - if g.s.CoreContracts { - g.printf("\nfunc OnLoad() {\n") - g.printf("\texports := wasmlib.NewScExports()\n") - for _, f := range g.s.Funcs { - constName := capitalize(f.FuncName) - g.printf("\texports.Add%s(%s, wasmlib.%sError)\n", f.Kind, constName, f.Kind) - } - g.printf("}\n") - } -} - -func (g *GoGenerator) writeInitialFuncs() { - g.println(g.packageName()) - g.println(goImportWasmLib) - - for _, f := range g.s.Funcs { - g.generateFuncSignature(f) - } -} - -func (g *GoGenerator) writeKeys() { - g.println(g.packageName()) - g.println(goImportWasmLib) - - g.s.KeyID = 0 - g.generateKeysIndexes(g.s.Params, "Param") - g.generateKeysIndexes(g.s.Results, "Result") - g.generateKeysIndexes(g.s.StateVars, "State") - g.flushConsts() - - size := g.s.KeyID - g.printf("\nconst keyMapLen = %d\n", size) - g.printf("\nvar keyMap = [keyMapLen]wasmlib.Key{\n") - g.generateKeysArray(g.s.Params, "Param") - g.generateKeysArray(g.s.Results, "Result") - g.generateKeysArray(g.s.StateVars, "State") - g.printf("}\n") - g.printf("\nvar idxMap [keyMapLen]wasmlib.Key32\n") -} - -func (g *GoGenerator) writeLib() { - g.println("//nolint:dupl") - g.println(g.packageName()) - g.println(goImportWasmLib) - - g.printf("\nfunc OnLoad() {\n") - g.printf("\texports := wasmlib.NewScExports()\n") - for _, f := range g.s.Funcs { - constName := capitalize(f.FuncName) - g.printf("\texports.Add%s(%s, %sThunk)\n", f.Kind, constName, f.FuncName) - } - - g.printf("\n\tfor i, key := range keyMap {\n") - g.printf("\t\tidxMap[i] = key.KeyID()\n") - g.printf("\t}\n") - - g.printf("}\n") - - // generate parameter structs and thunks to set up and check parameters - for _, f := range g.s.Funcs { - g.generateThunk(f) - } -} - -func (g *GoGenerator) writeParams() { - g.printf(g.packageName()) - g.println(goImportWasmLib) - - for _, f := range g.s.Funcs { - if len(f.Params) == 0 { - continue - } - g.generateProxyStruct(f.Params, PropImmutable, f.Type, "Params") - g.generateProxyStruct(f.Params, PropMutable, f.Type, "Params") +func (g *GoGenerator) Generate() error { + err := g.generateCommonFiles() + if err != nil { + return err } -} - -func (g *GoGenerator) writeResults() { - g.printf(g.packageName()) - g.println(goImportWasmLib) - for _, f := range g.s.Funcs { - if len(f.Results) == 0 { - continue - } - g.generateProxyStruct(f.Results, PropImmutable, f.Type, "Results") - g.generateProxyStruct(f.Results, PropMutable, f.Type, "Results") - } -} - -func (g *GoGenerator) writeSpecialMain() { - g.println("// +build wasm") - g.println("\npackage main") - g.println() - g.println(goImportWasmClient) - module := ModuleName + strings.Replace(ModuleCwd[len(ModulePath):], "\\", "/", -1) - g.printf("\nimport \"%s/go/%s\"\n", module, g.s.Name) - - g.printf("\nfunc main() {\n") - g.printf("}\n") - - g.printf("\n//export on_load\n") - g.printf("func onLoad() {\n") - g.printf("\th := &wasmclient.WasmVMHost{}\n") - g.printf("\th.ConnectWasmHost()\n") - g.printf("\t%s.OnLoad()\n", g.s.Name) - g.printf("}\n") -} + // now generate language-specific files -func (g *GoGenerator) writeState() { - g.printf(g.packageName()) - if len(g.s.StateVars) != 0 { - g.println(goImportWasmLib) - } - - g.generateProxyStruct(g.s.StateVars, PropImmutable, g.s.FullName, "State") - g.generateProxyStruct(g.s.StateVars, PropMutable, g.s.FullName, "State") -} - -func (g *GoGenerator) writeStructs() { - g.println(g.packageName()) - g.println(goImportWasmLib) - - for _, typeDef := range g.s.Structs { - g.generateStruct(typeDef) - } -} - -func (g *GoGenerator) writeTypeDefs() { - g.println(g.packageName()) - g.println(goImportWasmLib) - - for _, subtype := range g.s.Typedefs { - g.generateProxy(subtype, PropImmutable) - g.generateProxy(subtype, PropMutable) - } + return g.createSourceFile("../main", !g.s.CoreContracts) } diff --git a/tools/schema/generator/generator_java.go b/tools/schema/generator/generator_java.go deleted file mode 100644 index 139dab062c..0000000000 --- a/tools/schema/generator/generator_java.go +++ /dev/null @@ -1,439 +0,0 @@ -// Copyright 2020 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -package generator - -import ( - "bufio" - "fmt" - "os" - "regexp" - "strings" - - "github.com/iotaledger/wasp/packages/iscp" -) - -var javaFuncRegexp = regexp.MustCompile(`public static void (\w+).+$`) - -var javaTypes = StringMap{ - "Address": "ScAddress", - "AgentID": "ScAgentID", - "ChainID": "ScChainID", - "Color": "ScColor", - "Hash": "ScHash", - "Hname": "Hname", - "Int16": "short", - "Int32": "int", - "Int64": "long", - "RequestID": "ScRequestID", - "String": "String", -} - -func (s *Schema) GenerateJava() error { - currentPath, err := os.Getwd() - if err != nil { - return err - } - javaPath := "../../java/src/org/iota/wasp/contracts/" + s.Name - err = os.MkdirAll(javaPath, 0o755) - if err != nil { - return err - } - err = os.Chdir(javaPath) - if err != nil { - return err - } - defer func() { - _ = os.Chdir(currentPath) - }() - - err = os.MkdirAll("test", 0o755) - if err != nil { - return err - } - // err = os.MkdirAll("wasmmain", 0755) - // if err != nil { - // return err - // } - - // err = s.GenerateJavaWasmMain() - // if err != nil { - // return err - // } - err = s.GenerateJavaLib() - if err != nil { - return err - } - err = s.GenerateJavaConsts() - if err != nil { - return err - } - err = s.GenerateJavaTypes() - if err != nil { - return err - } - // err = s.GenerateJavaFuncs() - // if err != nil { - // return err - // } - return nil -} - -func (s *Schema) GenerateJavaFunc(file *os.File, f *Func) error { - funcName := f.FuncName - funcKind := capitalize(f.FuncName[:4]) - fmt.Fprintf(file, "\npublic static void %s(Sc%sContext ctx, %sParams params) {\n", funcName, funcKind, capitalize(funcName)) - fmt.Fprintf(file, "}\n") - return nil -} - -func (s *Schema) GenerateJavaFuncs() error { - scFileName := s.Name + ".java" - file, err := os.Open(scFileName) - if err != nil { - return s.GenerateJavaFuncsNew(scFileName) - } - lines, existing, err := s.GenerateJavaFuncScanner(file) - if err != nil { - return err - } - - // save old one from overwrite - scOriginal := s.Name + ".bak" - err = os.Rename(scFileName, scOriginal) - if err != nil { - return err - } - file, err = os.Create(scFileName) - if err != nil { - return err - } - defer file.Close() - - // make copy of file - for _, line := range lines { - fmt.Fprintln(file, line) - } - - // append any new funcs - for _, f := range s.Funcs { - if existing[f.FuncName] == "" { - err = s.GenerateJavaFunc(file, f) - if err != nil { - return err - } - } - } - - return os.Remove(scOriginal) -} - -func (s *Schema) GenerateJavaFuncScanner(file *os.File) ([]string, StringMap, error) { - defer file.Close() - existing := make(StringMap) - lines := make([]string, 0) - scanner := bufio.NewScanner(file) - for scanner.Scan() { - line := scanner.Text() - matches := javaFuncRegexp.FindStringSubmatch(line) - if matches != nil { - existing[matches[1]] = line - } - lines = append(lines, line) - } - err := scanner.Err() - if err != nil { - return nil, nil, err - } - return lines, existing, nil -} - -func (s *Schema) GenerateJavaFuncsNew(scFileName string) error { - file, err := os.Create(scFileName) - if err != nil { - return err - } - defer file.Close() - - // write file header - // fmt.Fprintln(file, copyright(false)) - fmt.Fprintf(file, "package org.iota.wasp.contracts.%s;\n\n", s.Name) - fmt.Fprintf(file, "import org.iota.wasp.contracts.%s.lib.*;\n", s.Name) - fmt.Fprintf(file, "import org.iota.wasp.wasmlib.context.*;\n") - fmt.Fprintf(file, "import org.iota.wasp.wasmlib.hashtypes.*;\n") - fmt.Fprintf(file, "import org.iota.wasp.wasmlib.immutable.*;\n") - fmt.Fprintf(file, "import org.iota.wasp.wasmlib.mutable.*;\n\n") - - fmt.Fprintf(file, "public class %s {\n", s.FullName) - for _, f := range s.Funcs { - err = s.GenerateJavaFunc(file, f) - if err != nil { - return err - } - } - fmt.Fprintf(file, "}\n") - return nil -} - -func (s *Schema) GenerateJavaLib() error { - err := os.MkdirAll("lib", 0o755) - if err != nil { - return err - } - file, err := os.Create("lib/" + s.FullName + "Thunk.java") - if err != nil { - return err - } - defer file.Close() - - // write file header - // fmt.Fprintln(file, copyright(true)) - fmt.Fprintf(file, "package org.iota.wasp.contracts.%s.lib;\n\n", s.Name) - fmt.Fprintf(file, "import de.mirkosertic.bytecoder.api.*;\n") - fmt.Fprintf(file, "import org.iota.wasp.contracts.%s.*;\n", s.Name) - fmt.Fprintf(file, "import org.iota.wasp.wasmlib.context.*;\n") - fmt.Fprintf(file, "import org.iota.wasp.wasmlib.exports.*;\n") - fmt.Fprintf(file, "import org.iota.wasp.wasmlib.immutable.*;\n") - fmt.Fprintf(file, "import org.iota.wasp.wasmlib.keys.*;\n\n") - - fmt.Fprintf(file, "public class %sThunk {\n", s.FullName) - fmt.Fprintf(file, " public static void main(String[] args) {\n") - fmt.Fprintf(file, " }\n\n") - - fmt.Fprintf(file, " @Export(\"on_load\")\n") - fmt.Fprintf(file, " public static void onLoad() {\n") - fmt.Fprintf(file, " ScExports exports = new ScExports();\n") - for _, f := range s.Funcs { - name := capitalize(f.FuncName) - kind := capitalize(f.FuncName[:4]) - fmt.Fprintf(file, " exports.Add%s(Consts.%s, %sThunk::%sThunk);\n", kind, name, s.FullName, f.FuncName) - } - fmt.Fprintf(file, " }\n") - - // generate parameter structs and thunks to set up and check parameters - for _, f := range s.Funcs { - name := capitalize(f.FuncName) - params, err := os.Create("lib/" + name + "Params.java") - if err != nil { - return err - } - defer params.Close() - s.GenerateJavaThunk(file, params, f) - } - - fmt.Fprintf(file, "}\n") - return nil -} - -func (s *Schema) GenerateJavaConsts() error { - file, err := os.Create("lib/Consts.java") - if err != nil { - return err - } - defer file.Close() - - // write file header - // fmt.Fprintln(file, copyright(true)) - fmt.Fprintf(file, "package org.iota.wasp.contracts.%s.lib;\n\n", s.Name) - fmt.Fprintf(file, "import org.iota.wasp.wasmlib.hashtypes.*;\n") - fmt.Fprintf(file, "import org.iota.wasp.wasmlib.keys.*;\n") - fmt.Fprintf(file, "\npublic class Consts {\n") - - fmt.Fprintf(file, " public static final String ScName = \"%s\";\n", s.Name) - if s.Description != "" { - fmt.Fprintf(file, " public static final String ScDescription = \"%s\";\n", s.Description) - } - hName := iscp.Hn(s.Name) - fmt.Fprintf(file, " public static final ScHname HScName = new ScHname(0x%s);\n", hName.String()) - - if len(s.Params) != 0 { - fmt.Fprintln(file) - for _, param := range s.Params { - name := capitalize(param.Name) - fmt.Fprintf(file, " public static final Key Param%s = new Key(\"%s\");\n", name, param.Alias) - } - } - - if len(s.StateVars) != 0 { - fmt.Fprintln(file) - for _, field := range s.StateVars { - name := capitalize(field.Name) - fmt.Fprintf(file, " public static final Key Var%s = new Key(\"%s\");\n", name, field.Alias) - } - } - - if len(s.Funcs) != 0 { - fmt.Fprintln(file) - for _, f := range s.Funcs { - name := capitalize(f.FuncName) - fmt.Fprintf(file, " public static final String %s = \"%s\";\n", name, f.String) - } - - fmt.Fprintln(file) - for _, f := range s.Funcs { - name := capitalize(f.FuncName) - fmt.Fprintf(file, " public static final ScHname H%s = new ScHname(0x%s);\n", name, f.Hname.String()) - } - } - - fmt.Fprintf(file, "}\n") - return nil -} - -func (s *Schema) GenerateJavaThunk(file, params *os.File, f *Func) { - // calculate padding - nameLen, typeLen := calculatePadding(f.Params, javaTypes, false) - - funcName := capitalize(f.FuncName) - funcKind := capitalize(f.FuncName[:4]) - - // fmt.Fprintln(params, copyright(true)) - fmt.Fprintf(params, "package org.iota.wasp.contracts.%s.lib;\n", s.Name) - if len(f.Params) != 0 { - fmt.Fprintf(params, "\nimport org.iota.wasp.wasmlib.immutable.*;\n") - } - if len(f.Params) > 1 { - fmt.Fprintf(params, "\n// @formatter:off") - } - fmt.Fprintf(params, "\npublic class %sParams {\n", funcName) - for _, param := range f.Params { - fldName := capitalize(param.Name) + ";" - if param.Comment != "" { - fldName = pad(fldName, nameLen+1) - } - fldType := pad(param.Type, typeLen) - fmt.Fprintf(params, " public ScImmutable%s %s%s\n", fldType, fldName, param.Comment) - } - fmt.Fprintf(params, "}\n") - if len(f.Params) > 1 { - fmt.Fprintf(params, "// @formatter:on\n") - } - - fmt.Fprintf(file, "\n private static void %sThunk(Sc%sContext ctx) {\n", f.FuncName, funcKind) - fmt.Fprintf(file, " ctx.Log(\"%s.%s\");\n", s.Name, f.FuncName) - - if f.Access != "" { - s.generateJavaThunkAccessCheck(file, f) - } - - if len(f.Params) != 0 { - fmt.Fprintf(file, " var p = ctx.Params();\n") - } - fmt.Fprintf(file, " var params = new %sParams();\n", funcName) - for _, param := range f.Params { - name := capitalize(param.Name) - fmt.Fprintf(file, " params.%s = p.Get%s(Consts.Param%s);\n", name, param.Type, name) - } - for _, param := range f.Params { - if !param.Optional { - name := capitalize(param.Name) - fmt.Fprintf(file, " ctx.Require(params.%s.Exists(), \"missing mandatory %s\");\n", name, param.Name) - } - } - fmt.Fprintf(file, " %s.%s(ctx, params);\n", s.FullName, f.FuncName) - fmt.Fprintf(file, " ctx.Log(\"%s.%s ok\");\n", s.Name, f.FuncName) - fmt.Fprintf(file, " }\n") -} - -func (s *Schema) generateJavaThunkAccessCheck(file *os.File, f *Func) { - grant := f.Access - index := strings.Index(grant, "//") - if index >= 0 { - fmt.Fprintf(file, " %s\n", grant[index:]) - grant = strings.TrimSpace(grant[:index]) - } - switch grant { - case AccessSelf: - grant = "ctx.AccountID()" - case AccessChain: - grant = "ctx.ChainOwnerID()" - case AccessCreator: - grant = "ctx.ContractCreator()" - default: - fmt.Fprintf(file, " var access = ctx.State().GetAgentID(new Key(\"%s\"));\n", grant) - fmt.Fprintf(file, " ctx.Require(access.Exists(), \"access not set: %s\");\n", grant) - grant = "access.Value()" - } - fmt.Fprintf(file, " ctx.Require(ctx.Caller().equals(%s), \"no permission\");\n\n", grant) -} - -func (s *Schema) GenerateJavaTypes() error { - if len(s.Structs) == 0 { - return nil - } - - err := os.MkdirAll("structs", 0o755) - if err != nil { - return err - } - - // write structs - for _, typeDef := range s.Structs { - err = s.GenerateJavaType(typeDef) - if err != nil { - return err - } - } - - return nil -} - -func (s *Schema) GenerateJavaType(td *Struct) error { - file, err := os.Create("structs/" + td.Name + ".java") - if err != nil { - return err - } - defer file.Close() - - // calculate padding - nameLen, typeLen := calculatePadding(td.Fields, javaTypes, false) - - // write file header - // fmt.Fprint(file, copyright(true)) - fmt.Fprintf(file, "\npackage org.iota.wasp.contracts.%s.structs;\n\n", s.Name) - fmt.Fprint(file, "import org.iota.wasp.wasmlib.bytes.*;\n") - fmt.Fprint(file, "import org.iota.wasp.wasmlib.hashtypes.*;\n\n") - - fmt.Fprintf(file, "public class %s {\n", td.Name) - - // write struct layout - if len(td.Fields) > 1 { - fmt.Fprint(file, " // @formatter:off\n") - } - for _, field := range td.Fields { - fldName := capitalize(field.Name) + ";" - fldType := pad(javaTypes[field.Type], typeLen) - if field.Comment != "" { - fldName = pad(fldName, nameLen+1) - } - fmt.Fprintf(file, " public %s %s%s\n", fldType, fldName, field.Comment) - } - if len(td.Fields) > 1 { - fmt.Fprint(file, " // @formatter:on\n") - } - - // write default constructor - fmt.Fprintf(file, "\n public %s() {\n }\n", td.Name) - - // write constructor from byte array - fmt.Fprintf(file, "\n public %s(byte[] bytes) {\n", td.Name) - fmt.Fprintf(file, " BytesDecoder decode = new BytesDecoder(bytes);\n") - for _, field := range td.Fields { - name := capitalize(field.Name) - fmt.Fprintf(file, " %s = decode.%s();\n", name, field.Type) - } - fmt.Fprintf(file, " decode.Close();\n") - fmt.Fprintf(file, " }\n") - - // write conversion to byte array - fmt.Fprintf(file, "\n public byte[] toBytes() {\n") - fmt.Fprintf(file, " return new BytesEncoder().\n") - for _, field := range td.Fields { - name := capitalize(field.Name) - fmt.Fprintf(file, " %s(%s).\n", field.Type, name) - } - fmt.Fprintf(file, " Data();\n }\n") - - fmt.Fprintf(file, "}\n") - return nil -} diff --git a/tools/schema/generator/generator_rust.go b/tools/schema/generator/generator_rust.go index 0eb330e612..6268d436b3 100644 --- a/tools/schema/generator/generator_rust.go +++ b/tools/schema/generator/generator_rust.go @@ -4,944 +4,34 @@ package generator import ( - "regexp" - "strconv" - "strings" - - "github.com/iotaledger/wasp/packages/iscp" -) - -const ( - allowDeadCode = "#![allow(dead_code)]" - allowUnusedImports = "#![allow(unused_imports)]" - useConsts = "use crate::consts::*;" - useCrate = "use crate::*;" - useKeys = "use crate::keys::*;" - useParams = "use crate::params::*;" - useResults = "use crate::results::*;" - useState = "use crate::state::*;" - useStdPtr = "use std::ptr;" - useStructs = "use crate::structs::*;" - useTypeDefs = "use crate::typedefs::*;" - useWasmLib = "use wasmlib::*;" - useWasmLibHost = "use wasmlib::host::*;" -) - -var rustTypes = StringMap{ - "Address": "ScAddress", - "AgentID": "ScAgentID", - "ChainID": "ScChainID", - "Color": "ScColor", - "Hash": "ScHash", - "Hname": "ScHname", - "Int16": "i16", - "Int32": "i32", - "Int64": "i64", - "RequestID": "ScRequestID", - "String": "String", -} - -var rustKeyTypes = StringMap{ - "Address": "&ScAddress", - "AgentID": "&ScAgentID", - "ChainID": "&ScChainID", - "Color": "&ScColor", - "Hash": "&ScHash", - "Hname": "&ScHname", - "Int16": "??TODO", - "Int32": "i32", - "Int64": "??TODO", - "RequestID": "&ScRequestID", - "String": "&str", -} - -var rustKeys = StringMap{ - "Address": "key", - "AgentID": "key", - "ChainID": "key", - "Color": "key", - "Hash": "key", - "Hname": "key", - "Int16": "??TODO", - "Int32": "Key32(int32)", - "Int64": "??TODO", - "RequestID": "key", - "String": "key", -} - -var rustTypeIds = StringMap{ - "Address": "TYPE_ADDRESS", - "AgentID": "TYPE_AGENT_ID", - "ChainID": "TYPE_CHAIN_ID", - "Color": "TYPE_COLOR", - "Hash": "TYPE_HASH", - "Hname": "TYPE_HNAME", - "Int16": "TYPE_INT16", - "Int32": "TYPE_INT32", - "Int64": "TYPE_INT64", - "RequestID": "TYPE_REQUEST_ID", - "String": "TYPE_STRING", -} - -const ( - rustTypeBytes = "TYPE_BYTES" - rustTypeMap = "TYPE_MAP" + "github.com/iotaledger/wasp/tools/schema/generator/rstemplates" + "github.com/iotaledger/wasp/tools/schema/model" ) type RustGenerator struct { GenBase } -func NewRustGenerator() *RustGenerator { +func NewRustGenerator(s *model.Schema) *RustGenerator { g := &RustGenerator{} - g.extension = ".rs" - g.funcRegexp = regexp.MustCompile(`^pub fn (\w+).+$`) - g.language = "Rust" - g.rootFolder = "src" - g.gen = g + g.init(s, rstemplates.TypeDependent, rstemplates.Templates) return g } -func (g *RustGenerator) crateOrWasmLib(withContract, withHost bool) string { - if g.s.CoreContracts { - retVal := useCrate - if withContract { - retVal += "\nuse crate::" + g.s.Name + "::*;" - } - if withHost { - retVal += "\nuse crate::host::*;" - } - return retVal - } - retVal := useWasmLib - if withHost { - retVal += "\n" + useWasmLibHost - } - return retVal -} - -func (g *RustGenerator) flushConsts(crateOnly bool) { - if len(g.s.ConstNames) == 0 { - return - } - - crate := "" - if crateOnly { - crate = "(crate)" - } - g.println() - g.s.flushConsts(func(name string, value string, padLen int) { - g.printf("pub%s const %s %s;\n", crate, pad(name+":", padLen+1), value) - }) -} - -func (g *RustGenerator) funcName(f *Func) string { - return snake(f.FuncName) -} - -func (g *RustGenerator) generateArrayType(varType string) string { - // native core contracts use Array16 instead of our nested array type - if g.s.CoreContracts { - return "TYPE_ARRAY16 | " + varType - } - return "TYPE_ARRAY | " + varType -} - -func (g *RustGenerator) generateConstsFields(fields []*Field, prefix string) { - if len(fields) != 0 { - for _, field := range fields { - if field.Alias == AliasThis { - continue - } - name := prefix + upper(snake(field.Name)) - value := "&str = \"" + field.Alias + "\"" - g.s.appendConst(name, value) - } - g.flushConsts(g.s.CoreContracts) - } -} - -func (g *RustGenerator) generateContractFuncs() { - g.println("\npub struct ScFuncs {") - g.println("}") - g.println("\nimpl ScFuncs {") - - for _, f := range g.s.Funcs { - nameLen := f.nameLen(4) + 1 - funcName := g.funcName(f) - constName := upper(funcName) - letMut := "" - if len(f.Params) != 0 || len(f.Results) != 0 { - letMut = "let mut f = " - } - kind := f.Kind - if f.Type == InitFunc { - kind = f.Type + f.Kind - } - g.printf(" pub fn %s(_ctx: & dyn Sc%sCallContext) -> %sCall {\n", funcName[5:], f.Kind, f.Type) - g.printf(" %s%sCall {\n", letMut, f.Type) - g.printf(" %s Sc%s::new(HSC_NAME, H%s),\n", pad("func:", nameLen), kind, constName) - paramsID := "ptr::null_mut()" - if len(f.Params) != 0 { - paramsID = "&mut f.params.id" - g.printf(" %s Mutable%sParams { id: 0 },\n", pad("params:", nameLen), f.Type) - } - resultsID := "ptr::null_mut()" - if len(f.Results) != 0 { - resultsID = "&mut f.results.id" - g.printf(" results: Immutable%sResults { id: 0 },\n", f.Type) - } - g.printf(" }") - if len(f.Params) != 0 || len(f.Results) != 0 { - g.printf(";\n") - g.printf(" f.func.set_ptrs(%s, %s);\n", paramsID, resultsID) - g.printf(" f") - } - g.printf("\n }\n") - } - g.printf("}\n") -} - -func (g *RustGenerator) generateFuncSignature(f *Func) { - switch f.FuncName { - case SpecialFuncInit: - g.printf("\npub fn %s(ctx: &Sc%sContext, f: &%sContext) {\n", g.funcName(f), f.Kind, capitalize(f.Type)) - g.printf(" if f.params.owner().exists() {\n") - g.printf(" f.state.owner().set_value(&f.params.owner().value());\n") - g.printf(" return;\n") - g.printf(" }\n") - g.printf(" f.state.owner().set_value(&ctx.contract_creator());\n") - case SpecialFuncSetOwner: - g.printf("\npub fn %s(_ctx: &Sc%sContext, f: &%sContext) {\n", g.funcName(f), f.Kind, capitalize(f.Type)) - g.printf(" f.state.owner().set_value(&f.params.owner().value());\n") - case SpecialViewGetOwner: - g.printf("\npub fn %s(_ctx: &Sc%sContext, f: &%sContext) {\n", g.funcName(f), f.Kind, capitalize(f.Type)) - g.printf(" f.results.owner().set_value(&f.state.owner().value());\n") - default: - g.printf("\npub fn %s(_ctx: &Sc%sContext, _f: &%sContext) {\n", g.funcName(f), f.Kind, capitalize(f.Type)) - } - g.printf("}\n") -} - -func (g *RustGenerator) generateKeysArray(fields []*Field, prefix string) { - for _, field := range fields { - if field.Alias == AliasThis { - continue - } - name := prefix + upper(snake(field.Name)) - g.printf(" %s,\n", name) - g.s.KeyID++ - } -} - -func (g *RustGenerator) generateKeysIndexes(fields []*Field, prefix string) { - for _, field := range fields { - if field.Alias == AliasThis { - continue - } - name := "IDX_" + prefix + upper(snake(field.Name)) - field.KeyID = g.s.KeyID - value := "usize = " + strconv.Itoa(field.KeyID) - g.s.KeyID++ - g.s.appendConst(name, value) - } -} - -func (g *RustGenerator) generateLanguageSpecificFiles() error { - if g.s.CoreContracts { - return g.createSourceFile("mod", g.writeSpecialMod) - } - return g.writeSpecialCargoToml() -} - -func (g *RustGenerator) generateModLines(format string) { - g.println() - - if !g.s.CoreContracts { - g.printf(format, g.s.Name) - g.println() - } - - g.printf(format, "consts") - g.printf(format, "contract") - if !g.s.CoreContracts { - g.printf(format, "keys") - g.printf(format, "lib") - } - if len(g.s.Params) != 0 { - g.printf(format, "params") - } - if len(g.s.Results) != 0 { - g.printf(format, "results") - } - if !g.s.CoreContracts { - g.printf(format, "state") - if len(g.s.Structs) != 0 { - g.printf(format, "structs") - } - if len(g.s.Typedefs) != 0 { - g.printf(format, "typedefs") - } - } -} - -func (g *RustGenerator) generateProxyArray(field *Field, mutability, arrayType, proxyType string) { - g.printf("\npub struct %s {\n", arrayType) - g.printf(" pub(crate) obj_id: i32,\n") - g.printf("}\n") - - g.printf("\nimpl %s {", arrayType) - defer g.printf("}\n") - - if mutability == PropMutable { - g.printf("\n pub fn clear(&self) {\n") - g.printf(" clear(self.obj_id);\n") - g.printf(" }\n") - } - - g.printf("\n pub fn length(&self) -> i32 {\n") - g.printf(" get_length(self.obj_id)\n") - g.printf(" }\n") - - if field.TypeID == 0 { - g.generateProxyArrayNewType(field, proxyType) - return - } - - // array of predefined type - g.printf("\n pub fn get_%s(&self, index: i32) -> Sc%s {\n", snake(field.Type), proxyType) - g.printf(" Sc%s::new(self.obj_id, Key32(index))\n", proxyType) - g.printf(" }\n") -} - -func (g *RustGenerator) generateProxyArrayNewType(field *Field, proxyType string) { - for _, subtype := range g.s.Typedefs { - if subtype.Name != field.Type { - continue - } - varType := rustTypeMap - if subtype.Array { - varType = rustTypeIds[subtype.Type] - if varType == "" { - varType = rustTypeBytes - } - varType = g.generateArrayType(varType) - } - g.printf("\n pub fn get_%s(&self, index: i32) -> %s {\n", snake(field.Type), proxyType) - g.printf(" let sub_id = get_object_id(self.obj_id, Key32(index), %s)\n", varType) - g.printf(" %s { obj_id: sub_id }\n", proxyType) - g.printf(" }\n") - return - } - - g.printf("\n pub fn get_%s(&self, index: i32) -> %s {\n", snake(field.Type), proxyType) - g.printf(" %s { obj_id: self.obj_id, key_id: Key32(index) }\n", proxyType) - g.printf(" }\n") -} - -func (g *RustGenerator) generateProxyMap(field *Field, mutability, mapType, proxyType string) { - keyType := rustKeyTypes[field.MapKey] - keyValue := rustKeys[field.MapKey] - - g.printf("\npub struct %s {\n", mapType) - g.printf(" pub(crate) obj_id: i32,\n") - g.printf("}\n") - - g.printf("\nimpl %s {", mapType) - defer g.printf("}\n") - - if mutability == PropMutable { - g.printf("\n pub fn clear(&self) {\n") - g.printf(" clear(self.obj_id)\n") - g.printf(" }\n") - } - - if field.TypeID == 0 { - g.generateProxyMapNewType(field, proxyType, keyType, keyValue) - return - } - - // map of predefined type - g.printf("\n pub fn get_%s(&self, key: %s) -> Sc%s {\n", snake(field.Type), keyType, proxyType) - g.printf(" Sc%s::new(self.obj_id, %s.get_key_id())\n", proxyType, keyValue) - g.printf(" }\n") -} - -func (g *RustGenerator) generateProxyMapNewType(field *Field, proxyType, keyType, keyValue string) { - for _, subtype := range g.s.Typedefs { - if subtype.Name != field.Type { - continue - } - varType := rustTypeMap - if subtype.Array { - varType = rustTypeIds[subtype.Type] - if varType == "" { - varType = rustTypeBytes - } - varType = g.generateArrayType(varType) - } - g.printf("\n pub fn get_%s(&self, key: %s) -> %s {\n", snake(field.Type), keyType, proxyType) - g.printf(" let sub_id = get_object_id(self.obj_id, %s.get_key_id(), %s);\n", keyValue, varType) - g.printf(" %s { obj_id: sub_id }\n", proxyType) - g.printf(" }\n") - return - } - - g.printf("\n pub fn get_%s(&self, key: %s) -> %s {\n", snake(field.Type), keyType, proxyType) - g.printf(" %s { obj_id: self.obj_id, key_id: %s.get_key_id() }\n", proxyType, keyValue) - g.printf(" }\n") -} - -func (g *RustGenerator) generateProxyReference(field *Field, mutability, typeName string) { - if field.Name[0] >= 'A' && field.Name[0] <= 'Z' { - g.printf("\npub type %s%s = %s;\n", mutability, field.Name, typeName) - } -} - -func (g *RustGenerator) generateProxyStruct(fields []*Field, mutability, typeName, kind string) { - typeName = mutability + typeName + kind - kind = strings.TrimSuffix(kind, "s") - kind = upper(kind) + "_" - - // first generate necessary array and map types - for _, field := range fields { - g.generateProxy(field, mutability) - } - - g.printf("\n#[derive(Clone, Copy)]\n") - g.printf("pub struct %s {\n", typeName) - g.printf(" pub(crate) id: i32,\n") - g.printf("}\n") - - if len(fields) != 0 { - g.printf("\nimpl %s {", typeName) - defer g.printf("}\n") - } - - for _, field := range fields { - varName := snake(field.Name) - varID := "idx_map(IDX_" + kind + upper(varName) + ")" - if g.s.CoreContracts { - varID = kind + upper(varName) + ".get_key_id()" - } - varType := rustTypeIds[field.Type] - if varType == "" { - varType = rustTypeBytes - } - if field.Array { - varType = g.generateArrayType(varType) - arrayType := "ArrayOf" + mutability + field.Type - g.printf("\n pub fn %s(&self) -> %s {\n", varName, arrayType) - g.printf(" let arr_id = get_object_id(self.id, %s, %s);\n", varID, varType) - g.printf(" %s { obj_id: arr_id }\n", arrayType) - g.printf(" }\n") - continue - } - if field.MapKey != "" { - varType = rustTypeMap - mapType := "Map" + field.MapKey + "To" + mutability + field.Type - g.printf("\n pub fn %s(&self) -> %s {\n", varName, mapType) - mapID := "self.id" - if field.Alias != AliasThis { - mapID = "map_id" - g.printf(" let map_id = get_object_id(self.id, %s, %s);\n", varID, varType) - } - g.printf(" %s { obj_id: %s }\n", mapType, mapID) - g.printf(" }\n") - continue - } - - proxyType := mutability + field.Type - if field.TypeID == 0 { - g.printf("\n pub fn %s(&self) -> %s {\n", varName, proxyType) - g.printf(" %s { obj_id: self.id, key_id: %s }\n", proxyType, varID) - g.printf(" }\n") - continue - } - - g.printf("\n pub fn %s(&self) -> Sc%s {\n", varName, proxyType) - g.printf(" Sc%s::new(self.id, %s)\n", proxyType, varID) - g.printf(" }\n") - } -} - -func (g *RustGenerator) generateStruct(typeDef *Struct) { - nameLen, typeLen := calculatePadding(typeDef.Fields, rustTypes, true) - - g.printf("\npub struct %s {\n", typeDef.Name) - for _, field := range typeDef.Fields { - fldName := pad(snake(field.Name)+":", nameLen+1) - fldType := rustTypes[field.Type] + "," - if field.Comment != "" { - fldType = pad(fldType, typeLen+1) - } - g.printf(" pub %s %s%s\n", fldName, fldType, field.Comment) - } - g.printf("}\n") - - // write encoder and decoder for struct - g.printf("\nimpl %s {", typeDef.Name) - - g.printf("\n pub fn from_bytes(bytes: &[u8]) -> %s {\n", typeDef.Name) - g.printf(" let mut decode = BytesDecoder::new(bytes);\n") - g.printf(" %s {\n", typeDef.Name) - for _, field := range typeDef.Fields { - name := snake(field.Name) - g.printf(" %s: decode.%s(),\n", name, snake(field.Type)) - } - g.printf(" }\n") - g.printf(" }\n") - - g.printf("\n pub fn to_bytes(&self) -> Vec {\n") - g.printf(" let mut encode = BytesEncoder::new();\n") - for _, field := range typeDef.Fields { - name := snake(field.Name) - ref := "&" - if field.Type == "Hname" || field.Type == "Int64" || field.Type == "Int32" || field.Type == "Int16" { - ref = "" - } - g.printf(" encode.%s(%sself.%s);\n", snake(field.Type), ref, name) - } - g.printf(" return encode.data();\n") - g.printf(" }\n") - g.printf("}\n") - - g.generateStructProxy(typeDef, false) - g.generateStructProxy(typeDef, true) -} - -func (g *RustGenerator) generateStructProxy(typeDef *Struct, mutable bool) { - typeName := PropImmutable + typeDef.Name - if mutable { - typeName = PropMutable + typeDef.Name - } - - g.printf("\npub struct %s {\n", typeName) - g.printf(" pub(crate) obj_id: i32,\n") - g.printf(" pub(crate) key_id: Key32,\n") - g.printf("}\n") - - g.printf("\nimpl %s {", typeName) - - g.printf("\n pub fn exists(&self) -> bool {\n") - g.printf(" exists(self.obj_id, self.key_id, TYPE_BYTES)\n") - g.printf(" }\n") - - if mutable { - g.printf("\n pub fn set_value(&self, value: &%s) {\n", typeDef.Name) - g.printf(" set_bytes(self.obj_id, self.key_id, TYPE_BYTES, &value.to_bytes());\n") - g.printf(" }\n") - } - - g.printf("\n pub fn value(&self) -> %s {\n", typeDef.Name) - g.printf(" %s::from_bytes(&get_bytes(self.obj_id, self.key_id, TYPE_BYTES))\n", typeDef.Name) - g.printf(" }\n") - - g.printf("}\n") -} - -func (g *RustGenerator) generateThunk(f *Func) { - nameLen := f.nameLen(5) + 1 - mutability := PropMutable - if f.Kind == KindView { - mutability = PropImmutable - } - g.printf("\npub struct %sContext {\n", f.Type) - if len(f.Params) != 0 { - g.printf(" %s Immutable%sParams,\n", pad("params:", nameLen), f.Type) - } - if len(f.Results) != 0 { - g.printf(" results: Mutable%sResults,\n", f.Type) - } - g.printf(" %s %s%sState,\n", pad("state:", nameLen), mutability, g.s.FullName) - g.printf("}\n") - - g.printf("\nfn %s_thunk(ctx: &Sc%sContext) {\n", g.funcName(f), f.Kind) - g.printf(" ctx.log(\"%s.%s\");\n", g.s.Name, f.FuncName) - - if f.Access != "" { - g.generateThunkAccessCheck(f) - } - - g.printf(" let f = %sContext {\n", f.Type) - - if len(f.Params) != 0 { - g.printf(" params: Immutable%sParams {\n", f.Type) - g.printf(" id: OBJ_ID_PARAMS,\n") - g.printf(" },\n") - } - - if len(f.Results) != 0 { - g.printf(" results: Mutable%sResults {\n", f.Type) - g.printf(" id: OBJ_ID_RESULTS,\n") - g.printf(" },\n") - } - - g.printf(" state: %s%sState {\n", mutability, g.s.FullName) - g.printf(" id: OBJ_ID_STATE,\n") - g.printf(" },\n") - - g.printf(" };\n") - - for _, param := range f.Params { - if !param.Optional { - name := snake(param.Name) - g.printf(" ctx.require(f.params.%s().exists(), \"missing mandatory %s\");\n", name, param.Name) - } - } - - g.printf(" %s(ctx, &f);\n", g.funcName(f)) - g.printf(" ctx.log(\"%s.%s ok\");\n", g.s.Name, f.FuncName) - g.printf("}\n") -} - -func (g *RustGenerator) generateThunkAccessCheck(f *Func) { - grant := f.Access - index := strings.Index(grant, "//") - if index >= 0 { - g.printf(" %s\n", grant[index:]) - grant = strings.TrimSpace(grant[:index]) - } - switch grant { - case AccessSelf: - grant = "ctx.account_id()" - case AccessChain: - grant = "ctx.chain_owner_id()" - case AccessCreator: - grant = "ctx.contract_creator()" - default: - g.printf(" let access = ctx.state().get_agent_id(\"%s\");\n", grant) - g.printf(" ctx.require(access.exists(), \"access not set: %s\");\n", grant) - grant = "access.value()" - } - g.printf(" ctx.require(ctx.caller() == %s, \"no permission\");\n\n", grant) -} - -func (g *RustGenerator) writeConsts() { - g.formatter(false) - g.println(allowDeadCode) - g.println() - g.println(g.crateOrWasmLib(false, false)) - - scName := g.s.Name - if g.s.CoreContracts { - // remove 'core' prefix - scName = scName[4:] - } - g.s.appendConst("SC_NAME", "&str = \""+scName+"\"") - if g.s.Description != "" { - g.s.appendConst("SC_DESCRIPTION", "&str = \""+g.s.Description+"\"") - } - hName := iscp.Hn(scName) - g.s.appendConst("HSC_NAME", "ScHname = ScHname(0x"+hName.String()+")") - g.flushConsts(false) - - g.generateConstsFields(g.s.Params, "PARAM_") - g.generateConstsFields(g.s.Results, "RESULT_") - g.generateConstsFields(g.s.StateVars, "STATE_") - - if len(g.s.Funcs) != 0 { - for _, f := range g.s.Funcs { - constName := upper(g.funcName(f)) - g.s.appendConst(constName, "&str = \""+f.String+"\"") - } - g.flushConsts(g.s.CoreContracts) - - for _, f := range g.s.Funcs { - constHname := "H" + upper(g.funcName(f)) - g.s.appendConst(constHname, "ScHname = ScHname(0x"+f.Hname.String()+")") - } - g.flushConsts(g.s.CoreContracts) - } - - g.formatter(true) -} - -func (g *RustGenerator) writeContract() { - g.formatter(false) - g.println(allowDeadCode) - g.println() - g.println(useStdPtr) - g.println() - g.println(g.crateOrWasmLib(true, false)) - if !g.s.CoreContracts { - g.println() - g.println(useConsts) - if len(g.s.Params) != 0 { - g.println(useParams) - } - if len(g.s.Results) != 0 { - g.println(useResults) - } - } - - for _, f := range g.s.Funcs { - nameLen := f.nameLen(4) + 1 - kind := f.Kind - if f.Type == InitFunc { - kind = f.Type + f.Kind - } - g.printf("\npub struct %sCall {\n", f.Type) - g.printf(" pub %s Sc%s,\n", pad("func:", nameLen), kind) - if len(f.Params) != 0 { - g.printf(" pub %s Mutable%sParams,\n", pad("params:", nameLen), f.Type) - } - if len(f.Results) != 0 { - g.printf(" pub results: Immutable%sResults,\n", f.Type) - } - g.printf("}\n") - } - - g.generateContractFuncs() - g.formatter(true) -} - -func (g *RustGenerator) writeInitialFuncs() { - g.println(useWasmLib) - g.println() - g.println(useCrate) - if len(g.s.Structs) != 0 { - g.println(useStructs) - } - if len(g.s.Typedefs) != 0 { - g.println(useTypeDefs) - } - - for _, f := range g.s.Funcs { - g.generateFuncSignature(f) - } -} - -func (g *RustGenerator) writeKeys() { - g.formatter(false) - g.println(allowDeadCode) - g.println() - g.println(useWasmLib) - g.println() - g.println(useCrate) - - g.s.KeyID = 0 - g.generateKeysIndexes(g.s.Params, "PARAM_") - g.generateKeysIndexes(g.s.Results, "RESULT_") - g.generateKeysIndexes(g.s.StateVars, "STATE_") - g.flushConsts(true) - - size := g.s.KeyID - g.printf("\npub const KEY_MAP_LEN: usize = %d;\n", size) - g.printf("\npub const KEY_MAP: [&str; KEY_MAP_LEN] = [\n") - g.generateKeysArray(g.s.Params, "PARAM_") - g.generateKeysArray(g.s.Results, "RESULT_") - g.generateKeysArray(g.s.StateVars, "STATE_") - g.printf("];\n") - - g.printf("\npub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN];\n") - - g.printf("\npub fn idx_map(idx: usize) -> Key32 {\n") - g.printf(" unsafe {\n") - g.printf(" IDX_MAP[idx]\n") - g.printf(" }\n") - g.printf("}\n") - - g.formatter(true) -} - -func (g *RustGenerator) writeLib() { - g.formatter(false) - g.println(allowDeadCode) - g.println(allowUnusedImports) - g.println() - g.printf("use %s::*;\n", g.s.Name) - g.println(useWasmLib) - g.println(useWasmLibHost) - g.println() - g.println(useConsts) - g.println(useKeys) - if len(g.s.Params) != 0 { - g.println(useParams) - } - if len(g.s.Results) != 0 { - g.println(useResults) - } - g.println(useState) - g.println() - - g.println("mod consts;") - g.println("mod contract;") - g.println("mod keys;") - if len(g.s.Params) != 0 { - g.println("mod params;") - } - if len(g.s.Results) != 0 { - g.println("mod results;") - } - g.println("mod state;") - if len(g.s.Structs) != 0 { - g.println("mod structs;") - } - if len(g.s.Typedefs) != 0 { - g.println("mod typedefs;") - } - g.printf("mod %s;\n", g.s.Name) - - g.println("\n#[no_mangle]") - g.println("fn on_load() {") - if len(g.s.Funcs) != 0 { - g.printf(" let exports = ScExports::new();\n") - } - for _, f := range g.s.Funcs { - name := g.funcName(f) - g.printf(" exports.add_%s(%s, %s_thunk);\n", lower(f.Kind), upper(name), name) - } - - g.printf("\n unsafe {\n") - g.printf(" for i in 0..KEY_MAP_LEN {\n") - g.printf(" IDX_MAP[i] = get_key_id_from_string(KEY_MAP[i]);\n") - g.printf(" }\n") - g.printf(" }\n") - - g.printf("}\n") - - // generate parameter structs and thunks to set up and check parameters - for _, f := range g.s.Funcs { - g.generateThunk(f) - } - - g.formatter(true) -} - -func (g *RustGenerator) writeParams() { - g.println(allowDeadCode) - g.println(allowUnusedImports) - g.println() - g.println(g.crateOrWasmLib(true, true)) - if !g.s.CoreContracts { - g.println() - g.println(useCrate) - g.println(useKeys) - } - - for _, f := range g.s.Funcs { - if len(f.Params) == 0 { - continue - } - g.generateProxyStruct(f.Params, PropImmutable, f.Type, "Params") - g.generateProxyStruct(f.Params, PropMutable, f.Type, "Params") - } -} - -func (g *RustGenerator) writeResults() { - g.println(allowDeadCode) - g.println(allowUnusedImports) - g.println() - g.println(g.crateOrWasmLib(true, true)) - if !g.s.CoreContracts { - g.println() - g.println(useCrate) - g.println(useKeys) - if len(g.s.Structs) != 0 { - g.println(useStructs) - } - } - - for _, f := range g.s.Funcs { - if len(f.Results) == 0 { - continue - } - g.generateProxyStruct(f.Results, PropImmutable, f.Type, "Results") - g.generateProxyStruct(f.Results, PropMutable, f.Type, "Results") - } -} - -func (g *RustGenerator) writeSpecialCargoToml() error { - err := g.exists("Cargo.toml") - if err == nil { - // already exists - return nil - } - - err = g.create("Cargo.toml") +func (g *RustGenerator) Generate() error { + err := g.generateCommonFiles() if err != nil { return err } - defer g.close() - g.printf("[package]\n") - g.printf("name = \"%s\"\n", g.s.Name) - g.printf("description = \"%s\"\n", g.s.Description) - g.printf("license = \"Apache-2.0\"\n") - g.printf("version = \"0.1.0\"\n") - g.printf("authors = [\"John Doe \"]\n") - g.printf("edition = \"2018\"\n") - g.printf("repository = \"https://%s\"\n", ModuleName) - g.printf("\n[lib]\n") - g.printf("crate-type = [\"cdylib\", \"rlib\"]\n") - g.printf("\n[features]\n") - g.printf("default = [\"console_error_panic_hook\"]\n") - g.printf("\n[dependencies]\n") - g.printf("wasmlib = { git = \"https://github.com/iotaledger/wasp\", branch = \"develop\" }\n") - g.printf("console_error_panic_hook = { version = \"0.1.6\", optional = true }\n") - g.printf("wee_alloc = { version = \"0.4.5\", optional = true }\n") - g.printf("\n[dev-dependencies]\n") - g.printf("wasm-bindgen-test = \"0.3.13\"\n") - - return nil -} + // now generate language-specific files -func (g *RustGenerator) writeSpecialMod() { - g.println(allowUnusedImports) - g.generateModLines("pub use %s::*;\n") - g.generateModLines("pub mod %s;\n") -} - -func (g *RustGenerator) writeState() { - g.println(allowDeadCode) - g.println(allowUnusedImports) - g.println() - g.println(useWasmLib) - g.println(useWasmLibHost) - g.println() - g.println(useCrate) - g.println(useKeys) - if len(g.s.Structs) != 0 { - g.println(useStructs) - } - if len(g.s.Typedefs) != 0 { - g.println(useTypeDefs) - } - - g.generateProxyStruct(g.s.StateVars, PropImmutable, g.s.FullName, "State") - g.generateProxyStruct(g.s.StateVars, PropMutable, g.s.FullName, "State") -} - -func (g *RustGenerator) writeStructs() { - g.formatter(false) - g.println(allowDeadCode) - g.println() - g.println(useWasmLib) - g.println(useWasmLibHost) - - for _, typeDef := range g.s.Structs { - g.generateStruct(typeDef) - } - - g.formatter(true) -} - -func (g *RustGenerator) writeTypeDefs() { - g.formatter(false) - g.println(allowDeadCode) - g.println() - g.println(useWasmLib) - g.println(useWasmLibHost) - if len(g.s.Structs) != 0 { - g.println() - g.println(useStructs) - } - - for _, subtype := range g.s.Typedefs { - g.generateProxy(subtype, PropImmutable) - g.generateProxy(subtype, PropMutable) + if g.s.CoreContracts { + return g.createSourceFile("mod", true) } - g.formatter(true) + cargoToml := "Cargo.toml" + return g.createFile(cargoToml, false, func() { + g.emit(cargoToml) + }) } diff --git a/tools/schema/generator/generator_ts.go b/tools/schema/generator/generator_ts.go index 361fac2732..954ccb82f3 100644 --- a/tools/schema/generator/generator_ts.go +++ b/tools/schema/generator/generator_ts.go @@ -4,731 +4,35 @@ package generator import ( - "regexp" - "strconv" - "strings" - - "github.com/iotaledger/wasp/packages/iscp" -) - -const ( - tsImportSelf = "import * as sc from \"./index\";" - tsImportWasmLib = "import * as wasmlib from \"wasmlib\"" -) - -var tsTypes = StringMap{ - "Address": "wasmlib.ScAddress", - "AgentID": "wasmlib.ScAgentID", - "ChainID": "wasmlib.ScChainID", - "Color": "wasmlib.ScColor", - "Hash": "wasmlib.ScHash", - "Hname": "wasmlib.ScHname", - "Int16": "i16", - "Int32": "i32", - "Int64": "i64", - "RequestID": "wasmlib.ScRequestID", - "String": "string", -} - -var tsInits = StringMap{ - "Address": "new wasmlib.ScAddress()", - "AgentID": "new wasmlib.ScAgentID()", - "ChainID": "new wasmlib.ScChainID()", - "Color": "new wasmlib.ScColor(0)", - "Hash": "new wasmlib.ScHash()", - "Hname": "new wasmlib.ScHname(0)", - "Int16": "0", - "Int32": "0", - "Int64": "0", - "RequestID": "new wasmlib.ScRequestID()", - "String": "\"\"", -} - -var tsKeys = StringMap{ - "Address": "key", - "AgentID": "key", - "ChainID": "key", - "Color": "key", - "Hash": "key", - "Hname": "key", - "Int16": "??TODO", - "Int32": "new wasmlib.Key32(key)", - "Int64": "??TODO", - "RequestID": "key", - "String": "wasmlib.Key32.fromString(key)", -} - -var tsTypeIds = StringMap{ - "Address": "wasmlib.TYPE_ADDRESS", - "AgentID": "wasmlib.TYPE_AGENT_ID", - "ChainID": "wasmlib.TYPE_CHAIN_ID", - "Color": "wasmlib.TYPE_COLOR", - "Hash": "wasmlib.TYPE_HASH", - "Hname": "wasmlib.TYPE_HNAME", - "Int16": "wasmlib.TYPE_INT16", - "Int32": "wasmlib.TYPE_INT32", - "Int64": "wasmlib.TYPE_INT64", - "RequestID": "wasmlib.TYPE_REQUEST_ID", - "String": "wasmlib.TYPE_STRING", -} - -const ( - tsTypeBytes = "wasmlib.TYPE_BYTES" - tsTypeMap = "wasmlib.TYPE_MAP" + "github.com/iotaledger/wasp/tools/schema/generator/tstemplates" + "github.com/iotaledger/wasp/tools/schema/model" ) type TypeScriptGenerator struct { GenBase } -func NewTypeScriptGenerator() *TypeScriptGenerator { +func NewTypeScriptGenerator(s *model.Schema) *TypeScriptGenerator { g := &TypeScriptGenerator{} - g.extension = ".ts" - g.funcRegexp = regexp.MustCompile(`^export function (\w+).+$`) - g.language = "TypeScript" - g.rootFolder = "ts" - g.gen = g + g.init(s, tstemplates.TypeDependent, tstemplates.Templates) return g } -func (g *TypeScriptGenerator) flushConsts() { - if len(g.s.ConstNames) == 0 { - return - } - - g.println() - g.s.flushConsts(func(name string, value string, padLen int) { - g.printf("export const %s = %s;\n", pad(name, padLen), value) - }) -} - -func (g *TypeScriptGenerator) funcName(f *Func) string { - return f.FuncName -} - -func (g *TypeScriptGenerator) generateArrayType(varType string) string { - // native core contracts use Array16 instead of our nested array type - if g.s.CoreContracts { - return "wasmlib.TYPE_ARRAY16|" + varType - } - return "wasmlib.TYPE_ARRAY|" + varType -} - -func (g *TypeScriptGenerator) generateConstsFields(fields []*Field, prefix string) { - if len(fields) != 0 { - for _, field := range fields { - if field.Alias == AliasThis { - continue - } - name := prefix + capitalize(field.Name) - value := "\"" + field.Alias + "\"" - g.s.appendConst(name, value) - } - g.flushConsts() - } -} - -func (g *TypeScriptGenerator) generateContractFuncs() { - g.println("\nexport class ScFuncs {") - for _, f := range g.s.Funcs { - g.printf("\n static %s(ctx: wasmlib.Sc%sCallContext): %sCall {\n", uncapitalize(f.Type), f.Kind, f.Type) - g.printf(" let f = new %sCall();\n", f.Type) - - paramsID := "null" - if len(f.Params) != 0 { - paramsID = "f.params" - } - resultsID := "null" - if len(f.Results) != 0 { - resultsID = "f.results" - } - if len(f.Params) != 0 || len(f.Results) != 0 { - g.printf(" f.func.setPtrs(%s, %s);\n", paramsID, resultsID) - } - g.printf(" return f;\n") - g.printf(" }\n") - } - g.printf("}\n") -} - -func (g *TypeScriptGenerator) generateFuncSignature(f *Func) { - g.printf("\nexport function %s(ctx: wasmlib.Sc%sContext, f: sc.%sContext): void {\n", f.FuncName, f.Kind, f.Type) - switch f.FuncName { - case SpecialFuncInit: - g.printf(" if (f.params.owner().exists()) {\n") - g.printf(" f.state.owner().setValue(f.params.owner().value());\n") - g.printf(" return;\n") - g.printf(" }\n") - g.printf(" f.state.owner().setValue(ctx.contractCreator());\n") - case SpecialFuncSetOwner: - g.printf(" f.state.owner().setValue(f.params.owner().value());\n") - case SpecialViewGetOwner: - g.printf(" f.results.owner().setValue(f.state.owner().value());\n") - default: - } - g.printf("}\n") -} - -func (g *TypeScriptGenerator) generateKeysArray(fields []*Field, prefix string) { - for _, field := range fields { - if field.Alias == AliasThis { - continue - } - name := prefix + capitalize(field.Name) - g.printf(" sc.%s,\n", name) - g.s.KeyID++ - } -} - -func (g *TypeScriptGenerator) generateKeysIndexes(fields []*Field, prefix string) { - for _, field := range fields { - if field.Alias == AliasThis { - continue - } - name := "Idx" + prefix + capitalize(field.Name) - field.KeyID = g.s.KeyID - value := strconv.Itoa(field.KeyID) - g.s.KeyID++ - g.s.appendConst(name, value) - } -} - -func (g *TypeScriptGenerator) generateLanguageSpecificFiles() error { - err := g.createSourceFile("index", g.writeSpecialIndex) +func (g *TypeScriptGenerator) Generate() error { + err := g.generateCommonFiles() if err != nil { return err } - return g.writeSpecialConfigJSON() -} - -func (g *TypeScriptGenerator) generateProxyArray(field *Field, mutability, arrayType, proxyType string) { - g.printf("\nexport class %s {\n", arrayType) - g.printf(" objID: i32;\n") - - g.printf("\n constructor(objID: i32) {\n") - g.printf(" this.objID = objID;\n") - g.printf(" }\n") - - if mutability == PropMutable { - g.printf("\n clear(): void {\n") - g.printf(" wasmlib.clear(this.objID);\n") - g.printf(" }\n") - } - - g.printf("\n length(): i32 {\n") - g.printf(" return wasmlib.getLength(this.objID);\n") - g.printf(" }\n") - - if field.TypeID == 0 { - g.generateProxyArrayNewType(field, proxyType) - g.printf("}\n") - return - } - - // array of predefined type - g.printf("\n get%s(index: i32): wasmlib.Sc%s {\n", field.Type, proxyType) - g.printf(" return new wasmlib.Sc%s(this.objID, new wasmlib.Key32(index));\n", proxyType) - g.printf(" }\n") - - g.printf("}\n") -} - -func (g *TypeScriptGenerator) generateProxyArrayNewType(field *Field, proxyType string) { - for _, subtype := range g.s.Typedefs { - if subtype.Name != field.Type { - continue - } - varType := tsTypeMap - if subtype.Array { - varType = tsTypeIds[subtype.Type] - if varType == "" { - varType = tsTypeBytes - } - varType = g.generateArrayType(varType) - } - g.printf("\n get%s(index: i32): sc.%s {\n", field.Type, proxyType) - g.printf(" let subID = wasmlib.getObjectID(this.objID, new wasmlib.Key32(index), %s);\n", varType) - g.printf(" return new sc.%s(subID);\n", proxyType) - g.printf(" }\n") - return - } - - g.printf("\n get%s(index: i32): sc.%s {\n", field.Type, proxyType) - g.printf(" return new sc.%s(this.objID, new wasmlib.Key32(index));\n", proxyType) - g.printf(" }\n") -} -func (g *TypeScriptGenerator) generateProxyMap(field *Field, mutability, mapType, proxyType string) { - keyType := tsTypes[field.MapKey] - keyValue := tsKeys[field.MapKey] + // now generate language-specific files - g.printf("\nexport class %s {\n", mapType) - g.printf(" objID: i32;\n") - - g.printf("\n constructor(objID: i32) {\n") - g.printf(" this.objID = objID;\n") - g.printf(" }\n") - - if mutability == PropMutable { - g.printf("\n clear(): void {\n") - g.printf(" wasmlib.clear(this.objID)\n") - g.printf(" }\n") - } - - if field.TypeID == 0 { - g.generateProxyMapNewType(field, proxyType, keyType, keyValue) - g.printf("}\n") - return - } - - // map of predefined type - g.printf("\n get%s(key: %s): wasmlib.Sc%s {\n", field.Type, keyType, proxyType) - g.printf(" return new wasmlib.Sc%s(this.objID, %s.getKeyID());\n", proxyType, keyValue) - g.printf(" }\n") - - g.printf("}\n") -} - -func (g *TypeScriptGenerator) generateProxyMapNewType(field *Field, proxyType, keyType, keyValue string) { - for _, subtype := range g.s.Typedefs { - if subtype.Name != field.Type { - continue - } - varType := tsTypeMap - if subtype.Array { - varType = tsTypeIds[subtype.Type] - if varType == "" { - varType = tsTypeBytes - } - varType = g.generateArrayType(varType) - } - g.printf("\n get%s(key: %s): sc.%s {\n", field.Type, keyType, proxyType) - g.printf(" let subID = wasmlib.getObjectID(this.objID, %s.getKeyID(), %s);\n", keyValue, varType) - g.printf(" return new sc.%s(subID);\n", proxyType) - g.printf(" }\n") - return - } - - g.printf("\n get%s(key: %s): sc.%s {\n", field.Type, keyType, proxyType) - g.printf(" return new sc.%s(this.objID, %s.getKeyID());\n", proxyType, keyValue) - g.printf(" }\n") -} - -func (g *TypeScriptGenerator) generateProxyReference(field *Field, mutability, typeName string) { - if field.Name[0] >= 'A' && field.Name[0] <= 'Z' { - g.printf("\nexport class %s%s extends %s {\n};\n", mutability, field.Name, typeName) - } -} - -func (g *TypeScriptGenerator) generateProxyStruct(fields []*Field, mutability, typeName, kind string) { - typeName = mutability + typeName + kind - kind = strings.TrimSuffix(kind, "s") - - // first generate necessary array and map types - for _, field := range fields { - g.generateProxy(field, mutability) - } - - g.printf("\nexport class %s extends wasmlib.ScMapID {\n", typeName) - - for _, field := range fields { - varName := field.Name - varID := "sc.idxMap[sc.Idx" + kind + capitalize(varName) + "]" - if g.s.CoreContracts { - varID = "wasmlib.Key32.fromString(sc." + kind + capitalize(varName) + ")" - } - varType := tsTypeIds[field.Type] - if varType == "" { - varType = tsTypeBytes - } - if field.Array { - varType = g.generateArrayType(varType) - arrayType := "ArrayOf" + mutability + field.Type - g.printf("\n %s(): sc.%s {\n", varName, arrayType) - g.printf(" let arrID = wasmlib.getObjectID(this.mapID, %s, %s);\n", varID, varType) - g.printf(" return new sc.%s(arrID)\n", arrayType) - g.printf(" }\n") - continue - } - if field.MapKey != "" { - varType = tsTypeMap - mapType := "Map" + field.MapKey + "To" + mutability + field.Type - g.printf("\n %s(): sc.%s {\n", varName, mapType) - mapID := "this.mapID" - if field.Alias != AliasThis { - mapID = "mapID" - g.printf(" let mapID = wasmlib.getObjectID(this.mapID, %s, %s);\n", varID, varType) - } - g.printf(" return new sc.%s(%s);\n", mapType, mapID) - g.printf(" }\n") - continue - } - - proxyType := mutability + field.Type - if field.TypeID == 0 { - g.printf("\n %s(): sc.%s {\n", varName, proxyType) - g.printf(" return new sc.%s(this.mapID, %s);\n", proxyType, varID) - g.printf(" }\n") - continue - } - - g.printf("\n %s(): wasmlib.Sc%s {\n", varName, proxyType) - g.printf(" return new wasmlib.Sc%s(this.mapID, %s);\n", proxyType, varID) - g.printf(" }\n") - } - g.printf("}\n") -} - -func (g *TypeScriptGenerator) generateStruct(typeDef *Struct) { - nameLen, typeLen := calculatePadding(typeDef.Fields, tsTypes, false) - - g.printf("\nexport class %s {\n", typeDef.Name) - for _, field := range typeDef.Fields { - fldName := pad(field.Name, nameLen) - fldType := tsTypes[field.Type] + " = " + tsInits[field.Type] + ";" - if field.Comment != "" { - fldType = pad(fldType, typeLen) - } - g.printf(" %s: %s%s\n", fldName, fldType, field.Comment) - } - - // write encoder and decoder for struct - g.printf("\n static fromBytes(bytes: u8[]): %s {\n", typeDef.Name) - g.printf(" let decode = new wasmlib.BytesDecoder(bytes);\n") - g.printf(" let data = new %s();\n", typeDef.Name) - for _, field := range typeDef.Fields { - name := field.Name - g.printf(" data.%s = decode.%s();\n", name, uncapitalize(field.Type)) - } - g.printf(" decode.close();\n") - g.printf(" return data;\n }\n") - - g.printf("\n bytes(): u8[] {\n") - g.printf(" return new wasmlib.BytesEncoder().\n") - for _, field := range typeDef.Fields { - name := field.Name - g.printf(" %s(this.%s).\n", uncapitalize(field.Type), name) - } - g.printf(" data();\n }\n") - - g.printf("}\n") - - g.generateStructProxy(typeDef, false) - g.generateStructProxy(typeDef, true) -} - -func (g *TypeScriptGenerator) generateStructProxy(typeDef *Struct, mutable bool) { - typeName := PropImmutable + typeDef.Name - if mutable { - typeName = PropMutable + typeDef.Name - } - - g.printf("\nexport class %s {\n", typeName) - g.printf(" objID: i32;\n") - g.printf(" keyID: wasmlib.Key32;\n") - - g.printf("\n constructor(objID: i32, keyID: wasmlib.Key32) {\n") - g.printf(" this.objID = objID;\n") - g.printf(" this.keyID = keyID;\n") - g.printf(" }\n") - - g.printf("\n exists(): boolean {\n") - g.printf(" return wasmlib.exists(this.objID, this.keyID, wasmlib.TYPE_BYTES);\n") - g.printf(" }\n") - - if mutable { - g.printf("\n setValue(value: %s): void {\n", typeDef.Name) - g.printf(" wasmlib.setBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES, value.bytes());\n") - g.printf(" }\n") - } - - g.printf("\n value(): %s {\n", typeDef.Name) - g.printf(" return %s.fromBytes(wasmlib.getBytes(this.objID, this.keyID,wasmlib. TYPE_BYTES));\n", typeDef.Name) - g.printf(" }\n") - - g.printf("}\n") -} - -func (g *TypeScriptGenerator) generateThunk(f *Func) { - g.printf("\nfunction %sThunk(ctx: wasmlib.Sc%sContext): void {\n", f.FuncName, f.Kind) - g.printf(" ctx.log(\"%s.%s\");\n", g.s.Name, f.FuncName) - - if f.Access != "" { - g.generateThunkAccessCheck(f) - } - - g.printf(" let f = new sc.%sContext();\n", f.Type) - - if len(f.Params) != 0 { - g.printf(" f.params.mapID = wasmlib.OBJ_ID_PARAMS;\n") - } - - if len(f.Results) != 0 { - g.printf(" f.results.mapID = wasmlib.OBJ_ID_RESULTS;\n") - } - - g.printf(" f.state.mapID = wasmlib.OBJ_ID_STATE;\n") - - for _, param := range f.Params { - if !param.Optional { - name := param.Name - g.printf(" ctx.require(f.params.%s().exists(), \"missing mandatory %s\")\n", name, param.Name) - } - } - - g.printf(" sc.%s(ctx, f);\n", f.FuncName) - g.printf(" ctx.log(\"%s.%s ok\");\n", g.s.Name, f.FuncName) - g.printf("}\n") -} - -func (g *TypeScriptGenerator) generateThunkAccessCheck(f *Func) { - grant := f.Access - index := strings.Index(grant, "//") - if index >= 0 { - g.printf(" %s\n", grant[index:]) - grant = strings.TrimSpace(grant[:index]) - } - switch grant { - case AccessSelf: - grant = "ctx.accountID()" - case AccessChain: - grant = "ctx.chainOwnerID()" - case AccessCreator: - grant = "ctx.contractCreator()" - default: - g.printf(" let access = ctx.state().getAgentID(wasmlib.Key32.fromString(\"%s\"));\n", grant) - g.printf(" ctx.require(access.exists(), \"access not set: %s\");\n", grant) - grant = "access.value()" - } - g.printf(" ctx.require(ctx.caller().equals(%s), \"no permission\");\n\n", grant) -} - -func (g *TypeScriptGenerator) writeConsts() { - g.println(tsImportWasmLib) - - scName := g.s.Name - if g.s.CoreContracts { - // remove 'core' prefix - scName = scName[4:] - } - g.s.appendConst("ScName", "\""+scName+"\"") - if g.s.Description != "" { - g.s.appendConst("ScDescription", "\""+g.s.Description+"\"") - } - hName := iscp.Hn(scName) - hNameType := "new wasmlib.ScHname" - g.s.appendConst("HScName", hNameType+"(0x"+hName.String()+")") - g.flushConsts() - - g.generateConstsFields(g.s.Params, "Param") - g.generateConstsFields(g.s.Results, "Result") - g.generateConstsFields(g.s.StateVars, "State") - - if len(g.s.Funcs) != 0 { - for _, f := range g.s.Funcs { - constName := capitalize(f.FuncName) - g.s.appendConst(constName, "\""+f.String+"\"") - } - g.flushConsts() - - for _, f := range g.s.Funcs { - constHname := "H" + capitalize(f.FuncName) - g.s.appendConst(constHname, hNameType+"(0x"+f.Hname.String()+")") - } - g.flushConsts() - } -} - -func (g *TypeScriptGenerator) writeContract() { - g.println(tsImportWasmLib) - g.println(tsImportSelf) - - for _, f := range g.s.Funcs { - kind := f.Kind - if f.Type == InitFunc { - kind = f.Type + f.Kind - } - g.printf("\nexport class %sCall {\n", f.Type) - g.printf(" func: wasmlib.Sc%s = new wasmlib.Sc%s(sc.HScName, sc.H%s%s);\n", kind, kind, f.Kind, f.Type) - if len(f.Params) != 0 { - g.printf(" params: sc.Mutable%sParams = new sc.Mutable%sParams();\n", f.Type, f.Type) - } - if len(f.Results) != 0 { - g.printf(" results: sc.Immutable%sResults = new sc.Immutable%sResults();\n", f.Type, f.Type) - } - g.printf("}\n") - - if !g.s.CoreContracts { - mutability := PropMutable - if f.Kind == KindView { - mutability = PropImmutable - } - g.printf("\nexport class %sContext {\n", f.Type) - if len(f.Params) != 0 { - g.printf(" params: sc.Immutable%sParams = new sc.Immutable%sParams();\n", f.Type, f.Type) - } - if len(f.Results) != 0 { - g.printf(" results: sc.Mutable%sResults = new sc.Mutable%sResults();\n", f.Type, f.Type) - } - g.printf(" state: sc.%s%sState = new sc.%s%sState();\n", mutability, g.s.FullName, mutability, g.s.FullName) - g.printf("}\n") - } - } - - g.generateContractFuncs() -} - -func (g *TypeScriptGenerator) writeInitialFuncs() { - g.println(tsImportWasmLib) - g.println(tsImportSelf) - - for _, f := range g.s.Funcs { - g.generateFuncSignature(f) - } -} - -func (g *TypeScriptGenerator) writeKeys() { - g.println(tsImportWasmLib) - g.println(tsImportSelf) - - g.s.KeyID = 0 - g.generateKeysIndexes(g.s.Params, "Param") - g.generateKeysIndexes(g.s.Results, "Result") - g.generateKeysIndexes(g.s.StateVars, "State") - g.flushConsts() - - g.printf("\nexport let keyMap: string[] = [\n") - g.generateKeysArray(g.s.Params, "Param") - g.generateKeysArray(g.s.Results, "Result") - g.generateKeysArray(g.s.StateVars, "State") - g.printf("];\n") - g.printf("\nexport let idxMap: wasmlib.Key32[] = new Array(keyMap.length);\n") -} - -func (g *TypeScriptGenerator) writeLib() { - g.println(tsImportWasmLib) - g.println(tsImportSelf) - - g.printf("\nexport function on_call(index: i32): void {\n") - g.printf(" return wasmlib.onCall(index);\n") - g.printf("}\n") - - g.printf("\nexport function on_load(): void {\n") - g.printf(" let exports = new wasmlib.ScExports();\n") - for _, f := range g.s.Funcs { - constName := capitalize(f.FuncName) - g.printf(" exports.add%s(sc.%s, %sThunk);\n", f.Kind, constName, f.FuncName) - } - - g.printf("\n for (let i = 0; i < sc.keyMap.length; i++) {\n") - g.printf(" sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]);\n") - g.printf(" }\n") - - g.printf("}\n") - - // generate parameter structs and thunks to set up and check parameters - for _, f := range g.s.Funcs { - g.generateThunk(f) - } -} - -func (g *TypeScriptGenerator) writeParams() { - g.println(tsImportWasmLib) - g.println(tsImportSelf) - - for _, f := range g.s.Funcs { - if len(f.Params) == 0 { - continue - } - g.generateProxyStruct(f.Params, PropImmutable, f.Type, "Params") - g.generateProxyStruct(f.Params, PropMutable, f.Type, "Params") - } -} - -func (g *TypeScriptGenerator) writeResults() { - g.println(tsImportWasmLib) - g.println(tsImportSelf) - - for _, f := range g.s.Funcs { - if len(f.Results) == 0 { - continue - } - g.generateProxyStruct(f.Results, PropImmutable, f.Type, "Results") - g.generateProxyStruct(f.Results, PropMutable, f.Type, "Results") - } -} - -func (g *TypeScriptGenerator) writeSpecialConfigJSON() error { - err := g.exists(g.Folder + "tsconfig.json") - if err == nil { - // already exists - return nil - } - - err = g.create(g.Folder + "tsconfig.json") + err = g.createSourceFile("index", true) if err != nil { return err } - defer g.close() - - g.println("{") - g.println(" \"extends\": \"assemblyscript/std/assembly.json\",") - g.println(" \"include\": [\"./*.ts\"]") - g.println("}") - - return nil -} - -func (g *TypeScriptGenerator) writeSpecialIndex() { - if !g.s.CoreContracts { - g.printf("export * from \"./%s\";\n\n", g.s.Name) - } - - g.println("export * from \"./consts\";") - g.println("export * from \"./contract\";") - if !g.s.CoreContracts { - g.println("export * from \"./keys\";") - g.println("export * from \"./lib\";") - } - if len(g.s.Params) != 0 { - g.println("export * from \"./params\";") - } - if len(g.s.Results) != 0 { - g.println("export * from \"./results\";") - } - if !g.s.CoreContracts { - g.println("export * from \"./state\";") - if len(g.s.Structs) != 0 { - g.println("export * from \"./structs\";") - } - if len(g.s.Typedefs) != 0 { - g.println("export * from \"./typedefs\";") - } - } -} - -func (g *TypeScriptGenerator) writeState() { - g.println(tsImportWasmLib) - g.println(tsImportSelf) - - g.generateProxyStruct(g.s.StateVars, PropImmutable, g.s.FullName, "State") - g.generateProxyStruct(g.s.StateVars, PropMutable, g.s.FullName, "State") -} - -func (g *TypeScriptGenerator) writeStructs() { - g.println(tsImportWasmLib) - for _, typeDef := range g.s.Structs { - g.generateStruct(typeDef) - } -} - -func (g *TypeScriptGenerator) writeTypeDefs() { - g.println(tsImportWasmLib) - g.println(tsImportSelf) - - for _, subtype := range g.s.Typedefs { - g.generateProxy(subtype, PropImmutable) - g.generateProxy(subtype, PropMutable) - } + tsconfig := "tsconfig.json" + return g.createFile(g.folder+tsconfig, false, func() { + g.emit(tsconfig) + }) } diff --git a/tools/schema/generator/gotemplates/alltemplates.go b/tools/schema/generator/gotemplates/alltemplates.go new file mode 100644 index 0000000000..f4d0fd736b --- /dev/null +++ b/tools/schema/generator/gotemplates/alltemplates.go @@ -0,0 +1,124 @@ +package gotemplates + +import "github.com/iotaledger/wasp/tools/schema/model" + +var config = map[string]string{ + "language": "Go", + "extension": ".go", + "rootFolder": "go", + "funcRegexp": `^func (\w+).+$`, +} + +var Templates = []map[string]string{ + config, + common, + constsGo, + contractGo, + eventsGo, + funcsGo, + keysGo, + libGo, + mainGo, + paramsGo, + proxyGo, + resultsGo, + stateGo, + structsGo, + typedefsGo, +} + +var TypeDependent = model.StringMapMap{ + "fldLangType": { + "Address": "wasmlib.ScAddress", + "AgentID": "wasmlib.ScAgentID", + "Bool": "bool", + "ChainID": "wasmlib.ScChainID", + "Color": "wasmlib.ScColor", + "Hash": "wasmlib.ScHash", + "Hname": "wasmlib.ScHname", + "Int8": "int8", + "Int16": "int16", + "Int32": "int32", + "Int64": "int64", + "RequestID": "wasmlib.ScRequestID", + "String": "string", + "Uint8": "uint8", + "Uint16": "uint16", + "Uint32": "uint32", + "Uint64": "uint64", + }, + "fldTypeID": { + "Address": "wasmlib.TYPE_ADDRESS", + "AgentID": "wasmlib.TYPE_AGENT_ID", + "Bool": "wasmlib.TYPE_BOOL", + "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", + }, + "fldToKey32": { + "Address": "key.KeyID()", + "AgentID": "key.KeyID()", + "Bool": "???cannot use Bool as map key", + "ChainID": "key.KeyID()", + "Color": "key.KeyID()", + "Hash": "key.KeyID()", + "Hname": "key.KeyID()", + "Int8": "wasmlib.GetKeyIDFromUint64(uint64(key), 1)", + "Int16": "wasmlib.GetKeyIDFromUint64(uint64(key), 2)", + "Int32": "wasmlib.GetKeyIDFromUint64(uint64(key), 4)", + "Int64": "wasmlib.GetKeyIDFromUint64(uint64(key), 8)", + "RequestID": "key.KeyID()", + "String": "wasmlib.Key(key).KeyID()", + "Uint8": "wasmlib.GetKeyIDFromUint64(uint64(key), 1)", + "Uint16": "wasmlib.GetKeyIDFromUint64(uint64(key), 2)", + "Uint32": "wasmlib.GetKeyIDFromUint64(uint64(key), 4)", + "Uint64": "wasmlib.GetKeyIDFromUint64(key, 8)", + }, +} + +var common = map[string]string{ + // ******************************* + "initGlobals": ` +$#set arrayTypeID wasmlib.TYPE_ARRAY +$#if core setArrayTypeID +`, + // ******************************* + "setArrayTypeID": ` +$#set arrayTypeID wasmlib.TYPE_ARRAY16 +`, + // ******************************* + "goPackage": ` +package $package +`, + // ******************************* + "importWasmLib": ` + +import "github.com/iotaledger/wasp/packages/vm/wasmlib/go/wasmlib" +`, + // ******************************* + "goHeader": ` +$#emit goPackage +$#emit importWasmLib +`, + // ******************************* + "setVarType": ` +$#set varType wasmlib.TYPE_MAP +$#if array setVarTypeArray +`, + // ******************************* + "setVarTypeArray": ` +$#set varType $arrayTypeID|$fldTypeID +`, +} diff --git a/tools/schema/generator/gotemplates/consts.go b/tools/schema/generator/gotemplates/consts.go new file mode 100644 index 0000000000..ac7d6e350c --- /dev/null +++ b/tools/schema/generator/gotemplates/consts.go @@ -0,0 +1,61 @@ +package gotemplates + +var constsGo = map[string]string{ + // ******************************* + "consts.go": ` +$#emit goHeader + +const ( + ScName = "$scName" + ScDescription = "$scDesc" + HScName = wasmlib.ScHname(0x$hscName) +) +$#if params constParams +$#if results constResults +$#if state constState + +const ( +$#each func constFunc +) + +const ( +$#each func constHFunc +) +`, + // ******************************* + "constParams": ` + +const ( +$#set constPrefix Param +$#each params constField +) +`, + // ******************************* + "constResults": ` + +const ( +$#set constPrefix Result +$#each results constField +) +`, + // ******************************* + "constState": ` + +const ( +$#set constPrefix State +$#each state constField +) +`, + // ******************************* + "constField": ` + $constPrefix$FldName$fldPad = "$fldAlias" +`, + // ******************************* + "constFunc": ` + $Kind$FuncName$funcPad = "$funcName" +`, + // ******************************* + "constHFunc": ` + H$Kind$FuncName$funcPad = wasmlib.ScHname(0x$funcHname) +`, +} diff --git a/tools/schema/generator/gotemplates/contract.go b/tools/schema/generator/gotemplates/contract.go new file mode 100644 index 0000000000..773be9aeec --- /dev/null +++ b/tools/schema/generator/gotemplates/contract.go @@ -0,0 +1,75 @@ +package gotemplates + +var contractGo = map[string]string{ + // ******************************* + "contract.go": ` +$#emit goHeader +$#each func FuncNameCall + +type Funcs struct{} + +var ScFuncs Funcs +$#each func FuncNameForCall +$#if core coreOnload +`, + // ******************************* + "FuncNameCall": ` +$#emit setupInitFunc + +type $FuncName$+Call struct { + Func *wasmlib.Sc$initFunc$Kind +$#if param MutableFuncNameParams +$#if result ImmutableFuncNameResults +} +`, + // ******************************* + "MutableFuncNameParams": ` + Params Mutable$FuncName$+Params +`, + // ******************************* + "ImmutableFuncNameResults": ` + Results Immutable$FuncName$+Results +`, + // ******************************* + "FuncNameForCall": ` +$#emit setupInitFunc + +func (sc Funcs) $FuncName(ctx wasmlib.Sc$Kind$+CallContext) *$FuncName$+Call { +$#set paramsID nil +$#set resultsID nil +$#if param setParamsID +$#if result setResultsID +$#if ptrs setPtrs noPtrs +} +`, + // ******************************* + "coreOnload": ` + +func OnLoad() { + exports := wasmlib.NewScExports() +$#each func coreExportFunc +} +`, + // ******************************* + "coreExportFunc": ` + exports.Add$Kind($Kind$FuncName, wasmlib.$Kind$+Error) +`, + // ******************************* + "setPtrs": ` + f := &$FuncName$+Call{Func: wasmlib.NewSc$initFunc$Kind(ctx, HScName, H$Kind$FuncName$initMap)} + f.Func.SetPtrs($paramsID, $resultsID) + return f +`, + // ******************************* + "setParamsID": ` +$#set paramsID &f.Params.id +`, + // ******************************* + "setResultsID": ` +$#set resultsID &f.Results.id +`, + // ******************************* + "noPtrs": ` + return &$FuncName$+Call{Func: wasmlib.NewSc$initFunc$Kind(ctx, HScName, H$Kind$FuncName$initMap)} +`, +} diff --git a/tools/schema/generator/gotemplates/events.go b/tools/schema/generator/gotemplates/events.go new file mode 100644 index 0000000000..a52a60fb7b --- /dev/null +++ b/tools/schema/generator/gotemplates/events.go @@ -0,0 +1,35 @@ +package gotemplates + +var eventsGo = map[string]string{ + // ******************************* + "events.go": ` +//nolint:gocritic +$#emit goHeader + +$#set TypeName $Package$+Events +type $TypeName struct { +} +$#each events eventFunc +`, + // ******************************* + "eventFunc": ` +$#set params +$#set separator +$#each event eventParam + +func (e $TypeName) $EvtName($params) { + wasmlib.NewEventEncoder("$package.$evtName"). +$#each event eventEmit + Emit() +} +`, + // ******************************* + "eventParam": ` +$#set params $params$separator$fldName $fldLangType +$#set separator , +`, + // ******************************* + "eventEmit": ` + $FldType($fldName). +`, +} diff --git a/tools/schema/generator/gotemplates/funcs.go b/tools/schema/generator/gotemplates/funcs.go new file mode 100644 index 0000000000..e235163ff6 --- /dev/null +++ b/tools/schema/generator/gotemplates/funcs.go @@ -0,0 +1,32 @@ +package gotemplates + +var funcsGo = map[string]string{ + // ******************************* + "funcs.go": ` +$#emit goHeader +$#each func funcSignature +`, + // ******************************* + "funcSignature": ` + +func $kind$FuncName(ctx wasmlib.Sc$Kind$+Context, f *$FuncName$+Context) { +$#emit init$Kind$FuncName +} +`, + // ******************************* + "initFuncInit": ` + if f.Params.Owner().Exists() { + f.State.Owner().SetValue(f.Params.Owner().Value()) + return + } + f.State.Owner().SetValue(ctx.ContractCreator()) +`, + // ******************************* + "initFuncSetOwner": ` + f.State.Owner().SetValue(f.Params.Owner().Value()) +`, + // ******************************* + "initViewGetOwner": ` + f.Results.Owner().SetValue(f.State.Owner().Value()) +`, +} diff --git a/tools/schema/generator/gotemplates/keys.go b/tools/schema/generator/gotemplates/keys.go new file mode 100644 index 0000000000..e8528d83bc --- /dev/null +++ b/tools/schema/generator/gotemplates/keys.go @@ -0,0 +1,40 @@ +package gotemplates + +var keysGo = map[string]string{ + // ******************************* + "keys.go": ` +$#emit goHeader + +const ( +$#set constPrefix Param +$#each params constFieldIdx + +$#set constPrefix Result +$#each results constFieldIdx + +$#set constPrefix State +$#each state constFieldIdx +) + +const keyMapLen = $maxIndex + +var keyMap = [keyMapLen]wasmlib.Key{ +$#set constPrefix Param +$#each params constFieldKey +$#set constPrefix Result +$#each results constFieldKey +$#set constPrefix State +$#each state constFieldKey +} + +var idxMap [keyMapLen]wasmlib.Key32 +`, + // ******************************* + "constFieldIdx": ` + Idx$constPrefix$FldName$fldPad = $fldIndex +`, + // ******************************* + "constFieldKey": ` + $constPrefix$FldName, +`, +} diff --git a/tools/schema/generator/gotemplates/lib.go b/tools/schema/generator/gotemplates/lib.go new file mode 100644 index 0000000000..ec5822463c --- /dev/null +++ b/tools/schema/generator/gotemplates/lib.go @@ -0,0 +1,148 @@ +package gotemplates + +var libGo = map[string]string{ + // ******************************* + "lib.go": ` +//nolint:dupl +$#emit goHeader + +func OnLoad() { + exports := wasmlib.NewScExports() +$#each func libExportFunc + + for i, key := range keyMap { + idxMap[i] = key.KeyID() + } +} +$#each func libThunk +`, + // ******************************* + "libExportFunc": ` + exports.Add$Kind($Kind$FuncName,$funcPad $kind$FuncName$+Thunk) +`, + // ******************************* + "libThunk": ` + +type $FuncName$+Context struct { +$#if func PackageEvents +$#if param ImmutableFuncNameParams +$#if result MutableFuncNameResults +$#if func MutablePackageState +$#if view ImmutablePackageState +} + +func $kind$FuncName$+Thunk(ctx wasmlib.Sc$Kind$+Context) { + ctx.Log("$package.$kind$FuncName") +$#emit accessCheck + f := &$FuncName$+Context{ +$#if param ImmutableFuncNameParamsInit +$#if result MutableFuncNameResultsInit +$#if func MutablePackageStateInit +$#if view ImmutablePackageStateInit + } +$#each mandatory requireMandatory + $kind$FuncName(ctx, f) + ctx.Log("$package.$kind$FuncName ok") +} +`, + // ******************************* + "PackageEvents": ` +$#if events PackageEventsExist +`, + // ******************************* + "PackageEventsExist": ` + Events $Package$+Events +`, + // ******************************* + "ImmutableFuncNameParams": ` + Params Immutable$FuncName$+Params +`, + // ******************************* + "ImmutableFuncNameParamsInit": ` + Params: Immutable$FuncName$+Params{ + id: wasmlib.OBJ_ID_PARAMS, + }, +`, + // ******************************* + "MutableFuncNameResults": ` + Results Mutable$FuncName$+Results +`, + // ******************************* + "MutableFuncNameResultsInit": ` + Results: Mutable$FuncName$+Results{ + id: wasmlib.OBJ_ID_RESULTS, + }, +`, + // ******************************* + "MutablePackageState": ` + State Mutable$Package$+State +`, + // ******************************* + "MutablePackageStateInit": ` + State: Mutable$Package$+State{ + id: wasmlib.OBJ_ID_STATE, + }, +`, + // ******************************* + "ImmutablePackageState": ` + State Immutable$Package$+State +`, + // ******************************* + "ImmutablePackageStateInit": ` + State: Immutable$Package$+State{ + id: wasmlib.OBJ_ID_STATE, + }, +`, + // ******************************* + "requireMandatory": ` + ctx.Require(f.Params.$FldName().Exists(), "missing mandatory $fldName") +`, + + // ******************************* + "accessCheck": ` +$#set accessFinalize accessOther +$#emit caseAccess$funcAccess +$#emit $accessFinalize +`, + // ******************************* + "caseAccess": ` +$#set accessFinalize accessDone +`, + // ******************************* + "caseAccessself": ` +$#if funcAccessComment accessComment + ctx.Require(ctx.Caller() == ctx.AccountID(), "no permission") + +$#set accessFinalize accessDone +`, + // ******************************* + "caseAccesschain": ` +$#if funcAccessComment accessComment + ctx.Require(ctx.Caller() == ctx.ChainOwnerID(), "no permission") + +$#set accessFinalize accessDone +`, + // ******************************* + "caseAccesscreator": ` +$#if funcAccessComment accessComment + ctx.Require(ctx.Caller() == ctx.ContractCreator(), "no permission") + +$#set accessFinalize accessDone +`, + // ******************************* + "accessOther": ` +$#if funcAccessComment accessComment + access := ctx.State().GetAgentID(wasmlib.Key("$funcAccess")) + ctx.Require(access.Exists(), "access not set: $funcAccess") + ctx.Require(ctx.Caller() == access.Value(), "no permission") + +`, + // ******************************* + "accessDone": ` +`, + // ******************************* + "accessComment": ` + + $funcAccessComment +`, +} diff --git a/tools/schema/generator/gotemplates/main.go b/tools/schema/generator/gotemplates/main.go new file mode 100644 index 0000000000..e03d43c541 --- /dev/null +++ b/tools/schema/generator/gotemplates/main.go @@ -0,0 +1,24 @@ +package gotemplates + +var mainGo = map[string]string{ + // ******************************* + "../main.go": ` +// +build wasm + +package main + +import "github.com/iotaledger/wasp/packages/vm/wasmclient" + +import "$module/go/$package" + +func main() { +} + +//export on_load +func onLoad() { + h := &wasmclient.WasmVMHost{} + h.ConnectWasmHost() + $package.OnLoad() +} +`, +} diff --git a/tools/schema/generator/gotemplates/params.go b/tools/schema/generator/gotemplates/params.go new file mode 100644 index 0000000000..447ee0580f --- /dev/null +++ b/tools/schema/generator/gotemplates/params.go @@ -0,0 +1,31 @@ +package gotemplates + +var paramsGo = map[string]string{ + // ******************************* + "params.go": ` +$#emit goHeader +$#each func paramsFunc +`, + // ******************************* + "paramsFunc": ` +$#if params paramsFuncParams +`, + // ******************************* + "paramsFuncParams": ` +$#set Kind Param +$#set mut Immutable +$#if param paramsProxyStruct +$#set mut Mutable +$#if param paramsProxyStruct +`, + // ******************************* + "paramsProxyStruct": ` +$#set TypeName $mut$FuncName$+Params +$#each param proxyContainers + +type $TypeName struct { + id int32 +} +$#each param proxyMethods +`, +} diff --git a/tools/schema/generator/gotemplates/proxy.go b/tools/schema/generator/gotemplates/proxy.go new file mode 100644 index 0000000000..4ea6a2f3f0 --- /dev/null +++ b/tools/schema/generator/gotemplates/proxy.go @@ -0,0 +1,81 @@ +package gotemplates + +var proxyGo = map[string]string{ + // ******************************* + "proxyContainers": ` +$#if array typedefProxyArray +$#if map typedefProxyMap +`, + // ******************************* + "proxyMethods": ` +$#set varID idxMap[Idx$Kind$FldName] +$#if core setCoreVarID +$#if array proxyArray proxyMethods2 +`, + // ******************************* + "proxyMethods2": ` +$#if map proxyMap proxyMethods3 +`, + // ******************************* + "proxyMethods3": ` +$#if basetype proxyBaseType proxyMethods4 +`, + // ******************************* + "proxyMethods4": ` +$#if typedef proxyTypeDef proxyStruct +`, + // ******************************* + "setCoreVarID": ` +$#set varID wasmlib.KeyID($Kind$FldName) +`, + // ******************************* + "proxyArray": ` + +func (s $TypeName) $FldName() ArrayOf$mut$FldType { + arrID := wasmlib.GetObjectID(s.id, $varID, $arrayTypeID|$fldTypeID) + return ArrayOf$mut$FldType{objID: arrID} +} +`, + // ******************************* + "proxyMap": ` +$#if this proxyMapThis proxyMapOther +`, + // ******************************* + "proxyMapThis": ` + +func (s $TypeName) $FldName() Map$fldMapKey$+To$mut$FldType { + return Map$fldMapKey$+To$mut$FldType{objID: s.id} +} +`, + // ******************************* + "proxyMapOther": `55544444.0 + +func (s $TypeName) $FldName() Map$fldMapKey$+To$mut$FldType { + mapID := wasmlib.GetObjectID(s.id, $varID, wasmlib.TYPE_MAP) + return Map$fldMapKey$+To$mut$FldType{objID: mapID} +} +`, + // ******************************* + "proxyBaseType": ` + +func (s $TypeName) $FldName() wasmlib.Sc$mut$FldType { + return wasmlib.NewSc$mut$FldType(s.id, $varID) +} +`, + // ******************************* + "proxyTypeDef": ` +$#emit setVarType + +func (s $TypeName) $OldName() $mut$OldType { + subID := wasmlib.GetObjectID(s.id, $varID, $varType) + return $mut$OldType{objID: subID} +} +`, + // ******************************* + "proxyStruct": ` + +func (s $TypeName) $FldName() $mut$FldType { + return $mut$FldType{objID: s.id, keyID: $varID} +} +`, +} diff --git a/tools/schema/generator/gotemplates/results.go b/tools/schema/generator/gotemplates/results.go new file mode 100644 index 0000000000..1b46ecd872 --- /dev/null +++ b/tools/schema/generator/gotemplates/results.go @@ -0,0 +1,31 @@ +package gotemplates + +var resultsGo = map[string]string{ + // ******************************* + "results.go": ` +$#emit goHeader +$#each func resultsFunc +`, + // ******************************* + "resultsFunc": ` +$#if results resultsFuncResults +`, + // ******************************* + "resultsFuncResults": ` +$#set Kind Result +$#set mut Immutable +$#if result resultsProxyStruct +$#set mut Mutable +$#if result resultsProxyStruct +`, + // ******************************* + "resultsProxyStruct": ` +$#set TypeName $mut$FuncName$+Results +$#each result proxyContainers + +type $TypeName struct { + id int32 +} +$#each result proxyMethods +`, +} diff --git a/tools/schema/generator/gotemplates/state.go b/tools/schema/generator/gotemplates/state.go new file mode 100644 index 0000000000..00dbd4163e --- /dev/null +++ b/tools/schema/generator/gotemplates/state.go @@ -0,0 +1,24 @@ +package gotemplates + +var stateGo = map[string]string{ + // ******************************* + "state.go": ` +$#emit goPackage +$#if state importWasmLib +$#set Kind State +$#set mut Immutable +$#emit stateProxyStruct +$#set mut Mutable +$#emit stateProxyStruct +`, + // ******************************* + "stateProxyStruct": ` +$#set TypeName $mut$Package$+State +$#each state proxyContainers + +type $TypeName struct { + id int32 +} +$#each state proxyMethods +`, +} diff --git a/tools/schema/generator/gotemplates/structs.go b/tools/schema/generator/gotemplates/structs.go new file mode 100644 index 0000000000..af2a356a87 --- /dev/null +++ b/tools/schema/generator/gotemplates/structs.go @@ -0,0 +1,78 @@ +package gotemplates + +var structsGo = map[string]string{ + // ******************************* + "structs.go": ` +$#emit goHeader +$#each structs structType +`, + // ******************************* + "structType": ` + +type $StrName struct { +$#each struct structField +} + +func New$StrName$+FromBytes(bytes []byte) *$StrName { + decode := wasmlib.NewBytesDecoder(bytes) + data := &$StrName$+{} +$#each struct structDecode + decode.Close() + return data +} + +func (o *$StrName) Bytes() []byte { + return wasmlib.NewBytesEncoder(). +$#each struct structEncode + Data() +} +$#set mut Immutable +$#emit structMethods +$#set mut Mutable +$#emit structMethods +`, + // ******************************* + "structField": ` + $FldName$fldPad $fldLangType $fldComment +`, + // ******************************* + "structDecode": ` + data.$FldName$fldPad = decode.$FldType() +`, + // ******************************* + "structEncode": ` + $FldType(o.$FldName). +`, + // ******************************* + "structMethods": ` + +type $mut$StrName struct { + objID int32 + keyID wasmlib.Key32 +} +$#if mut structMethodDelete + +func (o $mut$StrName) Exists() bool { + return wasmlib.Exists(o.objID, o.keyID, wasmlib.TYPE_BYTES) +} +$#if mut structMethodSetValue + +func (o $mut$StrName) Value() *$StrName { + return New$StrName$+FromBytes(wasmlib.GetBytes(o.objID, o.keyID, wasmlib.TYPE_BYTES)) +} +`, + // ******************************* + "structMethodDelete": ` + +func (o $mut$StrName) Delete() { + wasmlib.DelKey(o.objID, o.keyID, wasmlib.TYPE_BYTES) +} +`, + // ******************************* + "structMethodSetValue": ` + +func (o $mut$StrName) SetValue(value *$StrName) { + wasmlib.SetBytes(o.objID, o.keyID, wasmlib.TYPE_BYTES, value.Bytes()) +} +`, +} diff --git a/tools/schema/generator/gotemplates/typedefs.go b/tools/schema/generator/gotemplates/typedefs.go new file mode 100644 index 0000000000..ed5fcb42e9 --- /dev/null +++ b/tools/schema/generator/gotemplates/typedefs.go @@ -0,0 +1,129 @@ +package gotemplates + +var typedefsGo = map[string]string{ + // ******************************* + "typedefs.go": ` +$#emit goHeader +$#each typedef typedefProxy +`, + // ******************************* + "typedefProxy": ` +$#set mut Immutable +$#if array typedefProxyArray +$#if array typedefProxyAlias +$#if map typedefProxyMap +$#if map typedefProxyAlias +$#set mut Mutable +$#if array typedefProxyArray +$#if array typedefProxyAlias +$#if map typedefProxyMap +$#if map typedefProxyAlias +`, + // ******************************* + "typedefProxyAlias": ` + +type $mut$FldName = $proxy +`, + // ******************************* + "typedefProxyArray": ` +$#set proxy ArrayOf$mut$FldType +$#if exist else typedefProxyArrayNew +`, + // ******************************* + "typedefProxyArrayNew": ` + +type $proxy struct { + objID int32 +} +$#if mut typedefProxyArrayClear + +func (a $proxy) Length() int32 { + return wasmlib.GetLength(a.objID) +} +$#if basetype typedefProxyArrayNewBaseType typedefProxyArrayNewOtherType +$#set exist $proxy +`, + // ******************************* + "typedefProxyArrayClear": ` + +func (a $proxy) Clear() { + wasmlib.Clear(a.objID) +} +`, + // ******************************* + "typedefProxyArrayNewBaseType": ` + +func (a $proxy) Get$FldType(index int32) wasmlib.Sc$mut$FldType { + return wasmlib.NewSc$mut$FldType(a.objID, wasmlib.Key32(index)) +} +`, + // ******************************* + "typedefProxyArrayNewOtherType": ` +$#if typedef typedefProxyArrayNewOtherTypeTypeDef typedefProxyArrayNewOtherTypeStruct +`, + // ******************************* + "typedefProxyArrayNewOtherTypeTypeDef": ` +$#emit setVarType + +func (a $proxy) Get$OldType(index int32) $mut$OldType { + subID := wasmlib.GetObjectID(a.objID, wasmlib.Key32(index), $varType) + return $mut$OldType{objID: subID} +} +`, + // ******************************* + "typedefProxyArrayNewOtherTypeStruct": ` + +func (a $proxy) Get$FldType(index int32) $mut$FldType { + return $mut$FldType{objID: a.objID, keyID: wasmlib.Key32(index)} +} +`, + // ******************************* + "typedefProxyMap": ` +$#set proxy Map$fldMapKey$+To$mut$FldType +$#if exist else typedefProxyMapNew +`, + // ******************************* + "typedefProxyMapNew": ` + +type $proxy struct { + objID int32 +} +$#if mut typedefProxyMapClear +$#if basetype typedefProxyMapNewBaseType typedefProxyMapNewOtherType +$#set exist $proxy +`, + // ******************************* + "typedefProxyMapClear": ` + +func (m $proxy) Clear() { + wasmlib.Clear(m.objID) +} +`, + // ******************************* + "typedefProxyMapNewBaseType": ` + +func (m $proxy) Get$FldType(key $fldKeyLangType) wasmlib.Sc$mut$FldType { + return wasmlib.NewSc$mut$FldType(m.objID, $fldKeyToKey32) +} +`, + // ******************************* + "typedefProxyMapNewOtherType": ` +$#if typedef typedefProxyMapNewOtherTypeTypeDef typedefProxyMapNewOtherTypeStruct +`, + // ******************************* + "typedefProxyMapNewOtherTypeTypeDef": ` +$#emit setVarType + +func (m $proxy) Get$OldType(key $oldKeyLangType) $mut$OldType { + subID := wasmlib.GetObjectID(m.objID, $oldKeyToKey32, $varType) + return $mut$OldType{objID: subID} +} +`, + // ******************************* + "typedefProxyMapNewOtherTypeStruct": ` + +func (m $proxy) Get$FldType(key $fldKeyLangType) $mut$FldType { + return $mut$FldType{objID: m.objID, keyID: $fldKeyToKey32} +} +`, +} diff --git a/tools/schema/generator/rstemplates/alltemplates.go b/tools/schema/generator/rstemplates/alltemplates.go new file mode 100644 index 0000000000..394bf05480 --- /dev/null +++ b/tools/schema/generator/rstemplates/alltemplates.go @@ -0,0 +1,201 @@ +package rstemplates + +import "github.com/iotaledger/wasp/tools/schema/model" + +var config = map[string]string{ + "language": "Rust", + "extension": ".rs", + "rootFolder": "src", + "funcRegexp": `^pub fn (\w+).+$`, +} + +var Templates = []map[string]string{ + config, + common, + cargoToml, + constsRs, + contractRs, + eventsRs, + funcsRs, + keysRs, + libRs, + modRs, + paramsRs, + proxyRs, + resultsRs, + stateRs, + structsRs, + typedefsRs, +} + +var TypeDependent = model.StringMapMap{ + "fldLangType": { + "Address": "ScAddress", + "AgentID": "ScAgentID", + "Bool": "bool", + "ChainID": "ScChainID", + "Color": "ScColor", + "Hash": "ScHash", + "Hname": "ScHname", + "Int8": "i8", + "Int16": "i16", + "Int32": "i32", + "Int64": "i64", + "RequestID": "ScRequestID", + "String": "String", + "Uint8": "u8", + "Uint16": "u16", + "Uint32": "u32", + "Uint64": "u64", + }, + "fldTypeID": { + "Address": "TYPE_ADDRESS", + "AgentID": "TYPE_AGENT_ID", + "Bool": "TYPE_BOOL", + "ChainID": "TYPE_CHAIN_ID", + "Color": "TYPE_COLOR", + "Hash": "TYPE_HASH", + "Hname": "TYPE_HNAME", + "Int8": "TYPE_INT8", + "Int16": "TYPE_INT16", + "Int32": "TYPE_INT32", + "Int64": "TYPE_INT64", + "RequestID": "TYPE_REQUEST_ID", + "String": "TYPE_STRING", + "Uint8": "TYPE_INT8", + "Uint16": "TYPE_INT16", + "Uint32": "TYPE_INT32", + "Uint64": "TYPE_INT64", + "": "TYPE_BYTES", + }, + "fldToKey32": { + "Address": "key.get_key_id()", + "AgentID": "key.get_key_id()", + "Bool": "???cannot use Bool as map key", + "ChainID": "key.get_key_id()", + "Color": "key.get_key_id()", + "Hash": "key.get_key_id()", + "Hname": "key.get_key_id()", + "Int8": "get_key_id_from_uint64(key as u64, 1)", + "Int16": "get_key_id_from_uint64(key as u64, 2)", + "Int32": "get_key_id_from_uint64(key as u64, 4)", + "Int64": "get_key_id_from_uint64(key as u64, 8)", + "RequestID": "key.get_key_id()", + "String": "key.get_key_id()", + "Uint8": "get_key_id_from_uint64(key as u64, 1)", + "Uint16": "get_key_id_from_uint64(key as u64, 2)", + "Uint32": "get_key_id_from_uint64(key as u64, 4)", + "Uint64": "get_key_id_from_uint64(key, 8)", + }, + "fldParamLangType": { + "Address": "ScAddress", + "AgentID": "ScAgentID", + "Bool": "bool", + "ChainID": "ScChainID", + "Color": "ScColor", + "Hash": "ScHash", + "Hname": "ScHname", + "Int8": "i8", + "Int16": "i16", + "Int32": "i32", + "Int64": "i64", + "RequestID": "ScRequestID", + "String": "str", + "Uint8": "u8", + "Uint16": "u16", + "Uint32": "u32", + "Uint64": "u64", + }, + "fldRef": { + "Address": "&", + "AgentID": "&", + "ChainID": "&", + "Color": "&", + "Hash": "&", + "RequestID": "&", + "String": "&", + }, +} + +var common = map[string]string{ + // ******************************* + "initGlobals": ` +$#set arrayTypeID TYPE_ARRAY +$#set crate +$#if core setArrayTypeID +`, + // ******************************* + "setArrayTypeID": ` +$#set arrayTypeID TYPE_ARRAY16 +$#set crate (crate) +`, + // ******************************* + "rsHeader": ` +$#if core useCrate useWasmLib +`, + // ******************************* + "modEvents": ` +mod events; +`, + // ******************************* + "modParams": ` +mod params; +`, + // ******************************* + "modResults": ` +mod results; +`, + // ******************************* + "modStructs": ` +mod structs; +`, + // ******************************* + "modTypeDefs": ` +mod typedefs; +`, + // ******************************* + "useCrate": ` +use crate::*; +`, + // ******************************* + "useCoreContract": ` +use crate::$package::*; +`, + // ******************************* + "useEvents": ` +use crate::events::*; +`, + // ******************************* + "useHost": ` +use crate::host::*; +`, + // ******************************* + "useParams": ` +use crate::params::*; +`, + // ******************************* + "useResults": ` +use crate::results::*; +`, + // ******************************* + "useStructs": ` +use crate::structs::*; +`, + // ******************************* + "useTypeDefs": ` +use crate::typedefs::*; +`, + // ******************************* + "useWasmLib": ` +use wasmlib::*; +`, + // ******************************* + "setVarType": ` +$#set varType TYPE_MAP +$#if array setVarTypeArray +`, + // ******************************* + "setVarTypeArray": ` +$#set varType $arrayTypeID | $fldTypeID +`, +} diff --git a/tools/schema/generator/rstemplates/cargotoml.go b/tools/schema/generator/rstemplates/cargotoml.go new file mode 100644 index 0000000000..c7d245bed1 --- /dev/null +++ b/tools/schema/generator/rstemplates/cargotoml.go @@ -0,0 +1,32 @@ +package rstemplates + +var cargoToml = map[string]string{ + // ******************************* + "Cargo.toml": ` +# Copyright 2020 IOTA Stiftung +# SPDX-License-Identifier: Apache-2.0 + +[package] +name = "$package" +description = "$scDesc" +license = "Apache-2.0" +version = "0.1.0" +authors = ["John Doe "] +edition = "2018" +repository = "https://github.com/iotaledger/wasp" + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +default = ["console_error_panic_hook"] + +[dependencies] +wasmlib = { git = "https://github.com/iotaledger/wasp", branch = "develop" } +console_error_panic_hook = { version = "0.1.6", optional = true } +wee_alloc = { version = "0.4.5", optional = true } + +[dev-dependencies] +wasm-bindgen-test = "0.3.13" +`, +} diff --git a/tools/schema/generator/rstemplates/consts.go b/tools/schema/generator/rstemplates/consts.go new file mode 100644 index 0000000000..4c3a5bcc4b --- /dev/null +++ b/tools/schema/generator/rstemplates/consts.go @@ -0,0 +1,51 @@ +package rstemplates + +var constsRs = map[string]string{ + // ******************************* + "consts.rs": ` +#![allow(dead_code)] + +$#if core useCrate useWasmLib + +pub const SC_NAME : &str = "$scName"; +pub const SC_DESCRIPTION : &str = "$scDesc"; +pub const HSC_NAME : ScHname = ScHname(0x$hscName); +$#if params constParams +$#if results constResults +$#if state constState + +$#each func constFunc + +$#each func constHFunc +`, + // ******************************* + "constParams": ` + +$#set constPrefix PARAM_ +$#each params constField +`, + // ******************************* + "constResults": ` + +$#set constPrefix RESULT_ +$#each results constField +`, + // ******************************* + "constState": ` + +$#set constPrefix STATE_ +$#each state constField +`, + // ******************************* + "constField": ` +pub$crate const $constPrefix$FLD_NAME$fld_pad : &str = "$fldAlias"; +`, + // ******************************* + "constFunc": ` +pub$crate const $KIND$+_$FUNC_NAME$func_pad : &str = "$funcName"; +`, + // ******************************* + "constHFunc": ` +pub$crate const H$KIND$+_$FUNC_NAME$func_pad : ScHname = ScHname(0x$funcHname); +`, +} diff --git a/tools/schema/generator/rstemplates/contract.go b/tools/schema/generator/rstemplates/contract.go new file mode 100644 index 0000000000..f43624e968 --- /dev/null +++ b/tools/schema/generator/rstemplates/contract.go @@ -0,0 +1,92 @@ +package rstemplates + +var contractRs = map[string]string{ + // ******************************* + "contract.rs": ` +#![allow(dead_code)] + +use std::ptr; + +$#if core useCrate useWasmLib +$#if core useCoreContract contractUses +$#each func FuncNameCall + +pub struct ScFuncs { +} + +impl ScFuncs { +$#set separator $false +$#each func FuncNameForCall +} +`, + // ******************************* + "contractUses": ` + +use crate::consts::*; +$#if params useParams +$#if results useResults +`, + // ******************************* + "FuncNameCall": ` +$#emit setupInitFunc + +pub struct $FuncName$+Call { + pub func: Sc$initFunc$Kind, +$#if param MutableFuncNameParams +$#if result ImmutableFuncNameResults +} +`, + // ******************************* + "MutableFuncNameParams": ` + pub params: Mutable$FuncName$+Params, +`, + // ******************************* + "ImmutableFuncNameResults": ` + pub results: Immutable$FuncName$+Results, +`, + // ******************************* + "FuncNameForCall": ` +$#emit setupInitFunc +$#if separator newline +$#set separator $true + pub fn $func_name(_ctx: & dyn Sc$Kind$+CallContext) -> $FuncName$+Call { +$#set paramsID ptr::null_mut() +$#set resultsID ptr::null_mut() +$#if param setParamsID +$#if result setResultsID +$#if ptrs setPtrs noPtrs + } +`, + // ******************************* + "setPtrs": ` + let mut f = $FuncName$+Call { + func: Sc$initFunc$Kind::new(HSC_NAME, H$KIND$+_$FUNC_NAME), +$#if param FuncNameParamsInit +$#if result FuncNameResultsInit + }; + f.func.set_ptrs($paramsID, $resultsID); + f +`, + // ******************************* + "FuncNameParamsInit": ` + params: Mutable$FuncName$+Params { id: 0 }, +`, + // ******************************* + "FuncNameResultsInit": ` + results: Immutable$FuncName$+Results { id: 0 }, +`, + // ******************************* + "setParamsID": ` +$#set paramsID &mut f.params.id +`, + // ******************************* + "setResultsID": ` +$#set resultsID &mut f.results.id +`, + // ******************************* + "noPtrs": ` + $FuncName$+Call { + func: Sc$initFunc$Kind::new(HSC_NAME, H$KIND$+_$FUNC_NAME), + } +`, +} diff --git a/tools/schema/generator/rstemplates/events.go b/tools/schema/generator/rstemplates/events.go new file mode 100644 index 0000000000..6d203ac398 --- /dev/null +++ b/tools/schema/generator/rstemplates/events.go @@ -0,0 +1,45 @@ +package rstemplates + +var eventsRs = map[string]string{ + // ******************************* + "events.rs": ` +#![allow(dead_code)] + +use wasmlib::*; + +$#set TypeName $Package$+Events +pub struct $TypeName { +} + +impl $TypeName { +$#each events eventFunc +} +`, + // ******************************* + "eventFunc": ` +$#set params +$#each event eventParam + + pub fn $evt_name(&self$params) { +$#if event eventParams eventParamNone + } +`, + // ******************************* + "eventParam": ` +$#set params $params, $fld_name: $fldRef$fldParamLangType +`, + // ******************************* + "eventParamNone": ` + EventEncoder::new("$package.$evtName").emit(); +`, + // ******************************* + "eventParams": ` + let mut encoder = EventEncoder::new("$package.$evtName"); +$#each event eventEmit + encoder.emit(); +`, + // ******************************* + "eventEmit": ` + encoder.$fld_type($fldRef$fld_name); +`, +} diff --git a/tools/schema/generator/rstemplates/funcs.go b/tools/schema/generator/rstemplates/funcs.go new file mode 100644 index 0000000000..0ea4fb2983 --- /dev/null +++ b/tools/schema/generator/rstemplates/funcs.go @@ -0,0 +1,36 @@ +package rstemplates + +var funcsRs = map[string]string{ + // ******************************* + "funcs.rs": ` +use wasmlib::*; + +use crate::*; +$#if structs useStructs +$#if typedefs useTypeDefs +$#each func funcSignature +`, + // ******************************* + "funcSignature": ` + +pub fn $kind$+_$func_name(ctx: &Sc$Kind$+Context, f: &$FuncName$+Context) { +$#emit init$Kind$FuncName +} +`, + // ******************************* + "initFuncInit": ` + if f.params.owner().exists() { + f.state.owner().set_value(&f.params.owner().value()); + return; + } + f.state.owner().set_value(&ctx.contract_creator()); +`, + // ******************************* + "initFuncSetOwner": ` + f.state.owner().set_value(&f.params.owner().value()); +`, + // ******************************* + "initViewGetOwner": ` + f.results.owner().set_value(&f.state.owner().value()); +`, +} diff --git a/tools/schema/generator/rstemplates/keys.go b/tools/schema/generator/rstemplates/keys.go new file mode 100644 index 0000000000..6099c04e59 --- /dev/null +++ b/tools/schema/generator/rstemplates/keys.go @@ -0,0 +1,48 @@ +package rstemplates + +var keysRs = map[string]string{ + // ******************************* + "keys.rs": ` +#![allow(dead_code)] + +use wasmlib::*; + +use crate::*; + +$#set constPrefix PARAM_ +$#each params constFieldIdx + +$#set constPrefix RESULT_ +$#each results constFieldIdx + +$#set constPrefix STATE_ +$#each state constFieldIdx + +pub const KEY_MAP_LEN: usize = $maxIndex; + +pub const KEY_MAP: [&str; KEY_MAP_LEN] = [ +$#set constPrefix PARAM_ +$#each params constFieldKey +$#set constPrefix RESULT_ +$#each results constFieldKey +$#set constPrefix STATE_ +$#each state constFieldKey +]; + +pub static mut IDX_MAP: [Key32; KEY_MAP_LEN] = [Key32(0); KEY_MAP_LEN]; + +pub fn idx_map(idx: usize) -> Key32 { + unsafe { + IDX_MAP[idx] + } +} +`, + // ******************************* + "constFieldIdx": ` +pub(crate) const IDX_$constPrefix$FLD_NAME$fld_pad : usize = $fldIndex; +`, + // ******************************* + "constFieldKey": ` + $constPrefix$FLD_NAME, +`, +} diff --git a/tools/schema/generator/rstemplates/lib.go b/tools/schema/generator/rstemplates/lib.go new file mode 100644 index 0000000000..b7b599232f --- /dev/null +++ b/tools/schema/generator/rstemplates/lib.go @@ -0,0 +1,182 @@ +package rstemplates + +var libRs = map[string]string{ + // ******************************* + "lib.rs": ` +#![allow(dead_code)] +#![allow(unused_imports)] + +use $package::*; +use wasmlib::*; +use wasmlib::host::*; + +use crate::consts::*; +$#if events useEvents +use crate::keys::*; +$#if params useParams +$#if results useResults +use crate::state::*; + +mod consts; +mod contract; +$#if events modEvents +mod keys; +$#if params modParams +$#if results modResults +mod state; +$#if structs modStructs +$#if typedefs modTypeDefs +mod $package; + +#[no_mangle] +fn on_load() { + let exports = ScExports::new(); +$#each func libExportFunc + + unsafe { + for i in 0..KEY_MAP_LEN { + IDX_MAP[i] = get_key_id_from_string(KEY_MAP[i]); + } + } +} +$#each func libThunk +`, + // ******************************* + "libExportFunc": ` + exports.add_$kind($KIND$+_$FUNC_NAME,$func_pad $kind$+_$func_name$+_thunk); +`, + // ******************************* + "libThunk": ` + +pub struct $FuncName$+Context { +$#if func PackageEvents +$#if param ImmutableFuncNameParams +$#if result MutableFuncNameResults +$#if func MutablePackageState +$#if view ImmutablePackageState +} + +fn $kind$+_$func_name$+_thunk(ctx: &Sc$Kind$+Context) { + ctx.log("$package.$kind$FuncName"); +$#emit accessCheck + let f = $FuncName$+Context { +$#if func PackageEventsInit +$#if param ImmutableFuncNameParamsInit +$#if result MutableFuncNameResultsInit +$#if func MutablePackageStateInit +$#if view ImmutablePackageStateInit + }; +$#each mandatory requireMandatory + $kind$+_$func_name(ctx, &f); + ctx.log("$package.$kind$FuncName ok"); +} +`, + // ******************************* + "PackageEvents": ` +$#if events PackageEventsExist +`, + // ******************************* + "PackageEventsExist": ` + events: $Package$+Events, +`, + // ******************************* + "PackageEventsInit": ` +$#if events PackageEventsInitExist +`, + // ******************************* + "PackageEventsInitExist": ` + events: $Package$+Events {}, +`, + // ******************************* + "ImmutableFuncNameParams": ` + params: Immutable$FuncName$+Params, +`, + // ******************************* + "ImmutableFuncNameParamsInit": ` + params: Immutable$FuncName$+Params { + id: OBJ_ID_PARAMS, + }, +`, + // ******************************* + "MutableFuncNameResults": ` + results: Mutable$FuncName$+Results, +`, + // ******************************* + "MutableFuncNameResultsInit": ` + results: Mutable$FuncName$+Results { + id: OBJ_ID_RESULTS, + }, +`, + // ******************************* + "MutablePackageState": ` + state: Mutable$Package$+State, +`, + // ******************************* + "MutablePackageStateInit": ` + state: Mutable$Package$+State { + id: OBJ_ID_STATE, + }, +`, + // ******************************* + "ImmutablePackageState": ` + state: Immutable$Package$+State, +`, + // ******************************* + "ImmutablePackageStateInit": ` + state: Immutable$Package$+State { + id: OBJ_ID_STATE, + }, +`, + // ******************************* + "requireMandatory": ` + ctx.require(f.params.$fld_name().exists(), "missing mandatory $fldName"); +`, + + // ******************************* + "accessCheck": ` +$#set accessFinalize accessOther +$#emit caseAccess$funcAccess +$#emit $accessFinalize +`, + // ******************************* + "caseAccess": ` +$#set accessFinalize accessDone +`, + // ******************************* + "caseAccessself": ` +$#if funcAccessComment accessComment + ctx.require(ctx.caller() == ctx.account_id(), "no permission"); + +$#set accessFinalize accessDone +`, + // ******************************* + "caseAccesschain": ` +$#if funcAccessComment accessComment + ctx.require(ctx.caller() == ctx.chain_owner_id(), "no permission"); + +$#set accessFinalize accessDone +`, + // ******************************* + "caseAccesscreator": ` +$#if funcAccessComment accessComment + ctx.require(ctx.caller() == ctx.contract_creator(), "no permission"); + +$#set accessFinalize accessDone +`, + // ******************************* + "accessOther": ` +$#if funcAccessComment accessComment + let access = ctx.state().get_agent_id("$funcAccess"); + ctx.require(access.exists(), "access not set: $funcAccess"); + ctx.require(ctx.caller() == access.value(), "no permission"); + +`, + // ******************************* + "accessDone": ` +`, + // ******************************* + "accessComment": ` + + $funcAccessComment +`, +} diff --git a/tools/schema/generator/rstemplates/mod.go b/tools/schema/generator/rstemplates/mod.go new file mode 100644 index 0000000000..bfa74afb9f --- /dev/null +++ b/tools/schema/generator/rstemplates/mod.go @@ -0,0 +1,18 @@ +package rstemplates + +var modRs = map[string]string{ + // ******************************* + "mod.rs": ` +#![allow(unused_imports)] + +pub use consts::*; +pub use contract::*; +pub use params::*; +pub use results::*; + +pub mod consts; +pub mod contract; +pub mod params; +pub mod results; +`, +} diff --git a/tools/schema/generator/rstemplates/params.go b/tools/schema/generator/rstemplates/params.go new file mode 100644 index 0000000000..81c9a9253b --- /dev/null +++ b/tools/schema/generator/rstemplates/params.go @@ -0,0 +1,50 @@ +package rstemplates + +var paramsRs = map[string]string{ + // ******************************* + "params.rs": ` +#![allow(dead_code)] +#![allow(unused_imports)] + +$#if core useCrate useWasmLib +$#if core useCoreContract +$#if core useHost paramsUses +$#each func paramsFunc +`, + // ******************************* + "paramsUses": ` +use wasmlib::host::*; + +use crate::*; +use crate::keys::*; +$#if structs useStructs +$#if typedefs useTypeDefs +`, + // ******************************* + "paramsFunc": ` +$#if params paramsFuncParams +`, + // ******************************* + "paramsFuncParams": ` +$#set Kind PARAM_ +$#set mut Immutable +$#if param paramsProxyStruct +$#set mut Mutable +$#if param paramsProxyStruct +`, + // ******************************* + "paramsProxyStruct": ` +$#set TypeName $mut$FuncName$+Params +$#each param proxyContainers + +#[derive(Clone, Copy)] +pub struct $TypeName { + pub(crate) id: i32, +} + +impl $TypeName { +$#set separator $false +$#each param proxyMethods +} +`, +} diff --git a/tools/schema/generator/rstemplates/proxy.go b/tools/schema/generator/rstemplates/proxy.go new file mode 100644 index 0000000000..9070f680a3 --- /dev/null +++ b/tools/schema/generator/rstemplates/proxy.go @@ -0,0 +1,77 @@ +package rstemplates + +var proxyRs = map[string]string{ + // ******************************* + "proxyContainers": ` +$#if array typedefProxyArray +$#if map typedefProxyMap +`, + // ******************************* + "proxyMethods": ` +$#if separator newline +$#set separator $true +$#set varID idx_map(IDX_$Kind$FLD_NAME) +$#if core setCoreVarID +$#if array proxyArray proxyMethods2 +`, + // ******************************* + "proxyMethods2": ` +$#if map proxyMap proxyMethods3 +`, + // ******************************* + "proxyMethods3": ` +$#if basetype proxyBaseType proxyMethods4 +`, + // ******************************* + "proxyMethods4": ` +$#if typedef proxyTypeDef proxyStruct +`, + // ******************************* + "setCoreVarID": ` +$#set varID $Kind$FLD_NAME.get_key_id() +`, + // ******************************* + "proxyArray": ` + pub fn $fld_name(&self) -> ArrayOf$mut$FldType { + let arr_id = get_object_id(self.id, $varID, $arrayTypeID | $fldTypeID); + ArrayOf$mut$FldType { obj_id: arr_id } + } +`, + // ******************************* + "proxyMap": ` +$#if this proxyMapThis proxyMapOther +`, + // ******************************* + "proxyMapThis": ` + pub fn $fld_name(&self) -> Map$fldMapKey$+To$mut$FldType { + Map$fldMapKey$+To$mut$FldType { obj_id: self.id } + } +`, + // ******************************* + "proxyMapOther": `55544444.0 + 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 } + } +`, + // ******************************* + "proxyBaseType": ` + pub fn $fld_name(&self) -> Sc$mut$FldType { + Sc$mut$FldType::new(self.id, $varID) + } +`, + // ******************************* + "proxyTypeDef": ` +$#emit setVarType + pub fn $old_name(&self) -> $mut$OldType { + let sub_id = get_object_id(self.id, $varID, $varType); + $mut$OldType { obj_id: sub_id } + } +`, + // ******************************* + "proxyStruct": ` + pub fn $fld_name(&self) -> $mut$FldType { + $mut$FldType { obj_id: self.id, key_id: $varID } + } +`, +} diff --git a/tools/schema/generator/rstemplates/results.go b/tools/schema/generator/rstemplates/results.go new file mode 100644 index 0000000000..80b11aa37a --- /dev/null +++ b/tools/schema/generator/rstemplates/results.go @@ -0,0 +1,50 @@ +package rstemplates + +var resultsRs = map[string]string{ + // ******************************* + "results.rs": ` +#![allow(dead_code)] +#![allow(unused_imports)] + +$#if core useCrate useWasmLib +$#if core useCoreContract +$#if core useHost resultsUses +$#each func resultsFunc +`, + // ******************************* + "resultsUses": ` +use wasmlib::host::*; + +use crate::*; +use crate::keys::*; +$#if structs useStructs +$#if typedefs useTypeDefs +`, + // ******************************* + "resultsFunc": ` +$#if results resultsFuncResults +`, + // ******************************* + "resultsFuncResults": ` +$#set Kind RESULT_ +$#set mut Immutable +$#if result resultsProxyStruct +$#set mut Mutable +$#if result resultsProxyStruct +`, + // ******************************* + "resultsProxyStruct": ` +$#set TypeName $mut$FuncName$+Results +$#each result proxyContainers + +#[derive(Clone, Copy)] +pub struct $TypeName { + pub(crate) id: i32, +} + +impl $TypeName { +$#set separator $false +$#each result proxyMethods +} +`, +} diff --git a/tools/schema/generator/rstemplates/state.go b/tools/schema/generator/rstemplates/state.go new file mode 100644 index 0000000000..2dbdabed25 --- /dev/null +++ b/tools/schema/generator/rstemplates/state.go @@ -0,0 +1,41 @@ +package rstemplates + +var stateRs = map[string]string{ + // ******************************* + "state.rs": ` +#![allow(dead_code)] +#![allow(unused_imports)] + +use wasmlib::*; +use wasmlib::host::*; + +use crate::*; +use crate::keys::*; +$#if structs useStructs +$#if typedefs useTypeDefs +$#set Kind STATE_ +$#set mut Immutable +$#emit stateProxyStruct +$#set mut Mutable +$#emit stateProxyStruct +`, + // ******************************* + "stateProxyStruct": ` +$#set TypeName $mut$Package$+State +$#each state proxyContainers + +#[derive(Clone, Copy)] +pub struct $TypeName { + pub(crate) id: i32, +} +$#if state stateProxyImpl +`, + // ******************************* + "stateProxyImpl": ` + +impl $TypeName { +$#set separator $false +$#each state proxyMethods +} +`, +} diff --git a/tools/schema/generator/rstemplates/structs.go b/tools/schema/generator/rstemplates/structs.go new file mode 100644 index 0000000000..4c74de9f0e --- /dev/null +++ b/tools/schema/generator/rstemplates/structs.go @@ -0,0 +1,86 @@ +package rstemplates + +var structsRs = map[string]string{ + // ******************************* + "structs.rs": ` +#![allow(dead_code)] +#![allow(unused_imports)] + +use wasmlib::*; +use wasmlib::host::*; +$#if typedefs useTypeDefs +$#each structs structType +`, + // ******************************* + "structType": ` + +pub struct $StrName { +$#each struct structField +} + +impl $StrName { + pub fn from_bytes(bytes: &[u8]) -> $StrName { + let mut decode = BytesDecoder::new(bytes); + $StrName { +$#each struct structDecode + } + } + + pub fn to_bytes(&self) -> Vec { + let mut encode = BytesEncoder::new(); +$#each struct structEncode + return encode.data(); + } +} +$#set mut Immutable +$#emit structMethods +$#set mut Mutable +$#emit structMethods +`, + // ******************************* + "structField": ` + pub $fld_name$fld_pad : $fldLangType, $fldComment +`, + // ******************************* + "structDecode": ` + $fld_name$fld_pad : decode.$fld_type(), +`, + // ******************************* + "structEncode": ` + encode.$fld_type($fldRef$+self.$fld_name); +`, + // ******************************* + "structMethods": ` + +pub struct $mut$StrName { + pub(crate) obj_id: i32, + pub(crate) key_id: Key32, +} + +impl $mut$StrName { +$#if mut structMethodDelete + pub fn exists(&self) -> bool { + exists(self.obj_id, self.key_id, TYPE_BYTES) + } +$#if mut structMethodSetValue + + pub fn value(&self) -> $StrName { + $StrName::from_bytes(&get_bytes(self.obj_id, self.key_id, TYPE_BYTES)) + } +} +`, + // ******************************* + "structMethodDelete": ` + pub fn delete(&self) { + del_key(self.obj_id, self.key_id, TYPE_BYTES); + } + +`, + // ******************************* + "structMethodSetValue": ` + + pub fn set_value(&self, value: &$StrName) { + set_bytes(self.obj_id, self.key_id, TYPE_BYTES, &value.to_bytes()); + } +`, +} diff --git a/tools/schema/generator/rstemplates/typedefs.go b/tools/schema/generator/rstemplates/typedefs.go new file mode 100644 index 0000000000..3b6a2fd676 --- /dev/null +++ b/tools/schema/generator/rstemplates/typedefs.go @@ -0,0 +1,133 @@ +package rstemplates + +var typedefsRs = map[string]string{ + // ******************************* + "typedefs.rs": ` +#![allow(dead_code)] + +use wasmlib::*; +use wasmlib::host::*; +$#if structs useStructs +$#each typedef typedefProxy +`, + // ******************************* + "typedefProxy": ` +$#set mut Immutable +$#if array typedefProxyArray +$#if array typedefProxyAlias +$#if map typedefProxyMap +$#if map typedefProxyAlias +$#set mut Mutable +$#if array typedefProxyArray +$#if array typedefProxyAlias +$#if map typedefProxyMap +$#if map typedefProxyAlias +`, + // ******************************* + "typedefProxyAlias": ` + +pub type $mut$FldName = $proxy; +`, + // ******************************* + "typedefProxyArray": ` +$#set proxy ArrayOf$mut$FldType +$#if exist else typedefProxyArrayNew +`, + // ******************************* + "typedefProxyArrayNew": ` + +pub struct $proxy { + pub(crate) obj_id: i32, +} + +impl $proxy { +$#if mut typedefProxyArrayClear + pub fn length(&self) -> i32 { + get_length(self.obj_id) + } + +$#if basetype typedefProxyArrayNewBaseType typedefProxyArrayNewOtherType +} +$#set exist $proxy +`, + // ******************************* + "typedefProxyArrayClear": ` + pub fn clear(&self) { + clear(self.obj_id); + } + +`, + // ******************************* + "typedefProxyArrayNewBaseType": ` + pub fn get_$fld_type(&self, index: i32) -> Sc$mut$FldType { + Sc$mut$FldType::new(self.obj_id, Key32(index)) + } +`, + // ******************************* + "typedefProxyArrayNewOtherType": ` +$#if typedef typedefProxyArrayNewOtherTypeTypeDef typedefProxyArrayNewOtherTypeStruct +`, + // ******************************* + "typedefProxyArrayNewOtherTypeTypeDef": ` +$#emit setVarType + pub fn get_$old_type(&self, index: i32) -> $mut$OldType { + let sub_id = get_object_id(self.obj_id, Key32(index), $varType); + $mut$OldType { obj_id: sub_id } + } +`, + // ******************************* + "typedefProxyArrayNewOtherTypeStruct": ` + pub fn get_$fld_type(&self, index: i32) -> $mut$FldType { + $mut$FldType { obj_id: self.obj_id, key_id: Key32(index) } + } +`, + // ******************************* + "typedefProxyMap": ` +$#set proxy Map$fldMapKey$+To$mut$FldType +$#if exist else typedefProxyMapNew +`, + // ******************************* + "typedefProxyMapNew": ` + +pub struct $proxy { + pub(crate) obj_id: i32, +} + +impl $proxy { +$#if mut typedefProxyMapClear +$#if basetype typedefProxyMapNewBaseType typedefProxyMapNewOtherType +} +$#set exist $proxy +`, + // ******************************* + "typedefProxyMapClear": ` + pub fn clear(&self) { + clear(self.obj_id); + } + +`, + // ******************************* + "typedefProxyMapNewBaseType": ` + pub fn get_$fld_type(&self, key: $fldKeyRef$fldKeyParamLangType) -> Sc$mut$FldType { + Sc$mut$FldType::new(self.obj_id, $fldKeyToKey32) + } +`, + // ******************************* + "typedefProxyMapNewOtherType": ` +$#if typedef typedefProxyMapNewOtherTypeTypeDef typedefProxyMapNewOtherTypeStruct +`, + // ******************************* + "typedefProxyMapNewOtherTypeTypeDef": ` +$#emit setVarType + pub fn get_$old_type(&self, key: $oldKeyRef$oldKeyParamLangType) -> $mut$OldType { + let sub_id = get_object_id(self.obj_id, $oldKeyToKey32, $varType); + $mut$OldType { obj_id: sub_id } + } +`, + // ******************************* + "typedefProxyMapNewOtherTypeStruct": ` + pub fn get_$fld_type(&self, key: $fldKeyRef$fldKeyParamLangType) -> $mut$FldType { + $mut$FldType { obj_id: self.obj_id, key_id: $fldKeyToKey32 } + } +`, +} diff --git a/tools/schema/generator/templates.go b/tools/schema/generator/templates.go new file mode 100644 index 0000000000..b4652457dd --- /dev/null +++ b/tools/schema/generator/templates.go @@ -0,0 +1,59 @@ +package generator + +import "github.com/iotaledger/wasp/tools/schema/model" + +var commonTemplates = model.StringMap{ + // ******************************* + "else": ` +`, + // ******************************* + "nil": ` +`, + // ******************************* + "newline": ` + +`, + // ******************************* + "copyright": ` +$#emit initGlobals +// Copyright 2020 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +`, + // ******************************* + "warning": ` +// (Re-)generated by schema tool +// >>>> DO NOT CHANGE THIS FILE! <<<< +// Change the json schema instead + +`, + // ******************************* + "test.go": ` +$#emit copyright +package test + +import ( + "testing" + + "$module/go/$package" + "github.com/iotaledger/wasp/packages/vm/wasmsolo" + "github.com/stretchr/testify/require" +) + +func TestDeploy(t *testing.T) { + ctx := wasmsolo.NewSoloContext(t, $package.ScName, $package.OnLoad) + require.NoError(t, ctx.ContractExists($package.ScName)) +} +`, + // ******************************* + "setupInitFunc": ` +$#set initFunc +$#set initMap +$#if init setInitFunc +`, + // ******************************* + "setInitFunc": ` +$#set initFunc Init +$#set initMap , keyMap[:], idxMap[:] +`, +} diff --git a/tools/schema/generator/tstemplates/alltemplates.go b/tools/schema/generator/tstemplates/alltemplates.go new file mode 100644 index 0000000000..8fc4865ace --- /dev/null +++ b/tools/schema/generator/tstemplates/alltemplates.go @@ -0,0 +1,149 @@ +package tstemplates + +import "github.com/iotaledger/wasp/tools/schema/model" + +var config = map[string]string{ + "language": "TypeScript", + "extension": ".ts", + "rootFolder": "ts", + "funcRegexp": `^export function (\w+).+$`, +} + +var Templates = []map[string]string{ + config, + common, + constsTs, + contractTs, + eventsTs, + funcsTs, + indexTs, + keysTs, + libTs, + paramsTs, + proxyTs, + resultsTs, + stateTs, + structsTs, + typedefsTs, +} + +var TypeDependent = model.StringMapMap{ + "fldLangType": { + "Address": "wasmlib.ScAddress", + "AgentID": "wasmlib.ScAgentID", + "Bool": "bool", + "ChainID": "wasmlib.ScChainID", + "Color": "wasmlib.ScColor", + "Hash": "wasmlib.ScHash", + "Hname": "wasmlib.ScHname", + "Int8": "i8", + "Int16": "i16", + "Int32": "i32", + "Int64": "i64", + "RequestID": "wasmlib.ScRequestID", + "String": "string", + "Uint8": "u8", + "Uint16": "u16", + "Uint32": "u32", + "Uint64": "u64", + }, + "fldTypeID": { + "Address": "wasmlib.TYPE_ADDRESS", + "AgentID": "wasmlib.TYPE_AGENT_ID", + "Bool": "wasmlib.TYPE_BOOL", + "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", + }, + "fldToKey32": { + "Address": "key.getKeyID()", + "AgentID": "key.getKeyID()", + "Bool": "???cannot use Bool as map key", + "ChainID": "key.getKeyID()", + "Color": "key.getKeyID()", + "Hash": "key.getKeyID()", + "Hname": "key.getKeyID()", + "Int8": "wasmlib.getKeyIDFromUint64(key as u64, 1)", + "Int16": "wasmlib.getKeyIDFromUint64(key as u64, 2)", + "Int32": "wasmlib.getKeyIDFromUint64(key as u64, 4)", + "Int64": "wasmlib.getKeyIDFromUint64(key as u64, 8)", + "RequestID": "key.getKeyID()", + "String": "wasmlib.Key32.fromString(key)", + "Uint8": "wasmlib.getKeyIDFromUint64(key as u64, 1)", + "Uint16": "wasmlib.getKeyIDFromUint64(key as u64, 2)", + "Uint32": "wasmlib.getKeyIDFromUint64(key as u64, 4)", + "Uint64": "wasmlib.getKeyIDFromUint64(key, 8)", + }, + "fldTypeInit": { + "Address": "new wasmlib.ScAddress()", + "AgentID": "new wasmlib.ScAgentID()", + "Bool": "false", + "ChainID": "new wasmlib.ScChainID()", + "Color": "new wasmlib.ScColor(0)", + "Hash": "new wasmlib.ScHash()", + "Hname": "new wasmlib.ScHname(0)", + "Int8": "0", + "Int16": "0", + "Int32": "0", + "Int64": "0", + "RequestID": "new wasmlib.ScRequestID()", + "String": "\"\"", + "Uint8": "0", + "Uint16": "0", + "Uint32": "0", + "Uint64": "0", + }, +} + +var common = map[string]string{ + // ******************************* + "initGlobals": ` +$#set arrayTypeID wasmlib.TYPE_ARRAY +$#if core setArrayTypeID +`, + // ******************************* + "setArrayTypeID": ` +$#set arrayTypeID wasmlib.TYPE_ARRAY16 +`, + // ******************************* + "importWasmLib": ` +import * as wasmlib from "wasmlib"; +`, + // ******************************* + "importSc": ` +import * as sc from "./index"; +`, + // ******************************* + "tsImports": ` +$#emit importWasmLib +$#emit importSc +`, + // ******************************* + "tsconfig.json": ` +{ + "extends": "assemblyscript/std/assembly.json", + "include": ["./*.ts"] +} +`, + // ******************************* + "setVarType": ` +$#set varType wasmlib.TYPE_MAP +$#if array setVarTypeArray +`, + // ******************************* + "setVarTypeArray": ` +$#set varType $arrayTypeID|$fldTypeID +`, +} diff --git a/tools/schema/generator/tstemplates/consts.go b/tools/schema/generator/tstemplates/consts.go new file mode 100644 index 0000000000..002eade14c --- /dev/null +++ b/tools/schema/generator/tstemplates/consts.go @@ -0,0 +1,49 @@ +package tstemplates + +var constsTs = map[string]string{ + // ******************************* + "consts.ts": ` +$#emit importWasmLib + +export const ScName = "$scName"; +export const ScDescription = "$scDesc"; +export const HScName = new wasmlib.ScHname(0x$hscName); +$#if params constParams +$#if results constResults +$#if state constState + +$#each func constFunc + +$#each func constHFunc +`, + // ******************************* + "constParams": ` + +$#set constPrefix Param +$#each params constField +`, + // ******************************* + "constResults": ` + +$#set constPrefix Result +$#each results constField +`, + // ******************************* + "constState": ` + +$#set constPrefix State +$#each state constField +`, + // ******************************* + "constField": ` +export const $constPrefix$FldName$fldPad = "$fldAlias"; +`, + // ******************************* + "constFunc": ` +export const $Kind$FuncName$funcPad = "$funcName"; +`, + // ******************************* + "constHFunc": ` +export const H$Kind$FuncName$funcPad = new wasmlib.ScHname(0x$funcHname); +`, +} diff --git a/tools/schema/generator/tstemplates/contract.go b/tools/schema/generator/tstemplates/contract.go new file mode 100644 index 0000000000..a2cc9ba26b --- /dev/null +++ b/tools/schema/generator/tstemplates/contract.go @@ -0,0 +1,99 @@ +package tstemplates + +var contractTs = map[string]string{ + // ******************************* + "contract.ts": ` +$#emit tsImports +$#each func FuncNameCall + +export class ScFuncs { +$#set separator $false +$#each func FuncNameForCall +} +`, + // ******************************* + "FuncNameCall": ` +$#emit setupInitFunc + +export class $FuncName$+Call { + func: wasmlib.Sc$initFunc$Kind = new wasmlib.Sc$initFunc$Kind(sc.HScName, sc.H$Kind$FuncName); +$#if param MutableFuncNameParams +$#if result ImmutableFuncNameResults +} +$#if core else FuncNameContext +`, + // ******************************* + "FuncNameContext": ` + +export class $FuncName$+Context { +$#if func PackageEvents +$#if param ImmutableFuncNameParams +$#if result MutableFuncNameResults +$#if func MutablePackageState +$#if view ImmutablePackageState +} +`, + // ******************************* + "PackageEvents": ` +$#if events PackageEventsExist +`, + // ******************************* + "PackageEventsExist": ` + events: sc.$Package$+Events = new sc.$Package$+Events(); +`, + // ******************************* + "ImmutableFuncNameParams": ` + params: sc.Immutable$FuncName$+Params = new sc.Immutable$FuncName$+Params(); +`, + // ******************************* + "MutableFuncNameParams": ` + params: sc.Mutable$FuncName$+Params = new sc.Mutable$FuncName$+Params(); +`, + // ******************************* + "ImmutableFuncNameResults": ` + results: sc.Immutable$FuncName$+Results = new sc.Immutable$FuncName$+Results(); +`, + // ******************************* + "MutableFuncNameResults": ` + results: sc.Mutable$FuncName$+Results = new sc.Mutable$FuncName$+Results(); +`, + // ******************************* + "ImmutablePackageState": ` + state: sc.Immutable$Package$+State = new sc.Immutable$Package$+State(); +`, + // ******************************* + "MutablePackageState": ` + state: sc.Mutable$Package$+State = new sc.Mutable$Package$+State(); +`, + // ******************************* + "FuncNameForCall": ` +$#emit setupInitFunc +$#if separator newline +$#set separator $true + static $funcName(ctx: wasmlib.Sc$Kind$+CallContext): $FuncName$+Call { +$#set paramsID null +$#set resultsID null +$#if param setParamsID +$#if result setResultsID +$#if ptrs setPtrs noPtrs + } +`, + // ******************************* + "setPtrs": ` + let f = new $FuncName$+Call(); + f.func.setPtrs($paramsID, $resultsID); + return f; +`, + // ******************************* + "setParamsID": ` +$#set paramsID f.params +`, + // ******************************* + "setResultsID": ` +$#set resultsID f.results +`, + // ******************************* + "noPtrs": ` + return new $FuncName$+Call(); +`, +} diff --git a/tools/schema/generator/tstemplates/events.go b/tools/schema/generator/tstemplates/events.go new file mode 100644 index 0000000000..1712275c9e --- /dev/null +++ b/tools/schema/generator/tstemplates/events.go @@ -0,0 +1,34 @@ +package tstemplates + +var eventsTs = map[string]string{ + // ******************************* + "events.ts": ` +$#emit importWasmLib + +$#set TypeName $Package$+Events +export class $TypeName { +$#each events eventFunc +} +`, + // ******************************* + "eventFunc": ` +$#set params +$#set separator +$#each event eventParam + + $evtName($params): void { + new wasmlib.EventEncoder("$package.$evtName"). +$#each event eventEmit + emit(); + } +`, + // ******************************* + "eventParam": ` +$#set params $params$separator$fldName: $fldLangType +$#set separator , +`, + // ******************************* + "eventEmit": ` + $fldType($fldName). +`, +} diff --git a/tools/schema/generator/tstemplates/funcs.go b/tools/schema/generator/tstemplates/funcs.go new file mode 100644 index 0000000000..271f248056 --- /dev/null +++ b/tools/schema/generator/tstemplates/funcs.go @@ -0,0 +1,32 @@ +package tstemplates + +var funcsTs = map[string]string{ + // ******************************* + "funcs.ts": ` +$#emit tsImports +$#each func funcSignature +`, + // ******************************* + "funcSignature": ` + +export function $kind$+$FuncName(ctx: wasmlib.Sc$Kind$+Context, f: sc.$FuncName$+Context): void { +$#emit init$Kind$FuncName +} +`, + // ******************************* + "initFuncInit": ` + if (f.params.owner().exists()) { + f.state.owner().setValue(f.params.owner().value()); + return; + } + f.state.owner().setValue(ctx.contractCreator()); +`, + // ******************************* + "initFuncSetOwner": ` + f.state.owner().setValue(f.params.owner().value()); +`, + // ******************************* + "initViewGetOwner": ` + f.results.owner().setValue(f.state.owner().value()); +`, +} diff --git a/tools/schema/generator/tstemplates/index.go b/tools/schema/generator/tstemplates/index.go new file mode 100644 index 0000000000..4bb4725cad --- /dev/null +++ b/tools/schema/generator/tstemplates/index.go @@ -0,0 +1,55 @@ +package tstemplates + +var indexTs = map[string]string{ + // ******************************* + "index.ts": ` +$#if core else exportName +export * from "./consts"; +export * from "./contract"; +$#if events exportEvents +$#if core else exportKeys +$#if core else exportLib +$#if params exportParams +$#if results exportResults +$#if core else exportRest +`, + // ******************************* + "exportName": ` +export * from "./$package"; + +`, + // ******************************* + "exportEvents": ` +export * from "./events"; +`, + // ******************************* + "exportKeys": ` +export * from "./keys"; +`, + // ******************************* + "exportLib": ` +export * from "./lib"; +`, + // ******************************* + "exportParams": ` +export * from "./params"; +`, + // ******************************* + "exportResults": ` +export * from "./results"; +`, + // ******************************* + "exportRest": ` +export * from "./state"; +$#if structs exportStructs +$#if typedefs exportTypedefs +`, + // ******************************* + "exportStructs": ` +export * from "./structs"; +`, + // ******************************* + "exportTypedefs": ` +export * from "./typedefs"; +`, +} diff --git a/tools/schema/generator/tstemplates/keys.go b/tools/schema/generator/tstemplates/keys.go new file mode 100644 index 0000000000..6aaa919ad5 --- /dev/null +++ b/tools/schema/generator/tstemplates/keys.go @@ -0,0 +1,36 @@ +package tstemplates + +var keysTs = map[string]string{ + // ******************************* + "keys.ts": ` +$#emit tsImports + +$#set constPrefix Param +$#each params constFieldIdx + +$#set constPrefix Result +$#each results constFieldIdx + +$#set constPrefix State +$#each state constFieldIdx + +export let keyMap: string[] = [ +$#set constPrefix Param +$#each params constFieldKey +$#set constPrefix Result +$#each results constFieldKey +$#set constPrefix State +$#each state constFieldKey +]; + +export let idxMap: wasmlib.Key32[] = new Array(keyMap.length); +`, + // ******************************* + "constFieldIdx": ` +export const Idx$constPrefix$FldName$fldPad = $fldIndex; +`, + // ******************************* + "constFieldKey": ` + sc.$constPrefix$FldName, +`, +} diff --git a/tools/schema/generator/tstemplates/lib.go b/tools/schema/generator/tstemplates/lib.go new file mode 100644 index 0000000000..fa20ef1595 --- /dev/null +++ b/tools/schema/generator/tstemplates/lib.go @@ -0,0 +1,101 @@ +package tstemplates + +var libTs = map[string]string{ + // ******************************* + "lib.ts": ` +$#emit tsImports + +export function on_call(index: i32): void { + return wasmlib.onCall(index); +} + +export function on_load(): void { + let exports = new wasmlib.ScExports(); +$#each func libExportFunc + + for (let i = 0; i < sc.keyMap.length; i++) { + sc.idxMap[i] = wasmlib.Key32.fromString(sc.keyMap[i]); + } +} +$#each func libThunk +`, + // ******************************* + "libExportFunc": ` + exports.add$Kind(sc.$Kind$FuncName,$funcPad $kind$FuncName$+Thunk); +`, + // ******************************* + "libThunk": ` + +function $kind$FuncName$+Thunk(ctx: wasmlib.Sc$Kind$+Context): void { + ctx.log("$package.$kind$FuncName"); +$#emit accessCheck + let f = new sc.$FuncName$+Context(); +$#if param ImmutableFuncNameParamsInit +$#if result MutableFuncNameResultsInit + f.state.mapID = wasmlib.OBJ_ID_STATE; +$#each mandatory requireMandatory + sc.$kind$FuncName(ctx, f); + ctx.log("$package.$kind$FuncName ok"); +} +`, + // ******************************* + "ImmutableFuncNameParamsInit": ` + f.params.mapID = wasmlib.OBJ_ID_PARAMS; +`, + // ******************************* + "MutableFuncNameResultsInit": ` + f.results.mapID = wasmlib.OBJ_ID_RESULTS; +`, + // ******************************* + "requireMandatory": ` + ctx.require(f.params.$fldName().exists(), "missing mandatory $fldName"); +`, + + // ******************************* + "accessCheck": ` +$#set accessFinalize accessOther +$#emit caseAccess$funcAccess +$#emit $accessFinalize +`, + // ******************************* + "caseAccess": ` +$#set accessFinalize accessDone +`, + // ******************************* + "caseAccessself": ` +$#if funcAccessComment accessComment + ctx.require(ctx.caller().equals(ctx.accountID()), "no permission"); + +$#set accessFinalize accessDone +`, + // ******************************* + "caseAccesschain": ` +$#if funcAccessComment accessComment + ctx.require(ctx.caller().equals(ctx.chainOwnerID()), "no permission"); + +$#set accessFinalize accessDone +`, + // ******************************* + "caseAccesscreator": ` +$#if funcAccessComment accessComment + ctx.require(ctx.caller().equals(ctx.contractCreator()), "no permission"); + +$#set accessFinalize accessDone +`, + // ******************************* + "accessOther": ` +$#if funcAccessComment accessComment + let access = ctx.state().getAgentID(wasmlib.Key32.fromString("$funcAccess")); + ctx.require(access.exists(), "access not set: $funcAccess"); + ctx.require(ctx.caller().equals(access.value()), "no permission"); + +`, + // ******************************* + "accessDone": ` +`, + // ******************************* + "accessComment": ` + + $funcAccessComment +`, +} diff --git a/tools/schema/generator/tstemplates/params.go b/tools/schema/generator/tstemplates/params.go new file mode 100644 index 0000000000..8216ac2135 --- /dev/null +++ b/tools/schema/generator/tstemplates/params.go @@ -0,0 +1,31 @@ +package tstemplates + +var paramsTs = map[string]string{ + // ******************************* + "params.ts": ` +$#emit tsImports +$#each func paramsFunc +`, + // ******************************* + "paramsFunc": ` +$#if params paramsFuncParams +`, + // ******************************* + "paramsFuncParams": ` +$#set Kind Param +$#set mut Immutable +$#if param paramsProxyStruct +$#set mut Mutable +$#if param paramsProxyStruct +`, + // ******************************* + "paramsProxyStruct": ` +$#set TypeName $mut$FuncName$+Params +$#each param proxyContainers + +export class $TypeName extends wasmlib.ScMapID { +$#set separator $false +$#each param proxyMethods +} +`, +} diff --git a/tools/schema/generator/tstemplates/proxy.go b/tools/schema/generator/tstemplates/proxy.go new file mode 100644 index 0000000000..1cef0b8798 --- /dev/null +++ b/tools/schema/generator/tstemplates/proxy.go @@ -0,0 +1,77 @@ +package tstemplates + +var proxyTs = map[string]string{ + // ******************************* + "proxyContainers": ` +$#if array typedefProxyArray +$#if map typedefProxyMap +`, + // ******************************* + "proxyMethods": ` +$#if separator newline +$#set separator $true +$#set varID sc.idxMap[sc.Idx$Kind$FldName] +$#if core setCoreVarID +$#if array proxyArray proxyMethods2 +`, + // ******************************* + "proxyMethods2": ` +$#if map proxyMap proxyMethods3 +`, + // ******************************* + "proxyMethods3": ` +$#if basetype proxyBaseType proxyMethods4 +`, + // ******************************* + "proxyMethods4": ` +$#if typedef proxyTypeDef proxyStruct +`, + // ******************************* + "setCoreVarID": ` +$#set varID wasmlib.Key32.fromString(sc.$Kind$FldName) +`, + // ******************************* + "proxyArray": ` + $fldName(): sc.ArrayOf$mut$FldType { + let arrID = wasmlib.getObjectID(this.mapID, $varID, $arrayTypeID|$fldTypeID); + return new sc.ArrayOf$mut$FldType(arrID); + } +`, + // ******************************* + "proxyMap": ` +$#if this proxyMapThis proxyMapOther +`, + // ******************************* + "proxyMapThis": ` + $fldName(): sc.Map$fldMapKey$+To$mut$FldType { + return new sc.Map$fldMapKey$+To$mut$FldType(this.mapID); + } +`, + // ******************************* + "proxyMapOther": ` + $fldName(): sc.Map$fldMapKey$+To$mut$FldType { + let mapID = wasmlib.getObjectID(this.mapID, $varID, wasmlib.TYPE_MAP); + return new sc.Map$fldMapKey$+To$mut$FldType(mapID); + } +`, + // ******************************* + "proxyBaseType": ` + $fldName(): wasmlib.Sc$mut$FldType { + return new wasmlib.Sc$mut$FldType(this.mapID, $varID); + } +`, + // ******************************* + "proxyTypeDef": ` +$#emit setVarType + $oldName(): sc.$mut$OldType { + let subID = wasmlib.getObjectID(this.mapID, $varID, $varType); + return new sc.$mut$OldType(subID); + } +`, + // ******************************* + "proxyStruct": ` + $fldName(): sc.$mut$FldType { + return new sc.$mut$FldType(this.mapID, $varID); + } +`, +} diff --git a/tools/schema/generator/tstemplates/results.go b/tools/schema/generator/tstemplates/results.go new file mode 100644 index 0000000000..61dabe5049 --- /dev/null +++ b/tools/schema/generator/tstemplates/results.go @@ -0,0 +1,31 @@ +package tstemplates + +var resultsTs = map[string]string{ + // ******************************* + "results.ts": ` +$#emit tsImports +$#each func resultsFunc +`, + // ******************************* + "resultsFunc": ` +$#if results resultsFuncResults +`, + // ******************************* + "resultsFuncResults": ` +$#set Kind Result +$#set mut Immutable +$#if result resultsProxyStruct +$#set mut Mutable +$#if result resultsProxyStruct +`, + // ******************************* + "resultsProxyStruct": ` +$#set TypeName $mut$FuncName$+Results +$#each result proxyContainers + +export class $TypeName extends wasmlib.ScMapID { +$#set separator $false +$#each result proxyMethods +} +`, +} diff --git a/tools/schema/generator/tstemplates/state.go b/tools/schema/generator/tstemplates/state.go new file mode 100644 index 0000000000..f624be1471 --- /dev/null +++ b/tools/schema/generator/tstemplates/state.go @@ -0,0 +1,23 @@ +package tstemplates + +var stateTs = map[string]string{ + // ******************************* + "state.ts": ` +$#emit tsImports +$#set Kind State +$#set mut Immutable +$#emit stateProxyStruct +$#set mut Mutable +$#emit stateProxyStruct +`, + // ******************************* + "stateProxyStruct": ` +$#set TypeName $mut$Package$+State +$#each state proxyContainers + +export class $TypeName extends wasmlib.ScMapID { +$#set separator $false +$#each state proxyMethods +} +`, +} diff --git a/tools/schema/generator/tstemplates/structs.go b/tools/schema/generator/tstemplates/structs.go new file mode 100644 index 0000000000..254d8b329d --- /dev/null +++ b/tools/schema/generator/tstemplates/structs.go @@ -0,0 +1,83 @@ +package tstemplates + +var structsTs = map[string]string{ + // ******************************* + "structs.ts": ` +$#emit importWasmLib +$#each structs structType +`, + // ******************************* + "structType": ` + +export class $StrName { +$#each struct structField + + static fromBytes(bytes: u8[]): $StrName { + let decode = new wasmlib.BytesDecoder(bytes); + let data = new $StrName(); +$#each struct structDecode + decode.close(); + return data; + } + + bytes(): u8[] { + return new wasmlib.BytesEncoder(). +$#each struct structEncode + data(); + } +} +$#set mut Immutable +$#emit structMethods +$#set mut Mutable +$#emit structMethods +`, + // ******************************* + "structField": ` + $fldName$fldPad : $fldLangType = $fldTypeInit; $fldComment +`, + // ******************************* + "structDecode": ` + data.$fldName$fldPad = decode.$fldType(); +`, + // ******************************* + "structEncode": ` + $fldType(this.$fldName). +`, + // ******************************* + "structMethods": ` + +export class $mut$StrName { + objID: i32; + keyID: wasmlib.Key32; + + constructor(objID: i32, keyID: wasmlib.Key32) { + this.objID = objID; + this.keyID = keyID; + } +$#if mut structMethodDelete + + exists(): boolean { + return wasmlib.exists(this.objID, this.keyID, wasmlib.TYPE_BYTES); + } +$#if mut structMethodSetValue + + value(): $StrName { + return $StrName.fromBytes(wasmlib.getBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES)); + } +} +`, + // ******************************* + "structMethodDelete": ` + + delete(): void { + wasmlib.delKey(this.objID, this.keyID, wasmlib.TYPE_BYTES); + } +`, + // ******************************* + "structMethodSetValue": ` + + setValue(value: $StrName): void { + wasmlib.setBytes(this.objID, this.keyID, wasmlib.TYPE_BYTES, value.bytes()); + } +`, +} diff --git a/tools/schema/generator/tstemplates/typedefs.go b/tools/schema/generator/tstemplates/typedefs.go new file mode 100644 index 0000000000..21ae67839b --- /dev/null +++ b/tools/schema/generator/tstemplates/typedefs.go @@ -0,0 +1,138 @@ +package tstemplates + +var typedefsTs = map[string]string{ + // ******************************* + "typedefs.ts": ` +$#emit tsImports +$#each typedef typedefProxy +`, + // ******************************* + "typedefProxy": ` +$#set mut Immutable +$#if array typedefProxyArray +$#if array typedefProxyAlias +$#if map typedefProxyMap +$#if map typedefProxyAlias +$#set mut Mutable +$#if array typedefProxyArray +$#if array typedefProxyAlias +$#if map typedefProxyMap +$#if map typedefProxyAlias +`, + // ******************************* + "typedefProxyAlias": ` + +export class $mut$FldName extends $proxy { +}; +`, + // ******************************* + "typedefProxyArray": ` +$#set proxy ArrayOf$mut$FldType +$#if exist else typedefProxyArrayNew +`, + // ******************************* + "typedefProxyArrayNew": ` + +export class $proxy { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } +$#if mut typedefProxyArrayClear + + length(): i32 { + return wasmlib.getLength(this.objID); + } +$#if basetype typedefProxyArrayNewBaseType typedefProxyArrayNewOtherType +} +$#set exist $proxy +`, + // ******************************* + "typedefProxyArrayClear": ` + + clear(): void { + wasmlib.clear(this.objID); + } +`, + // ******************************* + "typedefProxyArrayNewBaseType": ` + + get$FldType(index: i32): wasmlib.Sc$mut$FldType { + return new wasmlib.Sc$mut$FldType(this.objID, new wasmlib.Key32(index)); + } +`, + // ******************************* + "typedefProxyArrayNewOtherType": ` +$#if typedef typedefProxyArrayNewOtherTypeTypeDef typedefProxyArrayNewOtherTypeStruct +`, + // ******************************* + "typedefProxyArrayNewOtherTypeTypeDef": ` +$#emit setVarType + + get$OldType(index: i32): sc.$mut$OldType { + let subID = wasmlib.getObjectID(this.objID, new wasmlib.Key32(index), $varType); + return new sc.$mut$OldType(subID); + } +`, + // ******************************* + "typedefProxyArrayNewOtherTypeStruct": ` + + get$FldType(index: i32): sc.$mut$FldType { + return new sc.$mut$FldType(this.objID, new wasmlib.Key32(index)); + } +`, + // ******************************* + "typedefProxyMap": ` +$#set proxy Map$fldMapKey$+To$mut$FldType +$#if exist else typedefProxyMapNew +`, + // ******************************* + "typedefProxyMapNew": ` + +export class $proxy { + objID: i32; + + constructor(objID: i32) { + this.objID = objID; + } +$#if mut typedefProxyMapClear +$#if basetype typedefProxyMapNewBaseType typedefProxyMapNewOtherType +} +$#set exist $proxy +`, + // ******************************* + "typedefProxyMapClear": ` + + clear(): void { + wasmlib.clear(this.objID); + } +`, + // ******************************* + "typedefProxyMapNewBaseType": ` + + get$FldType(key: $fldKeyLangType): wasmlib.Sc$mut$FldType { + return new wasmlib.Sc$mut$FldType(this.objID, $fldKeyToKey32); + } +`, + // ******************************* + "typedefProxyMapNewOtherType": ` +$#if typedef typedefProxyMapNewOtherTypeTypeDef typedefProxyMapNewOtherTypeStruct +`, + // ******************************* + "typedefProxyMapNewOtherTypeTypeDef": ` +$#emit setVarType + + get$OldType(key: $oldKeyLangType): sc.$mut$OldType { + let subID = wasmlib.getObjectID(this.objID, $oldKeyToKey32, $varType); + return new sc.$mut$OldType(subID); + } +`, + // ******************************* + "typedefProxyMapNewOtherTypeStruct": ` + + get$FldType(key: $fldKeyLangType): sc.$mut$FldType { + return new sc.$mut$FldType(this.objID, $fldKeyToKey32); + } +`, +} diff --git a/tools/schema/generator/utils.go b/tools/schema/generator/utils.go index 9687ca39a0..ae12a5aec8 100644 --- a/tools/schema/generator/utils.go +++ b/tools/schema/generator/utils.go @@ -5,65 +5,31 @@ import ( "fmt" "os" "regexp" - "sort" "strings" ) var ( - //nolint:unused - snakePart = regexp.MustCompile(`_[a-z]`) camelPart = regexp.MustCompile(`[a-z0-9][A-Z]`) camelPartWithID = regexp.MustCompile(`[A-Z][A-Z]+[a-z]`) + moduleCwd = "???" + moduleName = "???" + modulePath = "???" ) -func calculatePadding(fields []*Field, types StringMap, snakeName bool) (nameLen, typeLen int) { - for _, param := range fields { - fldName := param.Name - if snakeName { - fldName = snake(fldName) - } - if nameLen < len(fldName) { - nameLen = len(fldName) - } - fldType := param.Type - if types != nil { - fldType = types[fldType] - } - if typeLen < len(fldType) { - typeLen = len(fldType) - } - } - return -} - -// convert lowercase snake case to camel case -//nolint:deadcode,unused -func camel(name string) string { - // replace each underscore followed by [a-z] with [A-Z] - return snakePart.ReplaceAllStringFunc(name, func(sub string) string { - return strings.ToUpper(sub[1:]) - }) -} - // capitalize first letter func capitalize(name string) string { return upper(name[:1]) + name[1:] } -// convert to lower case -func lower(name string) string { - return strings.ToLower(name) -} - func FindModulePath() error { cwd, err := os.Getwd() if err != nil { return err } // we're going to walk up the path, make sure to restore - ModuleCwd = cwd + moduleCwd = cwd defer func() { - _ = os.Chdir(ModuleCwd) + _ = os.Chdir(moduleCwd) }() file, err := os.Open("go.mod") @@ -93,8 +59,8 @@ func FindModulePath() error { for scanner.Scan() { line := scanner.Text() if strings.HasPrefix(line, "module ") { - ModuleName = strings.TrimSpace(line[len("module"):]) - ModulePath = cwd + moduleName = strings.TrimSpace(line[len("module"):]) + modulePath = cwd return nil } } @@ -102,12 +68,9 @@ func FindModulePath() error { return fmt.Errorf("cannot find module definition in go.mod") } -// pad to specified size with spaces -func pad(name string, size int) string { - for i := len(name); i < size; i++ { - name += " " - } - return name +// convert to lower case +func lower(name string) string { + return strings.ToLower(name) } // convert camel case to lower case snake case @@ -136,39 +99,3 @@ func uncapitalize(name string) string { func upper(name string) string { return strings.ToUpper(name) } - -func sortedFields(dict FieldMap) []string { - keys := make([]string, 0) - for key := range dict { - keys = append(keys, key) - } - sort.Strings(keys) - return keys -} - -func sortedFuncDescs(dict FuncDefMap) []string { - keys := make([]string, 0) - for key := range dict { - keys = append(keys, key) - } - sort.Strings(keys) - return keys -} - -func sortedKeys(dict StringMap) []string { - keys := make([]string, 0) - for key := range dict { - keys = append(keys, key) - } - sort.Strings(keys) - return keys -} - -func sortedMaps(dict StringMapMap) []string { - keys := make([]string, 0) - for key := range dict { - keys = append(keys, key) - } - sort.Strings(keys) - return keys -} diff --git a/tools/schema/main.go b/tools/schema/main.go index 74bdc229f7..bcdb2543b6 100644 --- a/tools/schema/main.go +++ b/tools/schema/main.go @@ -17,17 +17,19 @@ import ( "time" "github.com/iotaledger/wasp/tools/schema/generator" + "github.com/iotaledger/wasp/tools/schema/model" "gopkg.in/yaml.v2" ) var ( - flagCore = flag.Bool("core", false, "generate core contract interface") - flagForce = flag.Bool("force", false, "force code generation") - flagGo = flag.Bool("go", false, "generate Go code") - flagInit = flag.String("init", "", "generate new schema file for smart contract named ") - flagRust = flag.Bool("rust", false, "generate Rust code") - flagTs = flag.Bool("ts", false, "generate TypScript code") - flagType = flag.String("type", "yaml", "type of schema file that will be generated. Values(yaml,json)") + flagCore = flag.Bool("core", false, "generate core contract interface") + flagClient = flag.Bool("client", false, "generate client side contract interface") + flagForce = flag.Bool("force", false, "force code generation") + flagGo = flag.Bool("go", false, "generate Go code") + flagInit = flag.String("init", "", "generate new schema file for smart contract named ") + flagRust = flag.Bool("rust", false, "generate Rust code") + flagTs = flag.Bool("ts", false, "generate TypScript code") + flagType = flag.String("type", "yaml", "type of schema file that will be generated. Values(yaml,json)") ) func init() { @@ -113,25 +115,33 @@ func generateSchema(file *os.File) error { s.SchemaTime = time.Now() } - if *flagTs { - g := generator.NewTypeScriptGenerator() - err = g.Generate(s) + if *flagClient { + g := generator.NewClientGenerator(s) + err = g.Generate() if err != nil { return err } } if *flagGo { - g := generator.NewGoGenerator() - err = g.Generate(s) + g := generator.NewGoGenerator(s) + err = g.Generate() if err != nil { return err } } if *flagRust { - g := generator.NewRustGenerator() - err = g.Generate(s) + g := generator.NewRustGenerator(s) + err = g.Generate() + if err != nil { + return err + } + } + + if *flagTs { + g := generator.NewTypeScriptGenerator(s) + err = g.Generate() if err != nil { return err } @@ -140,6 +150,7 @@ func generateSchema(file *os.File) error { } func generateSchemaNew() error { + // TODO make sure name is valid: no path characters name := *flagInit fmt.Println("initializing " + name) @@ -153,29 +164,30 @@ func generateSchemaNew() error { return err } - schemaDef := &generator.SchemaDef{} + schemaDef := &model.SchemaDef{} schemaDef.Name = name schemaDef.Description = name + " description" - schemaDef.Structs = make(generator.StringMapMap) - schemaDef.Typedefs = make(generator.StringMap) - schemaDef.State = make(generator.StringMap) + schemaDef.Structs = make(model.StringMapMap) + schemaDef.Events = make(model.StringMapMap) + schemaDef.Typedefs = make(model.StringMap) + schemaDef.State = make(model.StringMap) schemaDef.State["owner"] = "AgentID // current owner of this smart contract" - schemaDef.Funcs = make(generator.FuncDefMap) - schemaDef.Views = make(generator.FuncDefMap) + schemaDef.Funcs = make(model.FuncDefMap) + schemaDef.Views = make(model.FuncDefMap) - funcInit := &generator.FuncDef{} - funcInit.Params = make(generator.StringMap) + funcInit := &model.FuncDef{} + funcInit.Params = make(model.StringMap) funcInit.Params["owner"] = "AgentID? // optional owner of this smart contract" schemaDef.Funcs["init"] = funcInit - funcSetOwner := &generator.FuncDef{} + funcSetOwner := &model.FuncDef{} funcSetOwner.Access = "owner // current owner of this smart contract" - funcSetOwner.Params = make(generator.StringMap) + funcSetOwner.Params = make(model.StringMap) funcSetOwner.Params["owner"] = "AgentID // new owner of this smart contract" schemaDef.Funcs["setOwner"] = funcSetOwner - viewGetOwner := &generator.FuncDef{} - viewGetOwner.Results = make(generator.StringMap) + viewGetOwner := &model.FuncDef{} + viewGetOwner.Results = make(model.StringMap) viewGetOwner.Results["owner"] = "AgentID // current owner of this smart contract" schemaDef.Views["getOwner"] = viewGetOwner switch *flagType { @@ -187,9 +199,9 @@ func generateSchemaNew() error { return errors.New("invalid schema type: " + *flagType) } -func loadSchema(file *os.File) (s *generator.Schema, err error) { +func loadSchema(file *os.File) (s *model.Schema, err error) { fmt.Println("loading " + file.Name()) - schemaDef := &generator.SchemaDef{} + schemaDef := &model.SchemaDef{} switch filepath.Ext(file.Name()) { case ".json": err = json.NewDecoder(file).Decode(schemaDef) @@ -209,7 +221,7 @@ func loadSchema(file *os.File) (s *generator.Schema, err error) { return nil, err } - s = generator.NewSchema() + s = model.NewSchema() err = s.Compile(schemaDef) if err != nil { return nil, err @@ -217,7 +229,7 @@ func loadSchema(file *os.File) (s *generator.Schema, err error) { return s, nil } -func WriteJSONSchema(schemaDef *generator.SchemaDef) error { +func WriteJSONSchema(schemaDef *model.SchemaDef) error { file, err := os.Create("schema.json") if err != nil { return err @@ -239,7 +251,7 @@ func WriteJSONSchema(schemaDef *generator.SchemaDef) error { return err } -func WriteYAMLSchema(schemaDef *generator.SchemaDef) error { +func WriteYAMLSchema(schemaDef *model.SchemaDef) error { file, err := os.Create("schema.yaml") if err != nil { return err diff --git a/tools/schema/generator/field.go b/tools/schema/model/field.go similarity index 90% rename from tools/schema/generator/field.go rename to tools/schema/model/field.go index 2b28ca05af..38232a01df 100644 --- a/tools/schema/generator/field.go +++ b/tools/schema/model/field.go @@ -1,7 +1,7 @@ // Copyright 2020 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -package generator +package model import ( "fmt" @@ -20,16 +20,22 @@ var ( var FieldTypes = map[string]int32{ "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, } type Field struct { @@ -86,7 +92,7 @@ func (f *Field) Compile(s *Schema, fldName, fldType string) error { index = strings.Index(fldType, "]") if index > 5 { f.MapKey = strings.TrimSpace(fldType[4:index]) - if !fldTypeRegexp.MatchString(f.MapKey) { + if !fldTypeRegexp.MatchString(f.MapKey) || f.MapKey == "Bool" { return fmt.Errorf("invalid key field type: %s", f.MapKey) } fldType = strings.TrimSpace(fldType[index+1:]) diff --git a/tools/schema/generator/schema.go b/tools/schema/model/schema.go similarity index 63% rename from tools/schema/generator/schema.go rename to tools/schema/model/schema.go index 07ad36c581..99d3da9d6c 100644 --- a/tools/schema/generator/schema.go +++ b/tools/schema/model/schema.go @@ -1,10 +1,11 @@ // Copyright 2020 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -package generator +package model import ( "fmt" + "sort" "strings" "time" @@ -29,6 +30,7 @@ type FuncDefMap map[string]*FuncDef type SchemaDef struct { Name string `json:"name" yaml:"name"` Description string `json:"description" yaml:"description"` + Events StringMapMap `json:"events" yaml:"events"` Structs StringMapMap `json:"structs" yaml:"structs"` Typedefs StringMap `json:"typedefs" yaml:"typedefs"` State StringMap `json:"state" yaml:"state"` @@ -37,24 +39,12 @@ type SchemaDef struct { } type Func struct { - Access string - Kind string - FuncName string - Hname iscp.Hname - String string - Params []*Field - Results []*Field - Type string -} - -func (f *Func) nameLen(smallest int) int { - if len(f.Results) != 0 { - return 7 - } - if len(f.Params) != 0 { - return 6 - } - return smallest + Name string + Access string + Kind string + Hname iscp.Hname + Params []*Field + Results []*Field } type Struct struct { @@ -63,45 +53,38 @@ type Struct struct { } type Schema struct { - Name string - FullName string + ContractName string + PackageName string Description string KeyID int - ConstLen int - ConstNames []string - ConstValues []string CoreContracts bool SchemaTime time.Time + Events []*Struct Funcs []*Func Params []*Field Results []*Field StateVars []*Field Structs []*Struct Typedefs []*Field - Views []*Func } func NewSchema() *Schema { return &Schema{} } -func (s *Schema) appendConst(name, value string) { - if s.ConstLen < len(name) { - s.ConstLen = len(name) - } - s.ConstNames = append(s.ConstNames, name) - s.ConstValues = append(s.ConstValues, value) -} - func (s *Schema) Compile(schemaDef *SchemaDef) error { - s.FullName = strings.TrimSpace(schemaDef.Name) - if s.FullName == "" { + s.ContractName = strings.TrimSpace(schemaDef.Name) + if s.ContractName == "" { return fmt.Errorf("missing contract name") } - s.Name = lower(s.FullName) + s.PackageName = strings.ToLower(s.ContractName) s.Description = strings.TrimSpace(schemaDef.Description) - err := s.compileStructs(schemaDef) + err := s.compileEvents(schemaDef) + if err != nil { + return err + } + err = s.compileStructs(schemaDef) if err != nil { return err } @@ -119,15 +102,33 @@ func (s *Schema) Compile(schemaDef *SchemaDef) error { if err != nil { return err } + s.KeyID = 0 for _, name := range sortedFields(params) { - s.Params = append(s.Params, params[name]) + param := params[name] + param.KeyID = s.KeyID + s.KeyID++ + s.Params = append(s.Params, param) } for _, name := range sortedFields(results) { - s.Results = append(s.Results, results[name]) + result := results[name] + result.KeyID = s.KeyID + s.KeyID++ + s.Results = append(s.Results, result) } return s.compileStateVars(schemaDef) } +func (s *Schema) compileEvents(schemaDef *SchemaDef) error { + for _, eventName := range sortedMaps(schemaDef.Events) { + event, err := s.compileStruct("event", eventName, schemaDef.Events[eventName]) + if err != nil { + return err + } + s.Events = append(s.Events, event) + } + return nil +} + func (s *Schema) compileField(fldName, fldType string) (*Field, error) { field := &Field{} err := field.Compile(s, fldName, fldType) @@ -138,10 +139,10 @@ func (s *Schema) compileField(fldName, fldType string) (*Field, error) { } func (s *Schema) compileFuncs(schemaDef *SchemaDef, params, results *FieldMap, views bool) (err error) { - kind := "func" + funcKind := "func" templateFuncs := schemaDef.Funcs if views { - kind = "view" + funcKind = "view" templateFuncs = schemaDef.Views } for _, funcName := range sortedFuncDescs(templateFuncs) { @@ -149,19 +150,22 @@ func (s *Schema) compileFuncs(schemaDef *SchemaDef, params, results *FieldMap, v return fmt.Errorf("duplicate func/view name: %s", funcName) } funcDesc := templateFuncs[funcName] + if funcDesc == nil { + funcDesc = &FuncDef{} + } + f := &Func{} - f.String = funcName + f.Name = funcName + f.Kind = funcKind f.Hname = iscp.Hn(funcName) - // check for Hname collision + // check for Hname collision for _, other := range s.Funcs { if other.Hname == f.Hname { - return fmt.Errorf("hname collision: %d (%s and %s)", f.Hname, f.String, other.String) + return fmt.Errorf("hname collision: %d (%s and %s)", f.Hname, f.Name, other.Name) } } - f.Kind = capitalize(kind) - f.Type = capitalize(funcName) - f.FuncName = kind + f.Type + f.Access = funcDesc.Access f.Params, err = s.compileFuncFields(funcDesc.Params, params, "param") if err != nil { @@ -203,7 +207,7 @@ func (s *Schema) compileFuncFields(fieldMap StringMap, allFieldMap *FieldMap, wh return nil, fmt.Errorf("redefined %s alias: '%s' != '%s", what, existing.Alias, field.Alias) } if existing.Type != field.Type { - return nil, fmt.Errorf("redefined %s type", what) + return nil, fmt.Errorf("redefined %s type: %s", what, field.Name) } fields = append(fields, field) } @@ -227,42 +231,56 @@ func (s *Schema) compileStateVars(schemaDef *SchemaDef) error { return fmt.Errorf("duplicate var alias") } varAliases[varDef.Alias] = varDef.Alias + varDef.KeyID = s.KeyID + s.KeyID++ s.StateVars = append(s.StateVars, varDef) } return nil } func (s *Schema) compileStructs(schemaDef *SchemaDef) error { - for _, typeName := range sortedMaps(schemaDef.Structs) { - fieldMap := schemaDef.Structs[typeName] - typeDef := &Struct{} - typeDef.Name = typeName - fieldNames := make(StringMap) - fieldAliases := make(StringMap) - for _, fldName := range sortedKeys(fieldMap) { - fldType := fieldMap[fldName] - field, err := s.compileField(fldName, fldType) - if err != nil { - return err - } - if field.Optional { - return fmt.Errorf("type field cannot be optional") - } - if _, ok := fieldNames[field.Name]; ok { - return fmt.Errorf("duplicate field name") - } - fieldNames[field.Name] = field.Name - if _, ok := fieldAliases[field.Alias]; ok { - return fmt.Errorf("duplicate field alias") - } - fieldAliases[field.Alias] = field.Alias - typeDef.Fields = append(typeDef.Fields, field) + for _, structName := range sortedMaps(schemaDef.Structs) { + structDef, err := s.compileStruct("struct", structName, schemaDef.Structs[structName]) + if err != nil { + return err } - s.Structs = append(s.Structs, typeDef) + s.Structs = append(s.Structs, structDef) } return nil } +func (s *Schema) compileStruct(kind, structName string, structFields StringMap) (*Struct, error) { + structDef := &Struct{Name: structName} + fieldNames := make(StringMap) + fieldAliases := make(StringMap) + for _, fldName := range sortedKeys(structFields) { + fldType := structFields[fldName] + field, err := s.compileField(fldName, fldType) + if err != nil { + return nil, err + } + if field.Optional { + return nil, fmt.Errorf("%s field cannot be optional", kind) + } + if field.Array { + return nil, fmt.Errorf("%s field cannot be an array", kind) + } + if field.MapKey != "" { + return nil, fmt.Errorf("%s field cannot be a map", kind) + } + if _, ok := fieldNames[field.Name]; ok { + return nil, fmt.Errorf("duplicate %s field name", kind) + } + fieldNames[field.Name] = field.Name + if _, ok := fieldAliases[field.Alias]; ok { + return nil, fmt.Errorf("duplicate %s field alias", kind) + } + fieldAliases[field.Alias] = field.Alias + structDef.Fields = append(structDef.Fields, field) + } + return structDef, nil +} + func (s *Schema) compileTypeDefs(schemaDef *SchemaDef) error { varNames := make(StringMap) varAliases := make(StringMap) @@ -285,11 +303,38 @@ func (s *Schema) compileTypeDefs(schemaDef *SchemaDef) error { return nil } -func (s *Schema) flushConsts(printer func(name string, value string, padLen int)) { - for i, name := range s.ConstNames { - printer(name, s.ConstValues[i], s.ConstLen) +func sortedFields(dict FieldMap) []string { + keys := make([]string, 0) + for key := range dict { + keys = append(keys, key) + } + sort.Strings(keys) + return keys +} + +func sortedFuncDescs(dict FuncDefMap) []string { + keys := make([]string, 0) + for key := range dict { + keys = append(keys, key) + } + sort.Strings(keys) + return keys +} + +func sortedKeys(dict StringMap) []string { + keys := make([]string, 0) + for key := range dict { + keys = append(keys, key) + } + sort.Strings(keys) + return keys +} + +func sortedMaps(dict StringMapMap) []string { + keys := make([]string, 0) + for key := range dict { + keys = append(keys, key) } - s.ConstLen = 0 - s.ConstNames = nil - s.ConstValues = nil + sort.Strings(keys) + return keys } diff --git a/tools/wasp-cli/chain/blocklog.go b/tools/wasp-cli/chain/blocklog.go index a0fd92d423..0b087bb211 100644 --- a/tools/wasp-cli/chain/blocklog.go +++ b/tools/wasp-cli/chain/blocklog.go @@ -6,6 +6,7 @@ import ( "time" "github.com/iotaledger/wasp/packages/iscp" + "github.com/iotaledger/wasp/packages/iscp/request" "github.com/iotaledger/wasp/packages/kv/codec" "github.com/iotaledger/wasp/packages/kv/collections" "github.com/iotaledger/wasp/packages/kv/dict" @@ -61,25 +62,59 @@ func logRequestsInBlock(index uint32) { }) log.Check(err) arr := collections.NewArray16ReadOnly(ret, blocklog.ParamRequestRecord) - header := []string{"request ID", "kind", "error"} - rows := make([][]string, arr.MustLen()) for i := uint16(0); i < arr.MustLen(); i++ { - req, err := blocklog.RequestReceiptFromBytes(arr.MustGetAt(i)) + receipt, err := blocklog.RequestReceiptFromBytes(arr.MustGetAt(i)) log.Check(err) + logReceipt(receipt, i) + } +} - kind := "on-ledger" - if req.Request.IsOffLedger() { - kind = "off-ledger" - } +func logReceipt(receipt *blocklog.RequestReceipt, index ...uint16) { + req := receipt.Request - rows[i] = []string{ - req.Request.ID().Base58(), - kind, - fmt.Sprintf("%q", req.Error), - } + feePrepaid := "no" + if req.IsFeePrepaid() { + feePrepaid = "yes" } - log.Printf("Total %d requests\n", arr.MustLen()) - log.PrintTable(header, rows) + + kind := "on-ledger" + if req.IsOffLedger() { + kind = "off-ledger" + } + + timestamp := "n/a" + if !req.IsOffLedger() { + timestamp = req.Timestamp().UTC().Format(time.RFC3339) + } + + // TODO: use req.Params() instead (buggy atm) + args := req.(request.SolidifiableRequest).Args() + var argsTree interface{} = "(empty)" + if len(args) > 0 { + argsTree = dict.Dict(args) + } + + errMsg := "(empty)" + if receipt.Error != "" { + errMsg = fmt.Sprintf("%q", receipt.Error) + } + + tree := []log.TreeItem{ + {K: "Kind", V: kind}, + {K: "Fee prepaid", V: feePrepaid}, + {K: "Sender", V: req.SenderAccount().String()}, + {K: "Contract Hname", V: req.Target().Contract.String()}, + {K: "Entry point", V: req.Target().EntryPoint.String()}, + {K: "Timestamp", V: timestamp}, + {K: "Arguments", V: argsTree}, + {K: "Error", V: errMsg}, + } + if len(index) > 0 { + log.Printf("Request #%d (%s):\n", index[0], req.ID().Base58()) + } else { + log.Printf("Request %s:\n", req.ID().Base58()) + } + log.PrintTree(tree, 2, 2) } func logEventsInBlock(index uint32) { @@ -108,10 +143,11 @@ func requestCmd() *cobra.Command { receipt, err := blocklog.RequestReceiptFromBytes(ret.MustGet(blocklog.ParamRequestRecord)) log.Check(err) - log.Printf("request included in block %d\n, %s\n", blockIndex, receipt.String()) - + log.Printf("Request found in block %d\n\n", blockIndex) + logReceipt(receipt) log.Printf("\n") logEventsInRequest(reqID) + log.Printf("\n") }, } } diff --git a/tools/wasp-cli/chain/evm.go b/tools/wasp-cli/chain/evm.go index 2145a3c817..19fad4cda2 100644 --- a/tools/wasp-cli/chain/evm.go +++ b/tools/wasp-cli/chain/evm.go @@ -4,14 +4,19 @@ package chain import ( + "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/wasp/client/chainclient" "github.com/iotaledger/wasp/contracts/native/evm" "github.com/iotaledger/wasp/contracts/native/evm/evmchain" "github.com/iotaledger/wasp/packages/evm/evmtypes" "github.com/iotaledger/wasp/packages/evm/jsonrpc" + "github.com/iotaledger/wasp/packages/iscp/colored" + "github.com/iotaledger/wasp/packages/iscp/requestargs" "github.com/iotaledger/wasp/packages/kv/codec" "github.com/iotaledger/wasp/packages/kv/dict" "github.com/iotaledger/wasp/tools/evm/evmcli" "github.com/iotaledger/wasp/tools/wasp-cli/log" + "github.com/iotaledger/wasp/tools/wasp-cli/util" "github.com/spf13/cobra" ) @@ -38,11 +43,30 @@ func initEVMDeploy(evmCmd *cobra.Command) { Use: "deploy", Short: "Deploy the evmchain/evmlight contract (i.e. create a new EVM chain)", Run: func(cmd *cobra.Command, args []string) { + blockTime := deployParams.BlockTime() + blockKeepAmount := deployParams.BlockKeepAmount() deployContract(deployParams.Name(), deployParams.Description(), deployParams.EVMFlavor().ProgramHash, dict.Dict{ - evm.FieldChainID: codec.EncodeUint16(uint16(deployParams.ChainID)), - evm.FieldGenesisAlloc: evmtypes.EncodeGenesisAlloc(deployParams.GetGenesis(nil)), + evm.FieldChainID: codec.EncodeUint16(uint16(deployParams.ChainID)), + evm.FieldGenesisAlloc: evmtypes.EncodeGenesisAlloc(deployParams.GetGenesis(nil)), + evm.FieldGasLimit: codec.EncodeUint64(deployParams.GasLimit), + evm.FieldBlockKeepAmount: codec.EncodeInt32(blockKeepAmount), }) log.Printf("%s contract successfully deployed.\n", deployParams.Name()) + + if blockTime > 0 { + log.Printf("Setting block time to %ds...\n", blockTime) + util.WithSCTransaction(GetCurrentChainID(), func() (*ledgerstate.Transaction, error) { + return SCClient(deployParams.EVMFlavor().Hname()).PostRequest( + evm.FuncSetBlockTime.Name, + chainclient.PostRequestParams{ + Transfer: colored.NewBalancesForIotas(1), + Args: requestargs.New().AddEncodeSimple( + evm.FieldBlockTime, codec.EncodeUint32(blockTime), + ), + }, + ) + }) + } }, } evmCmd.AddCommand(evmDeployCmd) diff --git a/tools/wasp-cli/log/log.go b/tools/wasp-cli/log/log.go index 670e360eb5..51a64f1e08 100644 --- a/tools/wasp-cli/log/log.go +++ b/tools/wasp-cli/log/log.go @@ -1,11 +1,13 @@ package log import ( + "encoding/hex" "fmt" "os" "strings" "text/tabwriter" + "github.com/iotaledger/wasp/packages/kv/dict" "github.com/spf13/cobra" ) @@ -73,3 +75,41 @@ func makeSeparator(header []string) []string { } return ret } + +type TreeItem struct { + K string + V interface{} +} + +func PrintTree(node interface{}, tab, tabwidth int) { + indent := strings.Repeat(" ", tab) + switch node := node.(type) { + case []TreeItem: + for _, item := range node { + fmt.Printf("%s%s: ", indent, item.K) + if s, ok := item.V.(string); ok { + fmt.Printf("%s\n", s) + } else { + fmt.Print("\n") + PrintTree(item.V, tab+tabwidth, tabwidth) + } + } + case dict.Dict: + if len(node) == 0 { + fmt.Printf("%s(empty)", indent) + return + } + tree := make([]TreeItem, 0, len(node)) + for k, v := range node { + tree = append(tree, TreeItem{ + K: fmt.Sprintf("%q", string(k)), + V: fmt.Sprintf("0x%s", hex.EncodeToString(v)), + }) + } + PrintTree(tree, tab, tabwidth) + case string: + fmt.Printf("%s%s\n", indent, node) + default: + panic(fmt.Sprintf("no handler of value of type %T", node)) + } +} diff --git a/tools/wasp-cli/main.go b/tools/wasp-cli/main.go index 2601c47169..9a63f02e89 100644 --- a/tools/wasp-cli/main.go +++ b/tools/wasp-cli/main.go @@ -9,6 +9,7 @@ import ( "github.com/iotaledger/wasp/tools/wasp-cli/config" "github.com/iotaledger/wasp/tools/wasp-cli/decode" "github.com/iotaledger/wasp/tools/wasp-cli/log" + "github.com/iotaledger/wasp/tools/wasp-cli/metrics" "github.com/iotaledger/wasp/tools/wasp-cli/peering" "github.com/iotaledger/wasp/tools/wasp-cli/wallet" "github.com/spf13/cobra" @@ -35,6 +36,7 @@ func init() { chain.Init(rootCmd) decode.Init(rootCmd) peering.Init(rootCmd) + metrics.Init(rootCmd) } func main() { diff --git a/tools/wasp-cli/metrics/metrics.go b/tools/wasp-cli/metrics/metrics.go new file mode 100644 index 0000000000..b14acd0388 --- /dev/null +++ b/tools/wasp-cli/metrics/metrics.go @@ -0,0 +1,24 @@ +package metrics + +import ( + "github.com/iotaledger/wasp/tools/wasp-cli/log" + "github.com/spf13/cobra" +) + +var metricsCmd = &cobra.Command{ + Use: "metrics ", + Short: "Show current value of collected metrics of some component", + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + log.Check(cmd.Help()) + }, +} + +var chainIDStr string + +func Init(rootCmd *cobra.Command) { + rootCmd.AddCommand(metricsCmd) + + metricsCmd.AddCommand(nodeconnMetricsCmd) + metricsCmd.PersistentFlags().StringVarP(&chainIDStr, "chain", "", "", "chain ID for which metrics should be displayed") +} diff --git a/tools/wasp-cli/metrics/nodeconn.go b/tools/wasp-cli/metrics/nodeconn.go new file mode 100644 index 0000000000..ebe05c46ac --- /dev/null +++ b/tools/wasp-cli/metrics/nodeconn.go @@ -0,0 +1,70 @@ +package metrics + +import ( + "fmt" + "strings" + + "github.com/iotaledger/wasp/packages/iscp" + "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" +) + +const maxMessageLen = 80 + +var nodeconnMetricsCmd = &cobra.Command{ + Use: "nodeconn", + Short: "Show current value of collected metrics of connection to L1", + Args: cobra.NoArgs, + Run: func(cmd *cobra.Command, args []string) { + client := config.WaspClient() + if chainIDStr == "" { + nodeconnMetrics, err := client.GetNodeConnectionMetrics() + log.Check(err) + log.Printf("Following chains subscribed to L1 events:\n") + for _, s := range nodeconnMetrics.Subscribed { + log.Printf("\t%s\n", s) + } + printMessagesMetrics(&nodeconnMetrics.NodeConnectionMessagesMetrics) + } else { + chid, err := iscp.ChainIDFromBase58(chainIDStr) + log.Check(err) + msgsMetrics, err := client.GetChainNodeConnectionMetrics(chid) + log.Check(err) + printMessagesMetrics(msgsMetrics) + } + }, +} + +func printMessagesMetrics(msgsMetrics *model.NodeConnectionMessagesMetrics) { + header := []string{"Message name", "", "Total", "Last time", "Last message"} + table := make([][]string, 8) + table[0] = makeMessagesMetricsTableRow("Pull state", false, msgsMetrics.OutPullState) + table[1] = makeMessagesMetricsTableRow("Pull tx inclusion state", false, msgsMetrics.OutPullTransactionInclusionState) + table[2] = makeMessagesMetricsTableRow("Pull confirmed output", false, msgsMetrics.OutPullConfirmedOutput) + table[3] = makeMessagesMetricsTableRow("Post transaction", false, msgsMetrics.OutPostTransaction) + table[4] = makeMessagesMetricsTableRow("Transaction", true, msgsMetrics.InTransaction) + table[5] = makeMessagesMetricsTableRow("Inclusion state", true, msgsMetrics.InInclusionState) + table[6] = makeMessagesMetricsTableRow("Output", true, msgsMetrics.InOutput) + table[7] = makeMessagesMetricsTableRow("Unspent alias output", true, msgsMetrics.InUnspentAliasOutput) + log.PrintTable(header, table) +} + +func makeMessagesMetricsTableRow(name string, isIn bool, ncmm *model.NodeConnectionMessageMetrics) []string { + res := make([]string, 5) + res[0] = name + if isIn { + res[1] = "IN" + } else { + res[1] = "OUT" + } + res[2] = fmt.Sprintf("%v", ncmm.Total) + res[3] = ncmm.LastEvent.String() + res[4] = ncmm.LastMessage + if len(res[4]) > maxMessageLen { + res[4] = res[4][:maxMessageLen] + } + res[4] = strings.Replace(res[4], "\n", " ", -1) + return res +} diff --git a/tools/wasp-cli/util/types.go b/tools/wasp-cli/util/types.go index 5e792c341d..6a45287056 100644 --- a/tools/wasp-cli/util/types.go +++ b/tools/wasp-cli/util/types.go @@ -7,6 +7,7 @@ import ( "strconv" "github.com/iotaledger/goshimmer/packages/ledgerstate" + "github.com/iotaledger/wasp/packages/hashing" "github.com/iotaledger/wasp/packages/iscp" "github.com/iotaledger/wasp/packages/kv" "github.com/iotaledger/wasp/packages/kv/codec" @@ -15,67 +16,160 @@ import ( "github.com/mr-tron/base58" ) +//nolint:funlen func ValueFromString(vtype, s string) []byte { switch vtype { - case "uint64": - n, err := strconv.Atoi(s) + case "address": + addr, err := ledgerstate.AddressFromBase58EncodedString(s) log.Check(err) - return codec.EncodeUint64(uint64(n)) - case "uint32": - n, err := strconv.Atoi(s) + return addr.Bytes() + case "agentid": + agentid, err := iscp.NewAgentIDFromString(s) log.Check(err) - return codec.EncodeUint32(uint32(n)) - case "int32": - n, err := strconv.Atoi(s) //nolint:gosec // potential int32 overflow + return agentid.Bytes() + case "bool": + b, err := strconv.ParseBool(s) log.Check(err) - return codec.EncodeInt32(int32(n)) - case "int", "int64": - n, err := strconv.Atoi(s) + return codec.EncodeBool(b) + case "bytes", "base58": + b, err := base58.Decode(s) + log.Check(err) + return b + case "chainid": + chainid, err := iscp.ChainIDFromString(s) log.Check(err) - return codec.EncodeInt64(int64(n)) + return chainid.Bytes() case "color": col, err := ledgerstate.ColorFromBase58EncodedString(s) log.Check(err) return col.Bytes() - case "agentid": - agentid, err := iscp.NewAgentIDFromString(s) - log.Check(err) - return agentid.Bytes() case "file": return ReadFile(s) + case "hash": + hash, err := hashing.HashValueFromBase58(s) + log.Check(err) + return hash.Bytes() + case "hname": + hn, err := iscp.HnameFromString(s) + log.Check(err) + return hn.Bytes() + case "int8": + n, err := strconv.ParseInt(s, 10, 8) + log.Check(err) + return codec.EncodeInt8(int8(n)) + case "int16": + n, err := strconv.ParseInt(s, 10, 16) + log.Check(err) + return codec.EncodeInt16(int16(n)) + case "int32": + n, err := strconv.ParseInt(s, 10, 32) + log.Check(err) + return codec.EncodeInt32(int32(n)) + case "int64", "int": + n, err := strconv.ParseInt(s, 10, 64) + log.Check(err) + return codec.EncodeInt64(n) + case "requestid": + rid, err := iscp.RequestIDFromString(s) + log.Check(err) + return rid.Bytes() case "string": return []byte(s) - case "bytes", "base58": - b, err := base58.Decode(s) + case "uint8": + n, err := strconv.ParseUint(s, 10, 8) log.Check(err) - return b + return codec.EncodeUint8(uint8(n)) + case "uint16": + n, err := strconv.ParseUint(s, 10, 16) + log.Check(err) + return codec.EncodeUint16(uint16(n)) + case "uint32": + n, err := strconv.ParseUint(s, 10, 32) + log.Check(err) + return codec.EncodeUint32(uint32(n)) + case "uint64": + n, err := strconv.ParseUint(s, 10, 64) + log.Check(err) + return codec.EncodeUint64(n) } log.Fatalf("ValueFromString: No handler for type %s", vtype) return nil } +//nolint:funlen func ValueToString(vtype string, v []byte) string { switch vtype { - case "color": - col, err := codec.DecodeColor(v) + case "address": + addr, err := codec.DecodeAddress(v) log.Check(err) - return col.String() + return addr.Base58() case "agentid": aid, err := codec.DecodeAgentID(v) log.Check(err) return aid.String() - case "uint64": - n, err := codec.DecodeUint64(v) + case "bool": + b, err := codec.DecodeBool(v) + log.Check(err) + if b { + return "true" + } + return "false" + case "bytes", "base58": + return base58.Encode(v) + case "chainid": + cid, err := codec.DecodeChainID(v) + log.Check(err) + return cid.String() + case "color": + col, err := codec.DecodeColor(v) + log.Check(err) + return col.String() + case "hash": + hash, err := codec.DecodeHashValue(v) + log.Check(err) + return hash.String() + case "hname": + hn, err := codec.DecodeHname(v) + log.Check(err) + return hn.String() + case "int8": + n, err := codec.DecodeInt8(v) + log.Check(err) + return fmt.Sprintf("%d", n) + case "int16": + n, err := codec.DecodeInt16(v) log.Check(err) return fmt.Sprintf("%d", n) - case "int", "int64": + case "int32": + n, err := codec.DecodeInt32(v) + log.Check(err) + return fmt.Sprintf("%d", n) + case "int64", "int": n, err := codec.DecodeInt64(v) log.Check(err) return fmt.Sprintf("%d", n) + case "requestid": + rid, err := codec.DecodeRequestID(v) + log.Check(err) + return rid.String() case "string": return fmt.Sprintf("%q", string(v)) - case "bytes", "base58": - return base58.Encode(v) + case "uint8": + n, err := codec.DecodeUint8(v) + log.Check(err) + return fmt.Sprintf("%d", n) + case "uint16": + n, err := codec.DecodeUint16(v) + log.Check(err) + return fmt.Sprintf("%d", n) + case "uint32": + n, err := codec.DecodeUint32(v) + log.Check(err) + return fmt.Sprintf("%d", n) + case "uint64": + n, err := codec.DecodeUint64(v) + log.Check(err) + return fmt.Sprintf("%d", n) } log.Fatalf("ValueToString: No handler for type %s", vtype) return ""