diff --git a/Makefile b/Makefile index 79beaaa9..66ad9ec2 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,8 @@ PRECOMPILE_DIR := ./wasmx/x/wasmx/vm/precompiles TINYGO_TARGETS := \ wasmx-fsm:28.finite_state_machine.wasm \ wasmx-raft-lib:2a.raft_library.wasm \ - wasmx-raftp2p-lib:36.raftp2p_library.wasm + wasmx-raftp2p-lib:36.raftp2p_library.wasm \ + wasmx-ondemand-single-lib:65.wasmx_ondemand_single_library.wasm # wasmx-gov:35.gov_0.0.1.wasm \ # wasmx-gov-continuous:37.gov_cont_0.0.1.wasm \ diff --git a/tests/testdata/tinygo/wasmx-ondemand-single-lib/cmd/main.go b/tests/testdata/tinygo/wasmx-ondemand-single-lib/cmd/main.go new file mode 100644 index 00000000..ef495020 --- /dev/null +++ b/tests/testdata/tinygo/wasmx-ondemand-single-lib/cmd/main.go @@ -0,0 +1,112 @@ +package main + +import ( + "encoding/json" + + wasmx "github.com/loredanacirstea/wasmx-env/lib" + fsm "github.com/loredanacirstea/wasmx-fsm/lib" + lib "github.com/loredanacirstea/wasmx-ondemand-single-lib/lib" + raft "github.com/loredanacirstea/wasmx-raft-lib/lib" + raftp2p "github.com/loredanacirstea/wasmx-raftp2p-lib/lib" +) + +//go:wasm-module wasmx +//export memory_ptrlen_i64_1 +func Memory_ptrlen_i64_1() {} + +//go:wasm-module wasmx +//export wasmx_env_i64_2 +func Wasmx_env_i64_2() {} + +//go:wasm-module consensus +//export wasmx_consensus_json_i64_1 +func Wasmx_consensus_json_i64_1() {} + +//go:wasm-module wasmxcore +//export wasmx_env_core_i64_1 +func Wasmx_env_core_i64_1() {} + +//go:wasm-module crosschain +//export wasmx_crosschain_json_i64_1 +func Wasmx_crosschain_json_i64_1() {} + +//go:wasm-module multichain +//export wasmx_multichain_json_i64_1 +func Wasmx_multichain_json_i64_1() {} + +//go:wasm-module p2p +//export wasmx_p2p_json_i64_1 +func Wasmx_p2p_json_i64_1() {} + +//go:wasm-module wasmxcore +//export wasmx_nondeterministic_1 +func Wasmx_nondeterministic_1() {} + +//go:wasm-module wasmx-ondemand-single +//export instantiate +func Instantiate() {} + +func main() { + // Only internal + wasmx.OnlyInternal(lib.MODULE_NAME, "") + + databz := wasmx.GetCallData() + var calld fsm.ExternalActionCallData + if err := json.Unmarshal(databz, &calld); err != nil { + lib.Revert("invalid call data: " + err.Error() + ": " + string(databz)) + return + } + + // Route methods + switch calld.Method { + case "ifNewTransaction": + ok, err := raftp2p.IfNewTransaction(calld.Params, calld.Event) + if err != nil { + lib.Revert(err.Error()) + return + } + res := raft.WrapGuard(ok) + wasmx.Finish(res) + return + case "addToMempool": + if err := raftp2p.AddToMempool(calld.Params, calld.Event); err != nil { + lib.Revert(err.Error()) + return + } + case "setupNode": + if err := lib.SetupNode(calld.Params, calld.Event); err != nil { + lib.Revert(err.Error()) + return + } + case "sendNewTransactionResponse": + if err := raft.SendNewTransactionResponse(nil, fsm.EventObject{}); err != nil { + lib.Revert(err.Error()) + return + } + case "newBlock": + if err := lib.NewBlock(); err != nil { + lib.Revert(err.Error()) + return + } + case "setup": + if err := raft.Setup(calld.Params, calld.Event); err != nil { + lib.Revert(err.Error()) + return + } + case "StartNode": + // TODO + if err := lib.StartNode(); err != nil { + lib.Revert(err.Error()) + return + } + case "rollback": + if err := raft.Rollback(calld.Params, calld.Event); err != nil { + lib.Revert("Rollback failed: " + err.Error()) + return + } + default: + wasmx.Revert(append([]byte("invalid function call data: "), databz...)) + return + } + wasmx.Finish(wasmx.GetFinishData()) +} diff --git a/tests/testdata/tinygo/wasmx-ondemand-single-lib/diagram/code.json b/tests/testdata/tinygo/wasmx-ondemand-single-lib/diagram/code.json new file mode 100644 index 00000000..962370cf --- /dev/null +++ b/tests/testdata/tinygo/wasmx-ondemand-single-lib/diagram/code.json @@ -0,0 +1 @@ +{"context":[{"key":"maxLevel","value":0},{"key":"blockTimeout","value":"blockTimeoutInternal"},{"key":"currentLevel","value":0},{"key":"membersCount","value":1},{"key":"blockTimeoutInternal","value":3000}],"id":"OnDemand-Single","initial":"uninitialized","states":[{"name":"uninitialized","after":[],"always":[],"on":[{"name":"initialize","transitions":[{"target":"#OnDemand-Single.initialized","guard":null,"actions":[],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]},{"name":"initialized","after":[],"always":[],"on":[],"entry":[],"exit":[],"initial":"unstarted","states":[{"name":"unstarted","after":[],"always":[],"on":[{"name":"start","transitions":[{"target":"#OnDemand-Single.initialized.started","guard":null,"actions":[{"type":"StartNode","params":[]}],"meta":[]}]},{"name":"setup","transitions":[{"target":"#OnDemand-Single.initialized.unstarted","guard":null,"actions":[{"type":"setup","params":[]}],"meta":[]}]},{"name":"prestart","transitions":[{"target":"#OnDemand-Single.initialized.prestart","guard":null,"actions":[],"meta":[]}]},{"name":"setupNode","transitions":[{"target":"#OnDemand-Single.initialized.unstarted","guard":null,"actions":[{"type":"setupNode","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]},{"name":"started","after":[],"always":[],"on":[{"name":"start","transitions":[{"target":"#OnDemand-Single.initialized.started","guard":null,"actions":[{"type":"StartNode","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"active","states":[{"name":"active","after":[],"always":[],"on":[{"name":"newTransaction","transitions":[{"target":"#OnDemand-Single.initialized.started.proposer","guard":{"type":"ifNewTransaction","params":[]},"actions":[{"type":"addToMempool","params":[]},{"type":"sendNewTransactionResponse","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]},{"name":"proposer","after":[],"always":[{"name":"always","transitions":[{"target":"#OnDemand-Single.initialized.started.active","actions":[{"type":"newBlock","params":[]}],"guard":null,"meta":[]}]}],"on":[],"entry":[],"exit":[],"initial":"","states":[]}]},{"name":"prestart","after":[{"name":"500","transitions":[{"target":"#OnDemand-Single.initialized.started","guard":null,"actions":[],"meta":[]}]}],"always":[],"on":[],"entry":[],"exit":[],"initial":"","states":[]}]}]} diff --git a/tests/testdata/tinygo/wasmx-ondemand-single-lib/diagram/stately.ts b/tests/testdata/tinygo/wasmx-ondemand-single-lib/diagram/stately.ts new file mode 100644 index 00000000..6f8e3311 --- /dev/null +++ b/tests/testdata/tinygo/wasmx-ondemand-single-lib/diagram/stately.ts @@ -0,0 +1,133 @@ +// @ts-nocheck + +import { createMachine } from "xstate"; + +export const machine = createMachine({ + context: { + maxLevel: 0, + blockTimeout: "blockTimeoutInternal", + currentLevel: 0, + membersCount: 1, + blockTimeoutInternal: 3000, + }, + id: "OnDemand-Single", + initial: "uninitialized", + states: { + uninitialized: { + on: { + initialize: { + target: "initialized", + }, + }, + }, + initialized: { + initial: "unstarted", + states: { + unstarted: { + on: { + start: { + target: "started", + actions: { + type: "StartNode", + }, + }, + setup: { + target: "unstarted", + actions: { + type: "setup", + }, + }, + prestart: { + target: "prestart", + }, + setupNode: { + target: "unstarted", + actions: { + type: "setupNode", + }, + }, + }, + }, + started: { + initial: "active", + on: { + start: { + target: "started", + actions: { + type: "StartNode", + }, + }, + }, + states: { + active: { + on: { + newTransaction: { + target: "proposer", + actions: [ + { + type: "addToMempool", + }, + { + type: "sendNewTransactionResponse", + }, + ], + guard: { + type: "ifNewTransaction", + }, + }, + }, + }, + proposer: { + always: { + target: "active", + actions: { + type: "newBlock", + }, + }, + }, + }, + }, + prestart: { + after: { + "500": { + target: "started", + }, + }, + }, + }, + }, + }, +}).withConfig({ + actions: { + StartNode: function (context, event) { + // Add your action code here + // ... + }, + setup: function (context, event) { + // Add your action code here + // ... + }, + setupNode: function (context, event) { + // Add your action code here + // ... + }, + addToMempool: function (context, event) { + // Add your action code here + // ... + }, + sendNewTransactionResponse: function (context, event) { + // Add your action code here + // ... + }, + newBlock: function (context, event) { + // Add your action code here + // ... + }, + }, + guards: { + ifNewTransaction: function (context, event) { + // Add your guard condition here + return true; + }, + }, +}); diff --git a/tests/testdata/tinygo/wasmx-ondemand-single-lib/go.mod b/tests/testdata/tinygo/wasmx-ondemand-single-lib/go.mod new file mode 100644 index 00000000..748b7428 --- /dev/null +++ b/tests/testdata/tinygo/wasmx-ondemand-single-lib/go.mod @@ -0,0 +1,64 @@ +module github.com/loredanacirstea/wasmx-ondemand-single-lib + +go 1.24 + +toolchain go1.24.4 + +require github.com/loredanacirstea/wasmx-env v0.0.0 + +require github.com/loredanacirstea/wasmx-fsm v0.0.0 + +require github.com/loredanacirstea/wasmx-env-core v0.0.0 // indirect + +require github.com/loredanacirstea/wasmx-env-consensus v0.0.0 // indirect + +require github.com/loredanacirstea/wasmx-env-crosschain v0.0.0 // indirect + +require github.com/loredanacirstea/wasmx-staking v0.0.0 // indirect + +require github.com/loredanacirstea/wasmx-consensus-utils v0.0.0 // indirect + +require github.com/loredanacirstea/wasmx-blocks v0.0.0 // indirect + +require github.com/loredanacirstea/wasmx-env-multichain v0.0.0 // indirect + +require github.com/loredanacirstea/wasmx-raft-lib v0.0.0 + +require ( + github.com/loredanacirstea/wasmx-env-p2p v0.0.0 + github.com/loredanacirstea/wasmx-raftp2p-lib v0.0.0 +) + +require ( + cosmossdk.io/math v1.5.3 // indirect + github.com/loredanacirstea/wasmx-env-utils v0.0.0 // indirect + github.com/loredanacirstea/wasmx-utils v0.0.0 // indirect +) + +replace github.com/loredanacirstea/wasmx-env v0.0.0 => ../wasmx-env + +replace github.com/loredanacirstea/wasmx-env-utils v0.0.0 => ../wasmx-env-utils + +replace github.com/loredanacirstea/wasmx-utils v0.0.0 => ../wasmx-utils + +replace github.com/loredanacirstea/wasmx-fsm v0.0.0 => ../wasmx-fsm + +replace github.com/loredanacirstea/wasmx-env-core v0.0.0 => ../wasmx-env-core + +replace github.com/loredanacirstea/wasmx-env-crosschain v0.0.0 => ../wasmx-env-crosschain + +replace github.com/loredanacirstea/wasmx-env-consensus v0.0.0 => ../wasmx-env-consensus + +replace github.com/loredanacirstea/wasmx-staking v0.0.0 => ../wasmx-staking + +replace github.com/loredanacirstea/wasmx-consensus-utils v0.0.0 => ../wasmx-consensus-utils + +replace github.com/loredanacirstea/wasmx-blocks v0.0.0 => ../wasmx-blocks + +replace github.com/loredanacirstea/wasmx-env-multichain v0.0.0 => ../wasmx-env-multichain + +replace github.com/loredanacirstea/wasmx-raft-lib v0.0.0 => ../wasmx-raft-lib + +replace github.com/loredanacirstea/wasmx-raftp2p-lib v0.0.0 => ../wasmx-raftp2p-lib + +replace github.com/loredanacirstea/wasmx-env-p2p v0.0.0 => ../wasmx-env-p2p diff --git a/tests/testdata/tinygo/wasmx-ondemand-single-lib/go.sum b/tests/testdata/tinygo/wasmx-ondemand-single-lib/go.sum new file mode 100644 index 00000000..18cf05fc --- /dev/null +++ b/tests/testdata/tinygo/wasmx-ondemand-single-lib/go.sum @@ -0,0 +1,12 @@ +cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U= +cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/tests/testdata/tinygo/wasmx-ondemand-single-lib/lib/actions.go b/tests/testdata/tinygo/wasmx-ondemand-single-lib/lib/actions.go new file mode 100644 index 00000000..e5decc8c --- /dev/null +++ b/tests/testdata/tinygo/wasmx-ondemand-single-lib/lib/actions.go @@ -0,0 +1,109 @@ +package lib + +import ( + "encoding/base64" + "encoding/json" + "fmt" + + p2p "github.com/loredanacirstea/wasmx-env-p2p/lib" + wasmx "github.com/loredanacirstea/wasmx-env/lib" + fsm "github.com/loredanacirstea/wasmx-fsm/lib" + raftlib "github.com/loredanacirstea/wasmx-raft-lib/lib" +) + +// SetupNode initializes local state from InitChainSetup and peers (AS parity) +func SetupNode(_ []fsm.ActionParam, event fsm.EventObject) error { + // read base64-encoded InitChainSetup from event params (key: "data") + dataB64 := "" + for _, p := range event.Params { + if p.Key == "data" { + dataB64 = p.Value + break + } + } + if dataB64 == "" { + return fmt.Errorf("no initChainSetup found") + } + raw, err := base64.StdEncoding.DecodeString(dataB64) + if err != nil { + return err + } + // TODO remove validator private key from logs in initChainSetup + LoggerDebug("setupNode", []string{"initChainSetup", string(raw)}) + + // Reset commit/applied + if err := raftlib.SetLastApplied(raftlib.LOG_START); err != nil { + return err + } + + // Decode into raftlib.InitChainSetup + var init raftlib.InitChainSetup + if err := json.Unmarshal(raw, &init); err != nil { + return err + } + + // Set current node ID (for single node, this is always 0) + if err := raftlib.SetCurrentNodeId(0); err != nil { + return err + } + + // For single-node consensus, create minimal node info with just ourselves + // This is needed because raft-lib functions expect node info to be populated + selfNode := []p2p.NodeInfo{ + { + Address: wasmx.Bech32String(init.ValidatorAddress), + Node: p2p.NetworkNode{IP: "127.0.0.1"}, // Minimal placeholder + OutOfSync: false, + }, + } + if err := raftlib.SetNodeIPs(selfNode); err != nil { + return err + } + + // Initialize chain state and store consensus params for next height + if err := raftlib.InitChain(init); err != nil { + return err + } + + // Initialize Next/Match index arrays with length 1 (single node) + return raftlib.InitializeIndexArrays(1) +} + +func StartNode() error { + return nil +} + +// NewBlock builds and finalizes a block immediately for single-node on-demand consensus +func NewBlock() error { + // Step 1: Build the block proposal using the raft-lib ProposeBlock + // This will batch transactions from mempool and append to log + if err := raftlib.ProposeBlock(nil, fsm.EventObject{}); err != nil { + return fmt.Errorf("failed to propose block: %v", err) + } + + // Step 2: Get the newly created log entry (should be at last log index) + lastLogIndex, err := raftlib.GetLastLogIndex() + if err != nil { + return fmt.Errorf("failed to get last log index: %v", err) + } + + // Step 3: Retrieve the block entry from the log + entry, err := raftlib.GetLogEntryAggregate(lastLogIndex) + if err != nil { + return fmt.Errorf("failed to get log entry at index %d: %v", lastLogIndex, err) + } + if entry == nil { + return fmt.Errorf("log entry is nil at index %d", lastLogIndex) + } + + LoggerInfo("finalizing block immediately", []string{ + "height", raftlib.Int64ToString(entry.Index), + "termId", raftlib.Int32ToString(entry.TermID), + }) + + _, err = raftlib.StartBlockFinalizationInternal(entry, false) + if err != nil { + return fmt.Errorf("failed to finalize block at index %d: %v", lastLogIndex, err) + } + return nil +} diff --git a/tests/testdata/tinygo/wasmx-ondemand-single-lib/lib/types.go b/tests/testdata/tinygo/wasmx-ondemand-single-lib/lib/types.go new file mode 100644 index 00000000..6225eda1 --- /dev/null +++ b/tests/testdata/tinygo/wasmx-ondemand-single-lib/lib/types.go @@ -0,0 +1,6 @@ +package lib + +// Module identification and protocol constants +const ( + MODULE_NAME = "ondemand_single" +) diff --git a/tests/testdata/tinygo/wasmx-ondemand-single-lib/lib/utils.go b/tests/testdata/tinygo/wasmx-ondemand-single-lib/lib/utils.go new file mode 100644 index 00000000..284f4899 --- /dev/null +++ b/tests/testdata/tinygo/wasmx-ondemand-single-lib/lib/utils.go @@ -0,0 +1,25 @@ +package lib + +import ( + wasmx "github.com/loredanacirstea/wasmx-env/lib" +) + +func LoggerInfo(msg string, parts []string) { + wasmx.LoggerInfo(MODULE_NAME, msg, parts) +} + +func LoggerError(msg string, parts []string) { + wasmx.LoggerError(MODULE_NAME, msg, parts) +} + +func LoggerDebug(msg string, parts []string) { + wasmx.LoggerDebug(MODULE_NAME, msg, parts) +} + +func LoggerDebugExtended(msg string, parts []string) { + wasmx.LoggerDebugExtended(MODULE_NAME, msg, parts) +} + +func Revert(message string) { + wasmx.RevertWithModule(MODULE_NAME, message) +} diff --git a/wasmx/cmdutils/testnet.go b/wasmx/cmdutils/testnet.go index 656e0f9a..a3a9fd72 100644 --- a/wasmx/cmdutils/testnet.go +++ b/wasmx/cmdutils/testnet.go @@ -180,6 +180,7 @@ Note, strict routability for addresses is turned off in the config file. Example: mythosd testnet init-files --network.initial-chains=mythos,level0 --v 4 --output-dir ./.testnets --starting-ip-address 192.168.10.2 + mythosd testnet init-files --network.initial-chains=ondemand_single --v 1 --output-dir ./.testnets --starting-ip-address 192.168.10.2 `, RunE: func(cmd *cobra.Command, _ []string) error { clientCtx, err := client.GetClientQueryContext(cmd) @@ -216,7 +217,7 @@ Example: cmd.Flags().Bool(flagSameMachine, false, "Starting nodes on the same machine, on different ports") cmd.Flags().Bool(flagNoCors, false, "If present, sets cors to *") cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") - cmd.Flags().StringSlice(networksrvflags.NetworkInitialChains, []string{"mythos"}, "Initialized chains, separated by comma. E.g. 'mythos', 'mythos,level0'") + cmd.Flags().StringSlice(networksrvflags.NetworkInitialChains, []string{"mythos"}, "Initialized chains, separated by comma. E.g. 'mythos', 'mythos,level0', 'ondemand_single'") return cmd } @@ -271,7 +272,7 @@ Example: cmd.Flags().Bool(flagSameMachine, false, "Starting nodes on the same machine, on different ports") cmd.Flags().Bool(flagNoCors, false, "If present, sets cors to *") cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|test)") - cmd.Flags().StringSlice(networksrvflags.NetworkInitialChains, []string{"mythos"}, "Initialized chains, separated by comma. E.g. 'mythos', 'mythos,level0'") + cmd.Flags().StringSlice(networksrvflags.NetworkInitialChains, []string{"mythos"}, "Initialized chains, separated by comma. E.g. 'mythos', 'mythos,level0', 'ondemand_single'") return cmd } @@ -485,6 +486,7 @@ func initTestnetFilesInternal( mockNodeHome := path.Join(args.outputDir, "tmp") generateMythos := slices.Contains(args.initialChains, "mythos") generateLevel0 := slices.Contains(args.initialChains, "level0") + generateOnDemandSingle := slices.Contains(args.initialChains, "ondemand_single") if args.chainID == "" { args.chainID = fmt.Sprintf("mythos_%d-1", tmrand.Int63n(9999999999999)+1) } @@ -522,6 +524,9 @@ func initTestnetFilesInternal( if generateLevel0 { initialChainIds = append(initialChainIds, chainId0) } + if generateOnDemandSingle { + initialChainIds = append(initialChainIds, chainId) + } nodeIDs := make([]string, args.numValidators) valPubKeys := make([]cryptotypes.PubKey, args.numValidators) nodeIPs := make([]string, args.numValidators) @@ -829,6 +834,26 @@ func initTestnetFilesInternal( } } + if generateOnDemandSingle { + // initialize on-demand-single chain with same setup as mythos but different system contracts + if err := initGenFilesOnDemandSingle(clientCtx, mbm, args.chainID, genAccounts, genBalances, genFiles, args.numValidators, args.minLevelValidators, args.enableEIDCheck); err != nil { + return err + } + + for i := nodeIndexStart; i < args.numValidators; i++ { + err = collectGenFiles( + clientCtx, + mythosapp.TxConfig(), + nodeConfig, + args.chainID, nodeIDs[i], valPubKeys[i], i, + args.outputDir, args.nodeDirPrefix, args.nodeDaemonHome, genBalIterator, valAddrCodec, args.sameMachine, nodeConfig.GenesisFile(), "gentxs", + ) + if err != nil { + return err + } + } + } + // cleanup mocks err = os.RemoveAll(mockNodeHome) if err != nil { @@ -1093,6 +1118,103 @@ func initGenFilesLevel0( return nil } +func initGenFilesOnDemandSingle( + clientCtx client.Context, + mbm module.BasicManager, + chainID string, + genAccounts []cosmosmodtypes.GenesisAccount, + genBalances []banktypes.Balance, + genFiles []string, + numValidators int, + minLevelValidators int, + enableEIDCheck bool, +) error { + appGenState := mbm.DefaultGenesis(clientCtx.Codec) + chaincfg, err := mcfg.GetChainConfig(chainID) + if err != nil { + panic(err) + } + + addrCodec := mcodec.NewAccBech32Codec(chaincfg.Bech32PrefixAccAddr, mcodec.NewAddressPrefixedFromAcc) + + var cosmosmodGenState cosmosmodtypes.GenesisState + clientCtx.Codec.MustUnmarshalJSON(appGenState[cosmosmodtypes.ModuleName], &cosmosmodGenState) + + cosmosmodGenState.Bank.DenomInfo = cosmosmodtypes.DefaultBankDenoms(addrCodec.(mcodec.AccBech32Codec), mcfg.DenomUnit, uint32(mcfg.BaseDenomUnit)) + cosmosmodGenState.Bank.Balances = genBalances + cosmosmodGenState.Staking.Params.BondDenom = mcfg.BondBaseDenom + cosmosmodGenState.Staking.BaseDenom = mcfg.BaseDenom + p, _ := math.LegacyNewDecFromStr("0.6") + cosmosmodGenState.Slashing.Params.MinSignedPerWindow = p + cosmosmodGenState.Slashing.Params.DowntimeJailDuration = time.Hour * 2 + cosmosmodGenState.Slashing.Params.SignedBlocksWindow = 40000 + cosmosmodGenState.Distribution.BaseDenom = mcfg.BaseDenom + cosmosmodGenState.Distribution.RewardsDenom = cosmosmodGenState.Bank.DenomInfo[2].Metadata.Base + cosmosmodGenState.Gov.Params.MinDeposit[0].Denom = mcfg.BaseDenom + cosmosmodGenState.Gov.Params.ExpeditedMinDeposit = sdk.NewCoins(sdk.NewCoin(mcfg.BaseDenom, math.NewInt(50000000))) + votingP := time.Minute * 2 + cosmosmodGenState.Gov.Params.VotingPeriod = votingP.Milliseconds() + + // set the accounts in the genesis state + authGenesis, err := cosmosmodtypes.NewAuthGenesisStateFromCosmos(clientCtx.Codec, cosmosmodGenState.Auth.Params, genAccounts) + if err != nil { + return err + } + cosmosmodGenState.Auth = *authGenesis + + // set cosmosmod genesis + appGenState[cosmosmodtypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&cosmosmodGenState) + + var crisisGenState crisistypes.GenesisState + clientCtx.Codec.MustUnmarshalJSON(appGenState[crisistypes.ModuleName], &crisisGenState) + crisisGenState.ConstantFee.Denom = mcfg.BaseDenom + appGenState[crisistypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&crisisGenState) + + var mintGenState minttypes.GenesisState + clientCtx.Codec.MustUnmarshalJSON(appGenState[minttypes.ModuleName], &mintGenState) + mintGenState.Params.MintDenom = mcfg.BaseDenom + appGenState[minttypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&mintGenState) + + feeCollectorBech32, err := addrCodec.BytesToString(cosmosmodtypes.NewModuleAddress(wasmxtypes.FEE_COLLECTOR)) + if err != nil { + panic(err) + } + mintAddressBech32, err := addrCodec.BytesToString(cosmosmodtypes.NewModuleAddress("mint")) + if err != nil { + panic(err) + } + + bootstrapAccount, err := addrCodec.BytesToString(sdk.AccAddress(rand.Bytes(address.Len))) + if err != nil { + panic(err) + } + + var wasmxGenState wasmxtypes.GenesisState + clientCtx.Codec.MustUnmarshalJSON(appGenState[wasmxtypes.ModuleName], &wasmxGenState) + wasmxGenState.SystemContracts = wasmxtypes.DefaultOnDemandSingleContracts(addrCodec.(mcodec.AccBech32Codec), feeCollectorBech32, mintAddressBech32, int32(minLevelValidators), enableEIDCheck, "{}", mcfg.BondBaseDenom) + wasmxGenState.BootstrapAccountAddress = bootstrapAccount + appGenState[wasmxtypes.ModuleName] = clientCtx.Codec.MustMarshalJSON(&wasmxGenState) + + appGenStateJSON, err := json.MarshalIndent(appGenState, "", " ") + if err != nil { + return err + } + + genDoc := types.GenesisDoc{ + ChainID: chainID, + AppState: appGenStateJSON, + Validators: nil, + } + + // generate empty genesis files for each validator and save + for i := 0; i < numValidators; i++ { + if err := genDoc.SaveAs(genFiles[i]); err != nil { + return err + } + } + return nil +} + func collectGenFiles( clientCtx client.Context, txConfig client.TxConfig, diff --git a/wasmx/x/wasmx/types/system_contract.go b/wasmx/x/wasmx/types/system_contract.go index 7089f3e7..d50cae65 100644 --- a/wasmx/x/wasmx/types/system_contract.go +++ b/wasmx/x/wasmx/types/system_contract.go @@ -80,6 +80,9 @@ var ADDR_STORAGE_CONTRACTS = "0x0000000000000000000000000000000000000061" var ADDR_DTYPE = "0x0000000000000000000000000000000000000062" var ADDR_EMAIL_HANDLER = "0x0000000000000000000000000000000000000063" +var ADDR_ONDEMAND_SINGLE_LIBRARY = "0x0000000000000000000000000000000000000064" +var ADDR_ONDEMAND_SINGLE = "0x0000000000000000000000000000000000000065" + var ADDR_SYS_PROXY = "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" func StarterPrecompiles() SystemContracts { @@ -570,6 +573,11 @@ func ConsensusPrecompiles(minValidatorCount int32, enableEIDCheck bool, currentL panic("ConsensusPrecompiles: cannot marshal level0InitMsg message") } + onDemandSingleInitMsg, err := json.Marshal(WasmxExecutionMessage{Data: []byte(`{"instantiate":{"context":[{"key":"maxLevel","value":"0"},{"key":"blockTimeout","value":"blockTimeoutInternal"},{"key":"currentLevel","value":"0"},{"key":"membersCount","value":"1"},{"key":"blockTimeoutInternal","value":"3000"}],"initialState":"uninitialized"}}`)}) + if err != nil { + panic("ConsensusPrecompiles: cannot marshal onDemandSingleInitMsg message") + } + lobbyInitMsg, err := json.Marshal(WasmxExecutionMessage{Data: []byte(fmt.Sprintf(`{"instantiate":{"context":[{"key":"heartbeatTimeout","value":"5000"},{"key":"newchainTimeout","value":"20000"},{"key":"current_level","value":"0"},{"key":"min_validators_count","value":"%d"},{"key":"enable_eid_check","value":"%t"},{"key":"erc20CodeId","value":"%d"},{"key":"derc20CodeId","value":"%d"},{"key":"level_initial_balance","value":"10000000000000000000"}],"initialState":"uninitialized"}}`, minValidatorCount, enableEIDCheck, erc20CodeId, derc20CodeId))}) if err != nil { panic("ConsensusPrecompiles: cannot marshal lobbyInitMsg message") @@ -715,6 +723,25 @@ func ConsensusPrecompiles(minValidatorCount int32, enableEIDCheck bool, currentL StorageType: ContractStorageType_SingleConsensus, Deps: []string{INTERPRETER_FSM, BuildDep(ADDR_LEVEL0_LIBRARY, ROLE_LIBRARY)}, }, + { + Address: ADDR_ONDEMAND_SINGLE_LIBRARY, + Label: ONDEMAND_SINGLE_LIBRARY_v001, + InitMessage: initMsg, + Pinned: true, + MeteringOff: true, + Role: &SystemContractRole{Role: ROLE_LIBRARY, Label: ONDEMAND_SINGLE_LIBRARY_v001}, + StorageType: ContractStorageType_SingleConsensus, + Deps: []string{}, + }, + { + Address: ADDR_ONDEMAND_SINGLE, + Label: ONDEMAND_SINGLE_v001, + InitMessage: onDemandSingleInitMsg, + Pinned: false, + Role: &SystemContractRole{Role: ROLE_CONSENSUS, Label: ONDEMAND_SINGLE_v001}, + StorageType: ContractStorageType_SingleConsensus, + Deps: []string{INTERPRETER_FSM, BuildDep(ADDR_ONDEMAND_SINGLE_LIBRARY, ROLE_LIBRARY)}, + }, { Address: ADDR_MULTICHAIN_REGISTRY_LOCAL, Label: MULTICHAIN_REGISTRY_LOCAL_v001, @@ -832,16 +859,16 @@ func SpecialPrecompiles() SystemContracts { panic("SpecialPrecompiles: cannot marshal init message") } return []SystemContract{ - { - Address: ADDR_DTYPE, - Label: DTYPE_v001, - InitMessage: initMsg, - Pinned: true, - MeteringOff: true, - Role: &SystemContractRole{Role: ROLE_DTYPE, Label: ROLE_DTYPE, Primary: true}, - StorageType: ContractStorageType_CoreConsensus, - Deps: []string{}, - }, + // { + // Address: ADDR_DTYPE, + // Label: DTYPE_v001, + // InitMessage: initMsg, + // Pinned: true, + // MeteringOff: true, + // Role: &SystemContractRole{Role: ROLE_DTYPE, Label: ROLE_DTYPE, Primary: true}, + // StorageType: ContractStorageType_CoreConsensus, + // Deps: []string{}, + // }, // TODO dtype nondeterministic version { Address: ADDR_EMAIL_HANDLER, @@ -1001,6 +1028,50 @@ func DefaultTimeChainContracts(accBech32Codec mcodec.AccBech32Codec, feeCollecto return precompiles } +func DefaultOnDemandSingleContracts(accBech32Codec mcodec.AccBech32Codec, feeCollectorBech32 string, mintBech32 string, minValidatorCount int32, enableEIDCheck bool, initialPortValues string, bondBaseDenom string) SystemContracts { + + precompiles := StarterPrecompiles() + precompiles = append(precompiles, SimplePrecompiles()...) + precompiles = append(precompiles, InterpreterPrecompiles()...) + precompiles = append(precompiles, BasePrecompiles()...) + precompiles = append(precompiles, EIDPrecompiles()...) + precompiles = append(precompiles, HookPrecompiles()...) + precompiles = append(precompiles, CosmosPrecompiles(feeCollectorBech32, mintBech32, bondBaseDenom)...) + + erc20CodeId := int32(0) + derc20CodeId := int32(0) + for i, p := range precompiles { + if p.Label == ERC20_v001 { + erc20CodeId = int32(i + 1) + } + } + for i, p := range precompiles { + if p.Label == DERC20_v001 { + derc20CodeId = int32(i + 1) + } + } + if erc20CodeId == int32(0) || derc20CodeId == int32(0) { + panic(fmt.Sprintf("erc20 or derc20 contracts not found: erc20CodeId %d, derc20CodeId %d", erc20CodeId, derc20CodeId)) + } + + consensusPrecompiles := ConsensusPrecompiles(minValidatorCount, enableEIDCheck, 0, initialPortValues, erc20CodeId, derc20CodeId) + for i, val := range consensusPrecompiles { + if val.Label == ONDEMAND_SINGLE_v001 { + consensusPrecompiles[i].Role.Primary = true + } + } + precompiles = append(precompiles, consensusPrecompiles...) + precompiles = append(precompiles, MultiChainPrecompiles(minValidatorCount, enableEIDCheck, erc20CodeId, derc20CodeId)...) + precompiles = append(precompiles, ChatPrecompiles()...) + // precompiles = append(precompiles, SpecialPrecompiles()...) + + precompiles, err := FillRoles(precompiles, accBech32Codec, feeCollectorBech32) + if err != nil { + panic(err) + } + return precompiles +} + func (p SystemContract) Validate() error { if err := validateString(p.Label); err != nil { return err diff --git a/wasmx/x/wasmx/types/vm.go b/wasmx/x/wasmx/types/vm.go index 3db116bc..715f3a6b 100644 --- a/wasmx/x/wasmx/types/vm.go +++ b/wasmx/x/wasmx/types/vm.go @@ -332,6 +332,11 @@ var CONSENSUS_AVA_SNOWMAN = "consensus_ava_snowman_0.0.1" var CONSENSUS_AVA_SNOWMAN_LIBRARY = "ava_snowman_library" var CONSENSUS_LEVEL_LIBRARY = "level0_library" +var LEVEL0_v001 = "level0_0.0.1" +var LEVEL0_ONDEMAND_v001 = "level0_ondemand_0.0.1" +var LEVEL0_ONDEMAND_LIBRARY = "level0_ondemand_library" +var ONDEMAND_SINGLE_v001 = "ondemand_single_0.0.1" +var ONDEMAND_SINGLE_LIBRARY_v001 = "ondemand_single_library_0.0.1" var LOBBY_LIBRARY = "lobby_library" @@ -358,9 +363,6 @@ var DISTRIBUTION_v001 = "distribution_0.0.1" var CHAT_v001 = "chat_0.0.1" var CHAT_VERIFIER_v001 = "chat_verifier_0.0.1" var TIME_v001 = "time_0.0.1" -var LEVEL0_v001 = "level0_0.0.1" -var LEVEL0_ONDEMAND_v001 = "level0_ondemand_0.0.1" -var LEVEL0_ONDEMAND_LIBRARY = "level0_ondemand_library" var MULTICHAIN_REGISTRY_v001 = "multichain_registry_0.0.1" var MULTICHAIN_REGISTRY_LOCAL_v001 = "multichain_registry_local_0.0.1" var ERC20_ROLLUP_v001 = "erc20rollupjson_0.0.1" diff --git a/wasmx/x/wasmx/vm/precompiles/65.wasmx_ondemand_single_library.wasm b/wasmx/x/wasmx/vm/precompiles/65.wasmx_ondemand_single_library.wasm new file mode 100644 index 00000000..209314c5 Binary files /dev/null and b/wasmx/x/wasmx/vm/precompiles/65.wasmx_ondemand_single_library.wasm differ diff --git a/wasmx/x/wasmx/vm/precompiles/fsm.go b/wasmx/x/wasmx/vm/precompiles/fsm.go index 6aa8b786..6f8b2076 100644 --- a/wasmx/x/wasmx/vm/precompiles/fsm.go +++ b/wasmx/x/wasmx/vm/precompiles/fsm.go @@ -35,3 +35,7 @@ var LobbyP2Pv001 = func(libAddressBech32 string) string { var Level0OnDemand001 = func(libAddressBech32 string) string { return fmt.Sprintf(`{"id":"OnDemand-Levels-5","library":"%s","states":[{"name":"uninitialized","after":[],"always":[],"on":[{"name":"initialize","transitions":[{"target":"#OnDemand-Levels-5.initialized","guard":null,"actions":[],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]},{"name":"initialized","after":[],"always":[],"on":[],"entry":[],"exit":[],"initial":"unstarted","states":[{"name":"unstarted","after":[],"always":[],"on":[{"name":"setupNode","transitions":[{"target":"#OnDemand-Levels-5.initialized.unstarted","guard":null,"actions":[{"type":"setupNode","params":[]}],"meta":[]}]},{"name":"prestart","transitions":[{"target":"#OnDemand-Levels-5.initialized.prestart","guard":null,"actions":[],"meta":[]}]},{"name":"setup","transitions":[{"target":"#OnDemand-Levels-5.initialized.unstarted","guard":null,"actions":[{"type":"setup","params":[]}],"meta":[]}]},{"name":"start","transitions":[{"target":"#OnDemand-Levels-5.initialized.started","guard":null,"actions":[{"type":"connectPeers","params":[]},{"type":"connectRooms","params":[]},{"type":"requestBlockSync","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]},{"name":"prestart","after":[{"name":"500","transitions":[{"target":"#OnDemand-Levels-5.initialized.started","guard":null,"actions":[],"meta":[]}]}],"always":[],"on":[],"entry":[],"exit":[],"initial":"","states":[]},{"name":"started","after":[],"always":[],"on":[{"name":"newTransaction","transitions":[{"target":"","guard":{"type":"ifNewTransaction","params":[]},"actions":[{"type":"addToMempool","params":[]},{"type":"sendNewTransactionResponse","params":[]},{"type":"forwardMsgToChat","params":[{"key":"protocolId","value":"mempool"}]}],"meta":[]}]},{"name":"receiveStateSyncRequest","transitions":[{"target":"","guard":null,"actions":[{"type":"receiveStateSyncRequest","params":[]}],"meta":[]}]},{"name":"updateNode","transitions":[{"target":"","guard":null,"actions":[{"type":"updateNodeAndReturn","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"Node","states":[{"name":"Node","after":[],"always":[{"name":"always","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator","actions":[{"type":"registerValidatorWithNetwork","params":[]}],"guard":{"type":"ifNodeIsValidator","params":[]},"meta":[]}]}],"on":[{"name":"becomeValidator","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator","guard":null,"actions":[{"type":"registerValidatorWithNetwork","params":[]},{"type":"requestBlockSync","params":[]}],"meta":[]}]},{"name":"receiveStateSyncResponse","transitions":[{"target":"","guard":null,"actions":[{"type":"receiveStateSyncResponse","params":[]}],"meta":[]}]},{"name":"start","transitions":[{"target":"","guard":null,"actions":[{"type":"connectPeers","params":[]},{"type":"connectRooms","params":[]},{"type":"requestBlockSync","params":[]}],"meta":[]}]},{"name":"receiveCommit","transitions":[{"target":"","guard":null,"actions":[{"type":"receiveCommit","params":[]}],"meta":[]}]},{"name":"receiveUpdateNodeResponse","transitions":[{"target":"","guard":null,"actions":[{"type":"receiveUpdateNodeResponse","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]},{"name":"Validator","after":[],"always":[],"on":[{"name":"receiveBlockProposal","transitions":[{"target":"","guard":{"type":"ifSenderIsProposer","params":[]},"actions":[{"type":"receiveBlockProposal","params":[]}],"meta":[]}]},{"name":"stop","transitions":[{"target":"#OnDemand-Levels-5.stopped","guard":null,"actions":[],"meta":[]}]},{"name":"receiveUpdateNodeResponse","transitions":[{"target":"","guard":null,"actions":[{"type":"receiveUpdateNodeResponse","params":[]}],"meta":[]}]},{"name":"start","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator","guard":null,"actions":[{"type":"connectPeers","params":[]},{"type":"connectRooms","params":[]},{"type":"registerValidatorWithNetwork","params":[]},{"type":"requestBlockSync","params":[]}],"meta":[]}]},{"name":"receiveCommit","transitions":[{"target":"","guard":null,"actions":[{"type":"receiveCommit","params":[]}],"meta":[]}]},{"name":"receiveUpdateNodeRequest","transitions":[{"target":"","guard":null,"actions":[{"type":"receiveUpdateNodeRequest","params":[]}],"meta":[]}]},{"name":"receiveStateSyncResponse","transitions":[{"target":"","guard":null,"actions":[{"type":"receiveStateSyncResponse","params":[]},{"type":"requestValidatorNodeInfoIfSynced","params":[]}],"meta":[]}]},{"name":"receivePrecommit","transitions":[{"target":"","guard":null,"actions":[{"type":"receivePrecommit","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"active","states":[{"name":"active","after":[{"name":"timeoutPropose","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator.precommit","guard":null,"actions":[{"type":"sendPrecommitNil","params":[]}],"meta":[]}]}],"always":[{"name":"always","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Proposer","guard":{"type":"isNextProposer","params":[]},"actions":[],"meta":[]}]}],"on":[{"name":"receiveBlockProposal","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator.precommit","guard":{"type":"ifSenderIsProposer","params":[]},"actions":[{"type":"receiveBlockProposal","params":[]},{"type":"sendPrecommit","params":[]},{"type":"cancelActiveIntervals","params":[{"key":"after","value":"timeoutPropose"}]}],"meta":[]},{"target":"#OnDemand-Levels-5.initialized.started.Validator.precommit","guard":{"type":"ifForceProposalReset","params":[]},"actions":[{"type":"receiveBlockProposal","params":[]},{"type":"resetPrecommits","params":[]},{"type":"setRoundProposer","params":[]},{"type":"sendPrecommit","params":[]},{"type":"cancelActiveIntervals","params":[{"key":"after","value":"timeoutPropose"}]}],"meta":[]}]}],"entry":[{"type":"incrementCurrentTerm","params":[]},{"type":"setRoundProposer","params":[]},{"type":"resetPrecommits","params":[]}],"exit":[],"initial":"","states":[]},{"name":"precommit","after":[{"name":"timeoutPrecommit","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator.active","guard":null,"actions":[],"meta":[]}]}],"always":[{"name":"always","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator.commit","actions":[{"type":"commitBlock","params":[]},{"type":"sendCommit","params":[]},{"type":"cancelActiveIntervals","params":[{"key":"after","value":"timeoutPrecommit"}]}],"guard":{"type":"ifPrecommitAcceptThreshold","params":[]},"meta":[]}]}],"on":[{"name":"receivePrecommit","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator.precommit","guard":null,"actions":[{"type":"receivePrecommit","params":[]}],"meta":[]}]},{"name":"receiveBlockProposal","transitions":[{"target":"","guard":{"type":"ifSenderIsProposer","params":[]},"actions":[{"type":"receiveBlockProposal","params":[]}],"meta":[]},{"target":"#OnDemand-Levels-5.initialized.started.Validator.precommit","guard":{"type":"ifForceProposalReset","params":[]},"actions":[{"type":"receiveBlockProposal","params":[]},{"type":"resetPrecommits","params":[]},{"type":"setRoundProposer","params":[]},{"type":"sendPrecommit","params":[]},{"type":"cancelActiveIntervals","params":[{"key":"after","value":"timeoutPrecommit"}]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]},{"name":"commit","after":[{"name":"roundTimeout","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.waiting","guard":null,"actions":[],"meta":[]}]}],"always":[],"on":[{"name":"receivePrecommit","transitions":[{"target":"","guard":null,"actions":[{"type":"receivePrecommit","params":[]}],"meta":[]}]},{"name":"receiveBlockProposal","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator.precommit","guard":{"type":"ifNextBlockProposal","params":[]},"actions":[{"type":"incrementCurrentTerm","params":[]},{"type":"setRoundProposer","params":[]},{"type":"resetPrecommits","params":[]},{"type":"receiveBlockProposal","params":[]},{"type":"sendPrecommit","params":[]},{"type":"cancelActiveIntervals","params":[{"key":"after","value":"roundTimeout"}]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]}]},{"name":"waiting","after":[{"name":"batchTimeout","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator.active","guard":{"type":"ifMempoolNotEmpty","params":[]},"actions":[],"meta":[]}]}],"always":[],"on":[{"name":"newTransaction","transitions":[{"target":"","guard":{"type":"ifOldTransaction","params":[]},"actions":[],"meta":[]},{"target":"#OnDemand-Levels-5.initialized.started.waiting","guard":{"type":"ifMempoolEmpty","params":[]},"actions":[{"type":"addToMempool","params":[]},{"type":"sendNewTransactionResponse","params":[]},{"type":"forwardMsgToChat","params":[{"key":"protocolId","value":"mempool"}]}],"meta":[]},{"target":"#OnDemand-Levels-5.initialized.started.Validator.active","guard":{"type":"ifMempoolFull","params":[]},"actions":[{"type":"addToMempool","params":[]},{"type":"sendNewTransactionResponse","params":[]},{"type":"forwardMsgToChat","params":[{"key":"protocolId","value":"mempool"}]},{"type":"cancelActiveIntervals","params":[{"key":"after","value":"batchTimeout"}]}],"meta":[]},{"target":"","guard":null,"actions":[{"type":"addToMempool","params":[]},{"type":"sendNewTransactionResponse","params":[]},{"type":"forwardMsgToChat","params":[{"key":"protocolId","value":"mempool"}]}],"meta":[]}]},{"name":"start","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator","guard":null,"actions":[{"type":"connectPeers","params":[]},{"type":"connectRooms","params":[]},{"type":"registerValidatorWithNetwork","params":[]},{"type":"requestBlockSync","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]},{"name":"Proposer","after":[],"always":[],"on":[{"name":"start","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator","guard":null,"actions":[{"type":"connectPeers","params":[]},{"type":"connectRooms","params":[]},{"type":"registerValidatorWithNetwork","params":[]},{"type":"requestBlockSync","params":[]}],"meta":[]}]},{"name":"stop","transitions":[{"target":"#OnDemand-Levels-5.stopped","guard":null,"actions":[],"meta":[]}]},{"name":"receiveUpdateNodeRequest","transitions":[{"target":"","guard":null,"actions":[{"type":"receiveUpdateNodeRequest","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"active","states":[{"name":"active","after":[],"always":[{"name":"always","transitions":[{"target":"#OnDemand-Levels-5.initialized.started.Validator.precommit","guard":null,"actions":[],"meta":[]}]}],"on":[],"entry":[{"type":"proposeBlock","params":[]},{"type":"sendBlockProposal","params":[]},{"type":"sendPrecommit","params":[]}],"exit":[],"initial":"","states":[]}]}]}]},{"name":"stopped","after":[],"always":[],"on":[{"name":"restart","transitions":[{"target":"#OnDemand-Levels-5.initialized.unstarted","guard":null,"actions":[],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]}]}`, libAddressBech32) } + +var OnDemandSingle = func(libAddressBech32 string) string { + return fmt.Sprintf(`{"library":"%s","id":"Levels-OnDemand-Single","initial":"uninitialized","states":[{"name":"uninitialized","after":[],"always":[],"on":[{"name":"initialize","transitions":[{"target":"#OnDemand-Single.initialized","guard":null,"actions":[],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]},{"name":"initialized","after":[],"always":[],"on":[],"entry":[],"exit":[],"initial":"unstarted","states":[{"name":"unstarted","after":[],"always":[],"on":[{"name":"start","transitions":[{"target":"#OnDemand-Single.initialized.started","guard":null,"actions":[{"type":"StartNode","params":[]}],"meta":[]}]},{"name":"setup","transitions":[{"target":"#OnDemand-Single.initialized.unstarted","guard":null,"actions":[{"type":"setup","params":[]}],"meta":[]}]},{"name":"prestart","transitions":[{"target":"#OnDemand-Single.initialized.prestart","guard":null,"actions":[],"meta":[]}]},{"name":"setupNode","transitions":[{"target":"#OnDemand-Single.initialized.unstarted","guard":null,"actions":[{"type":"setupNode","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]},{"name":"started","after":[],"always":[],"on":[{"name":"start","transitions":[{"target":"#OnDemand-Single.initialized.started","guard":null,"actions":[{"type":"StartNode","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"active","states":[{"name":"active","after":[],"always":[],"on":[{"name":"newTransaction","transitions":[{"target":"#OnDemand-Single.initialized.started.proposer","guard":{"type":"ifNewTransaction","params":[]},"actions":[{"type":"addToMempool","params":[]},{"type":"sendNewTransactionResponse","params":[]}],"meta":[]}]}],"entry":[],"exit":[],"initial":"","states":[]},{"name":"proposer","after":[],"always":[{"name":"always","transitions":[{"target":"#OnDemand-Single.initialized.started.active","actions":[{"type":"newBlock","params":[]}],"guard":null,"meta":[]}]}],"on":[],"entry":[],"exit":[],"initial":"","states":[]}]},{"name":"prestart","after":[{"name":"500","transitions":[{"target":"#OnDemand-Single.initialized.started","guard":null,"actions":[],"meta":[]}]}],"always":[],"on":[],"entry":[],"exit":[],"initial":"","states":[]}]}]}`, libAddressBech32) +} diff --git a/wasmx/x/wasmx/vm/precompiles/precompiles.go b/wasmx/x/wasmx/vm/precompiles/precompiles.go index 08d517ae..c24b5083 100644 --- a/wasmx/x/wasmx/vm/precompiles/precompiles.go +++ b/wasmx/x/wasmx/vm/precompiles/precompiles.go @@ -159,6 +159,9 @@ var ( //go:embed 64.wasmx_httpserver_registry_0.0.1.wasm wasmx_httpserver_registry []byte + //go:embed 65.wasmx_ondemand_single_library.wasm + ondemand_single_library []byte + //go:embed ff.sys_proxy.wasm sys_proxy []byte ) @@ -295,6 +298,15 @@ func GetPrecompileByLabel(addrCodec address.Codec, label string) []byte { panic(err) } wasmbin = []byte(Level0OnDemand001(libaddrstr)) + case types.ONDEMAND_SINGLE_LIBRARY_v001: + wasmbin = ondemand_single_library + case types.ONDEMAND_SINGLE_v001: + libaddr := types.AccAddressFromHex(types.ADDR_ONDEMAND_SINGLE_LIBRARY) + libaddrstr, err := addrCodec.BytesToString(libaddr) + if err != nil { + panic(err) + } + wasmbin = []byte(OnDemandSingle(libaddrstr)) case types.MULTICHAIN_REGISTRY_v001: wasmbin = multichain_registry case types.MULTICHAIN_REGISTRY_LOCAL_v001: