diff --git a/activation-service/helm/tfchainactivationservice/Chart.yaml b/activation-service/helm/tfchainactivationservice/Chart.yaml index 042e2e4a2..4f5ccd231 100644 --- a/activation-service/helm/tfchainactivationservice/Chart.yaml +++ b/activation-service/helm/tfchainactivationservice/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: tfchainactivationservice description: TFchain account activation funding service type: application -version: 2.10.1 -appVersion: '2.10.1' +version: 2.11.0 +appVersion: '2.11.0' diff --git a/activation-service/package.json b/activation-service/package.json index 9fa0a9122..3064c9f9b 100644 --- a/activation-service/package.json +++ b/activation-service/package.json @@ -1,6 +1,6 @@ { "name": "substrate-funding-service", - "version": "2.10.1", + "version": "2.11.0", "description": "Substrate funding service", "main": "index.js", "scripts": { diff --git a/bridge/tfchain_bridge/chart/tfchainbridge/Chart.yaml b/bridge/tfchain_bridge/chart/tfchainbridge/Chart.yaml index df4906e9b..85a127079 100644 --- a/bridge/tfchain_bridge/chart/tfchainbridge/Chart.yaml +++ b/bridge/tfchain_bridge/chart/tfchainbridge/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: tfchainbridge description: Bridge for TFT between Tfchain Stellar type: application -version: 2.10.1 -appVersion: '2.10.1' +version: 2.11.0 +appVersion: '2.11.0' diff --git a/clients/tfchain-client-go/events.go b/clients/tfchain-client-go/events.go index 70f462826..8f1b7210b 100644 --- a/clients/tfchain-client-go/events.go +++ b/clients/tfchain-client-go/events.go @@ -331,6 +331,25 @@ type ZosVersionUpdated struct { Topics []types.Hash } +type NodeV3BillingOptedOut struct { + Phase types.Phase + NodeID types.U32 `json:"node_id"` + OptedOutAt types.U64 `json:"opted_out_at"` + Topics []types.Hash +} + +type TwinAdminAdded struct { + Phase types.Phase + Account AccountID `json:"account_id"` + Topics []types.Hash +} + +type TwinAdminRemoved struct { + Phase types.Phase + Account AccountID `json:"account_id"` + Topics []types.Hash +} + type EventSchedulerCallUnavailable struct { Phase types.Phase Task types.TaskAddress @@ -467,6 +486,9 @@ type EventRecords struct { TfgridModule_FarmingPolicySet []FarmingPolicySet //nolint:stylecheck,golint TfgridModule_FarmCertificationSet []FarmCertificationSet //nolint:stylecheck,golint TfgridModule_ZosVersionUpdated []ZosVersionUpdated //nolint:stylecheck,golint + TfgridModule_NodeV3BillingOptedOut []NodeV3BillingOptedOut //nolint:stylecheck,golint + TfgridModule_TwinAdminAdded []TwinAdminAdded //nolint:stylecheck,golint + TfgridModule_TwinAdminRemoved []TwinAdminRemoved //nolint:stylecheck,golint // burn module events BurningModule_BurnTransactionCreated []BurnTransactionCreated //nolint:stylecheck,golint diff --git a/clients/tfchain-client-go/node.go b/clients/tfchain-client-go/node.go index 6eade3661..96ad8ad91 100644 --- a/clients/tfchain-client-go/node.go +++ b/clients/tfchain-client-go/node.go @@ -805,6 +805,124 @@ func (s *Substrate) GetDedicatedNodePrice(nodeID uint32) (uint64, error) { return uint64(price), nil } +// OptOutOfV3Billing opts a node out of the v3 billing system, opening a free migration window. +// Only the farmer who owns the node can call this. +func (s *Substrate) OptOutOfV3Billing(identity Identity, nodeID uint32) (hash types.Hash, err error) { + cl, meta, err := s.GetClient() + if err != nil { + return hash, err + } + + c, err := types.NewCall(meta, "TfgridModule.opt_out_of_v3_billing", nodeID) + if err != nil { + return hash, errors.Wrap(err, "failed to create call") + } + + callResponse, err := s.Call(cl, meta, identity, c) + if err != nil { + return hash, errors.Wrap(err, "failed to opt out of v3 billing") + } + + return callResponse.Hash, nil +} + +// AddTwinAdmin adds an account to the list of twin admins allowed to deploy on opted-out nodes. +// Requires council (restricted) origin. +func (s *Substrate) AddTwinAdmin(identity Identity, account AccountID) (hash types.Hash, err error) { + cl, meta, err := s.GetClient() + if err != nil { + return hash, err + } + + c, err := types.NewCall(meta, "TfgridModule.add_twin_admin", account) + if err != nil { + return hash, errors.Wrap(err, "failed to create call") + } + + callResponse, err := s.Call(cl, meta, identity, c) + if err != nil { + return hash, errors.Wrap(err, "failed to add twin admin") + } + + return callResponse.Hash, nil +} + +// RemoveTwinAdmin removes an account from the list of twin admins allowed to deploy on opted-out nodes. +// Requires council (restricted) origin. +func (s *Substrate) RemoveTwinAdmin(identity Identity, account AccountID) (hash types.Hash, err error) { + cl, meta, err := s.GetClient() + if err != nil { + return hash, err + } + + c, err := types.NewCall(meta, "TfgridModule.remove_twin_admin", account) + if err != nil { + return hash, errors.Wrap(err, "failed to create call") + } + + callResponse, err := s.Call(cl, meta, identity, c) + if err != nil { + return hash, errors.Wrap(err, "failed to remove twin admin") + } + + return callResponse.Hash, nil +} + +// GetAllowedTwinAdmins returns the list of accounts allowed to deploy on opted-out nodes. +// Returns an empty slice if no admins have been configured. +func (s *Substrate) GetAllowedTwinAdmins() ([]AccountID, error) { + cl, meta, err := s.GetClient() + if err != nil { + return nil, err + } + + key, err := types.CreateStorageKey(meta, "TfgridModule", "AllowedTwinAdmins") + if err != nil { + return nil, errors.Wrap(err, "failed to create substrate query key") + } + + raw, err := cl.RPC.State.GetStorageRawLatest(key) + if err != nil { + return nil, errors.Wrap(err, "failed to lookup allowed twin admins") + } + + if len(*raw) == 0 { + return []AccountID{}, nil + } + + var admins []AccountID + if err := Decode(*raw, &admins); err != nil { + return nil, errors.Wrap(err, "failed to decode allowed twin admins") + } + + return admins, nil +} + +// IsNodeOptedOutOfV3Billing returns true if the node has opted out of v3 billing. +func (s *Substrate) IsNodeOptedOutOfV3Billing(nodeID uint32) (bool, error) { + cl, meta, err := s.GetClient() + if err != nil { + return false, err + } + + bytes, err := Encode(nodeID) + if err != nil { + return false, errors.Wrap(err, "substrate: encoding error building query arguments") + } + + key, err := types.CreateStorageKey(meta, "TfgridModule", "NodeV3BillingOptOut", bytes) + if err != nil { + return false, errors.Wrap(err, "failed to create substrate query key") + } + + raw, err := cl.RPC.State.GetStorageRawLatest(key) + if err != nil { + return false, errors.Wrap(err, "failed to lookup node v3 billing opt-out") + } + + return len(*raw) > 0, nil +} + // SetNodeCertificate sets the node certificate type func (s *Substrate) SetNodeCertificate(identity Identity, id uint32, cert NodeCertification) error { cl, meta, err := s.GetClient() diff --git a/clients/tfchain-client-go/node_test.go b/clients/tfchain-client-go/node_test.go index 5bb185764..d59b81acf 100644 --- a/clients/tfchain-client-go/node_test.go +++ b/clients/tfchain-client-go/node_test.go @@ -67,6 +67,54 @@ func TestSetDedicatedNodePrice(t *testing.T) { require.Equal(t, uint64(price), priceSet) } +func TestOptOutOfV3Billing(t *testing.T) { + cl := startLocalConnection(t) + defer cl.Close() + + // Bob is the farmer + identity, err := NewIdentityFromSr25519Phrase(BobMnemonics) + require.NoError(t, err) + + farmID, twinID := assertCreateFarm(t, cl) + nodeID := assertCreateNode(t, cl, farmID, twinID, identity) + + _, err = cl.OptOutOfV3Billing(identity, nodeID) + // NodeV3BillingOptOutAlreadyEnabled is acceptable on re-runs (opt-out is permanent) + if err != nil { + require.EqualError(t, err, "NodeV3BillingOptOutAlreadyEnabled") + } + + optedOut, err := cl.IsNodeOptedOutOfV3Billing(nodeID) + require.NoError(t, err) + require.True(t, optedOut) +} + +func TestGetAllowedTwinAdmins(t *testing.T) { + cl := startLocalConnection(t) + defer cl.Close() + + rootIdentity, err := NewIdentityFromSr25519Phrase(AliceMnemonics) + require.NoError(t, err) + + bobAccount, err := FromAddress(BobAddress) + require.NoError(t, err) + + // Ensure Bob is in the list + _, err = cl.AddTwinAdmin(rootIdentity, bobAccount) + require.NoError(t, err) + admins, err := cl.GetAllowedTwinAdmins() + require.NoError(t, err) + require.Contains(t, admins, bobAccount) + + // Clean up + _, err = cl.RemoveTwinAdmin(rootIdentity, bobAccount) + require.NoError(t, err) + + admins, err = cl.GetAllowedTwinAdmins() + require.NoError(t, err) + require.NotContains(t, admins, bobAccount) +} + func TestUptimeReport(t *testing.T) { cl := startLocalConnection(t) defer cl.Close() diff --git a/clients/tfchain-client-go/utils.go b/clients/tfchain-client-go/utils.go index 9d23d7bc9..5b405eaf8 100644 --- a/clients/tfchain-client-go/utils.go +++ b/clients/tfchain-client-go/utils.go @@ -129,6 +129,7 @@ var smartContractModuleErrors = []string{ "UnauthorizedToSetExtraFee", "RewardDistributionError", "ContractPaymentStateNotExists", + "OnlyTwinAdminCanDeployOnThisNode", } // https://github.com/threefoldtech/tfchain/blob/development/substrate-node/pallets/pallet-tfgrid/src/lib.rs#L442 @@ -249,6 +250,13 @@ var tfgridModuleErrors = []string{ "InvalidRelayAddress", "InvalidTimestampHint", "InvalidStorageInput", + "TwinTransferRequestNotFound", + "TwinTransferNewAccountHasTwin", + "TwinTransferPendingExists", + "NodeV3BillingOptOutAlreadyEnabled", + "AlreadyTwinAdmin", + "NotTwinAdmin", + "TwinAdminListFull", } // https://github.com/threefoldtech/tfchain/blob/development/substrate-node/pallets/pallet-tft-bridge/src/lib.rs#L152 diff --git a/clients/tfchain-client-js/lib/node.js b/clients/tfchain-client-js/lib/node.js index fd25eccd7..f0c9fcb07 100644 --- a/clients/tfchain-client-js/lib/node.js +++ b/clients/tfchain-client-js/lib/node.js @@ -126,6 +126,42 @@ async function deleteNode (self, id, callback) { .signAndSend(self.key, { nonce }, callback) } +// optOutOfV3Billing opts a node out of v3 billing (farmer only, one-way) +async function optOutOfV3Billing (self, nodeID, callback) { + const nonce = await self.api.rpc.system.accountNextIndex(self.address) + return self.api.tx.tfgridModule + .optOutOfV3Billing(nodeID) + .signAndSend(self.key, { nonce }, callback) +} + +// addTwinAdmin adds an account to the list of twin admins (council origin) +async function addTwinAdmin (self, account, callback) { + const nonce = await self.api.rpc.system.accountNextIndex(self.address) + return self.api.tx.tfgridModule + .addTwinAdmin(account) + .signAndSend(self.key, { nonce }, callback) +} + +// removeTwinAdmin removes an account from the list of twin admins (council origin) +async function removeTwinAdmin (self, account, callback) { + const nonce = await self.api.rpc.system.accountNextIndex(self.address) + return self.api.tx.tfgridModule + .removeTwinAdmin(account) + .signAndSend(self.key, { nonce }, callback) +} + +// getAllowedTwinAdmins returns the list of accounts allowed to deploy on opted-out nodes +async function getAllowedTwinAdmins (self) { + const result = await self.api.query.tfgridModule.allowedTwinAdmins() + return result.toJSON() || [] +} + +// isNodeOptedOutOfV3Billing returns true if the node has opted out of v3 billing +async function isNodeOptedOutOfV3Billing (self, nodeID) { + const result = await self.api.query.tfgridModule.nodeV3BillingOptOut(nodeID) + return !result.isNone +} + async function validateNode (self, farmID) { const farm = await getFarm(self, farmID) if (farm.id !== farmID) { @@ -139,5 +175,10 @@ module.exports = { getNode, getNodeIDByPubkey, deleteNode, - listNodes + listNodes, + optOutOfV3Billing, + addTwinAdmin, + removeTwinAdmin, + getAllowedTwinAdmins, + isNodeOptedOutOfV3Billing } diff --git a/clients/tfchain-client-js/package.json b/clients/tfchain-client-js/package.json index 4c308657f..76ee6b0f7 100644 --- a/clients/tfchain-client-js/package.json +++ b/clients/tfchain-client-js/package.json @@ -1,6 +1,6 @@ { "name": "tfgrid-api-client", - "version": "2.10.1", + "version": "2.11.0", "description": "API client for the TF Grid", "main": "index.js", "scripts": { diff --git a/docs/architecture/0025-v3-billing-opt-out.md b/docs/architecture/0025-v3-billing-opt-out.md new file mode 100644 index 000000000..154d7c65a --- /dev/null +++ b/docs/architecture/0025-v3-billing-opt-out.md @@ -0,0 +1,67 @@ +# 25. V3 Billing Opt-Out for Node Migration + +Date: 2026-02-18 + +## Status + +Accepted + +## Context + +During the migration from v3 to Mycelium, farmers need a way to signal that their nodes are entering a migration window. Existing workloads on these nodes should not be billed during this period, as the node is transitioning infrastructure. + +## Decision + +### New Storage Items (pallet-tfgrid) + +- **`NodeV3BillingOptOut`**: A `StorageMap` tracking which nodes have opted out. Presence in this map is the sole indicator of opt-out status. No storage migration is required as this is an additive change. +- **`AllowedTwinAdmins`**: A `StorageValue>` listing accounts authorized to deploy on opted-out nodes. Bounded to `MaxTwinAdmins` (default: 100) to prevent unbounded storage growth. + +### New Extrinsics (pallet-tfgrid) + +| Extrinsic | Origin | Call Index | +| --- | --- | --- | +| `opt_out_of_v3_billing(node_id)` | Farmer (signed) | 43 | +| `add_twin_admin(account)` | Council (`RestrictedOrigin`) | 44 | +| `remove_twin_admin(account)` | Council (`RestrictedOrigin`) | 45 | + +Opt-out is one-way and permanent — there is no opt-back-in extrinsic. The `NodeV3BillingOptOut` entry is cleaned up automatically when the node is deleted. + +### Deployment Guards (pallet-smart-contract) + +`_create_node_contract` and `_create_rent_contract` both check `NodeV3BillingOptOut` before allowing deployment. If the target node has opted out, the caller's `AccountId` must be present in `AllowedTwinAdmins`, otherwise the call fails with `OnlyTwinAdminCanDeployOnThisNode`. + +### Billing Suppression (pallet-smart-contract) + +In `bill_contract`, a `should_waive_migration_billing` flag is computed by checking `NodeV3BillingOptOut` for the contract's node. When true: + +- **`Created` state**: early return, no billing work performed. +- **`GracePeriod` state**: cost is zeroed; `manage_contract_state` runs normally, allowing the contract to be restored to `Created` once the user tops up to cover pre-opt-out overdraft. +- **`Deleted` state**: cost is zeroed; cleanup proceeds normally. + +This is distinct from `should_waive_standby_rent` (standby power state, rent contracts only, emits `RentWaived`). The migration billing waiver is silent — no event is emitted because no billing is expected after opt-out. + +### New Events (pallet-tfgrid) + +- `NodeV3BillingOptedOut { node_id, opted_out_at }` — emitted on successful opt-out. +- `TwinAdminAdded(AccountId)` — emitted when an admin is added. +- `TwinAdminRemoved(AccountId)` — emitted when an admin is removed. + +### New Errors + +### pallet-smart-contract + +- `OnlyTwinAdminCanDeployOnThisNode` — returned when a non-admin attempts to deploy on an opted-out node. + +### pallet-tfgrid + +- `NodeV3BillingOptOutAlreadyEnabled` — returned when `opt_out_of_v3_billing` is called on a node that has already opted out. +- `AlreadyTwinAdmin` — returned when `add_twin_admin` is called for an account already in the admin list. +- `NotTwinAdmin` — returned when `remove_twin_admin` is called for an account not in the admin list, or when the list is empty. +- `TwinAdminListFull` — returned when `add_twin_admin` is called but the list has reached `MaxTwinAdmins` capacity. + +## Consequences + +- **No storage migration**: all new storage items are additive. +- **Free migration window**: existing workloads on opted-out nodes accumulate no new charges. Users with pre-existing overdraft (contracts in `GracePeriod`) can still top up to restore their workloads, after which subsequent billing cycles are free. +- **Access control**: only council-approved twin admins can deploy new workloads on opted-out nodes. diff --git a/scripts/package.json b/scripts/package.json index c639415e9..78de3aa6c 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -1,6 +1,6 @@ { "name": "tfchain-js-scripts", - "version": "2.10.1", + "version": "2.11.0", "description": "scripts to fetch data / write data to tfchain", "main": "index.js", "scripts": { diff --git a/substrate-node/Cargo.lock b/substrate-node/Cargo.lock index 27796fc31..05d3cd7cf 100644 --- a/substrate-node/Cargo.lock +++ b/substrate-node/Cargo.lock @@ -4590,7 +4590,7 @@ dependencies = [ [[package]] name = "pallet-burning" -version = "2.10.1" +version = "2.11.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -4625,7 +4625,7 @@ dependencies = [ [[package]] name = "pallet-dao" -version = "2.10.1" +version = "2.11.0" dependencies = [ "env_logger", "frame-benchmarking", @@ -4672,7 +4672,7 @@ dependencies = [ [[package]] name = "pallet-kvstore" -version = "2.10.1" +version = "2.11.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -4705,7 +4705,7 @@ dependencies = [ [[package]] name = "pallet-runtime-upgrade" -version = "2.10.1" +version = "2.11.0" dependencies = [ "frame-support", "frame-system", @@ -4774,7 +4774,7 @@ dependencies = [ [[package]] name = "pallet-smart-contract" -version = "2.10.1" +version = "2.11.0" dependencies = [ "env_logger", "frame-benchmarking", @@ -4827,7 +4827,7 @@ dependencies = [ [[package]] name = "pallet-tfgrid" -version = "2.10.1" +version = "2.11.0" dependencies = [ "env_logger", "frame-benchmarking", @@ -4856,7 +4856,7 @@ dependencies = [ [[package]] name = "pallet-tft-bridge" -version = "2.10.1" +version = "2.11.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -4875,7 +4875,7 @@ dependencies = [ [[package]] name = "pallet-tft-price" -version = "2.10.1" +version = "2.11.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -4980,7 +4980,7 @@ dependencies = [ [[package]] name = "pallet-validator" -version = "2.10.1" +version = "2.11.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -8379,7 +8379,7 @@ dependencies = [ [[package]] name = "substrate-validator-set" -version = "2.10.1" +version = "2.11.0" dependencies = [ "frame-benchmarking", "frame-support", @@ -8519,7 +8519,7 @@ checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" [[package]] name = "tfchain" -version = "2.10.1" +version = "2.11.0" dependencies = [ "clap", "frame-benchmarking", @@ -8565,7 +8565,7 @@ dependencies = [ [[package]] name = "tfchain-runtime" -version = "2.10.1" +version = "2.11.0" dependencies = [ "frame-benchmarking", "frame-executive", @@ -8619,7 +8619,7 @@ dependencies = [ [[package]] name = "tfchain-support" -version = "2.10.1" +version = "2.11.0" dependencies = [ "frame-support", "frame-system", diff --git a/substrate-node/Cargo.toml b/substrate-node/Cargo.toml index 1c39e4c02..e75119ad3 100644 --- a/substrate-node/Cargo.toml +++ b/substrate-node/Cargo.toml @@ -6,7 +6,7 @@ homepage = "https://threefold.io/" license-file = "LICENSE" readme = "README.md" repository = "https://github.com/threefoldtech/tfchain3" -version = "2.10.1" +version = "2.11.0" [workspace] members = [ diff --git a/substrate-node/charts/substrate-node/Chart.yaml b/substrate-node/charts/substrate-node/Chart.yaml index ad75bb5da..524fad31d 100644 --- a/substrate-node/charts/substrate-node/Chart.yaml +++ b/substrate-node/charts/substrate-node/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: substrate-node description: Tfchain node type: application -version: 2.10.1 -appVersion: '2.10.1' +version: 2.11.0 +appVersion: '2.11.0' diff --git a/substrate-node/pallets/pallet-burning/src/weights.rs b/substrate-node/pallets/pallet-burning/src/weights.rs index c319c57ae..3e8a3f87c 100644 --- a/substrate-node/pallets/pallet-burning/src/weights.rs +++ b/substrate-node/pallets/pallet-burning/src/weights.rs @@ -2,9 +2,9 @@ //! Autogenerated weights for pallet_burning //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2025-09-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2026-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ebea9d7a9918`, CPU: `AMD Ryzen 7 5800X 8-Core Processor` +//! HOSTNAME: `19750001b071`, CPU: `DO-Regular` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -45,8 +45,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `109` // Estimated: `1594` - // Minimum execution time: 26_060_000 picoseconds. - Weight::from_parts(26_561_000, 1594) + // Minimum execution time: 54_457_000 picoseconds. + Weight::from_parts(93_148_000, 1594) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -60,8 +60,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `109` // Estimated: `1594` - // Minimum execution time: 26_060_000 picoseconds. - Weight::from_parts(26_561_000, 1594) + // Minimum execution time: 54_457_000 picoseconds. + Weight::from_parts(93_148_000, 1594) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate-node/pallets/pallet-dao/src/weights.rs b/substrate-node/pallets/pallet-dao/src/weights.rs index b97ec0112..dcfef11bb 100644 --- a/substrate-node/pallets/pallet-dao/src/weights.rs +++ b/substrate-node/pallets/pallet-dao/src/weights.rs @@ -2,9 +2,9 @@ //! Autogenerated weights for pallet_dao //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2025-09-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2026-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ebea9d7a9918`, CPU: `AMD Ryzen 7 5800X 8-Core Processor` +//! HOSTNAME: `19750001b071`, CPU: `DO-Regular` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -58,8 +58,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `208` // Estimated: `4687` - // Minimum execution time: 18_274_000 picoseconds. - Weight::from_parts(18_706_000, 4687) + // Minimum execution time: 38_004_000 picoseconds. + Weight::from_parts(40_173_000, 4687) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -77,8 +77,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `979` // Estimated: `4444` - // Minimum execution time: 24_997_000 picoseconds. - Weight::from_parts(25_498_000, 4444) + // Minimum execution time: 48_203_000 picoseconds. + Weight::from_parts(50_745_000, 4444) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -92,8 +92,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `487` // Estimated: `4687` - // Minimum execution time: 17_904_000 picoseconds. - Weight::from_parts(18_395_000, 4687) + // Minimum execution time: 34_237_000 picoseconds. + Weight::from_parts(48_378_000, 4687) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -111,8 +111,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `521` // Estimated: `4687` - // Minimum execution time: 24_947_000 picoseconds. - Weight::from_parts(26_390_000, 4687) + // Minimum execution time: 50_644_000 picoseconds. + Weight::from_parts(57_493_000, 4687) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -136,8 +136,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `208` // Estimated: `4687` - // Minimum execution time: 18_274_000 picoseconds. - Weight::from_parts(18_706_000, 4687) + // Minimum execution time: 38_004_000 picoseconds. + Weight::from_parts(40_173_000, 4687) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -155,8 +155,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `979` // Estimated: `4444` - // Minimum execution time: 24_997_000 picoseconds. - Weight::from_parts(25_498_000, 4444) + // Minimum execution time: 48_203_000 picoseconds. + Weight::from_parts(50_745_000, 4444) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -170,8 +170,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `487` // Estimated: `4687` - // Minimum execution time: 17_904_000 picoseconds. - Weight::from_parts(18_395_000, 4687) + // Minimum execution time: 34_237_000 picoseconds. + Weight::from_parts(48_378_000, 4687) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -189,8 +189,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `521` // Estimated: `4687` - // Minimum execution time: 24_947_000 picoseconds. - Weight::from_parts(26_390_000, 4687) + // Minimum execution time: 50_644_000 picoseconds. + Weight::from_parts(57_493_000, 4687) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } diff --git a/substrate-node/pallets/pallet-kvstore/src/weights.rs b/substrate-node/pallets/pallet-kvstore/src/weights.rs index df9f5ae3f..96a3b72a6 100644 --- a/substrate-node/pallets/pallet-kvstore/src/weights.rs +++ b/substrate-node/pallets/pallet-kvstore/src/weights.rs @@ -2,9 +2,9 @@ //! Autogenerated weights for pallet_kvstore //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2025-09-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2026-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ebea9d7a9918`, CPU: `AMD Ryzen 7 5800X 8-Core Processor` +//! HOSTNAME: `19750001b071`, CPU: `DO-Regular` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -46,8 +46,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_833_000 picoseconds. - Weight::from_parts(7_104_000, 0) + // Minimum execution time: 23_608_000 picoseconds. + Weight::from_parts(28_283_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `TFKVStore::TFKVStore` (r:1 w:1) @@ -56,8 +56,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `146` // Estimated: `3611` - // Minimum execution time: 11_963_000 picoseconds. - Weight::from_parts(12_283_000, 3611) + // Minimum execution time: 23_301_000 picoseconds. + Weight::from_parts(24_584_000, 3611) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -71,8 +71,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 6_833_000 picoseconds. - Weight::from_parts(7_104_000, 0) + // Minimum execution time: 23_608_000 picoseconds. + Weight::from_parts(28_283_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `TFKVStore::TFKVStore` (r:1 w:1) @@ -81,8 +81,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `146` // Estimated: `3611` - // Minimum execution time: 11_963_000 picoseconds. - Weight::from_parts(12_283_000, 3611) + // Minimum execution time: 23_301_000 picoseconds. + Weight::from_parts(24_584_000, 3611) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate-node/pallets/pallet-smart-contract/src/billing.rs b/substrate-node/pallets/pallet-smart-contract/src/billing.rs index 9178424ee..28be9ad94 100644 --- a/substrate-node/pallets/pallet-smart-contract/src/billing.rs +++ b/substrate-node/pallets/pallet-smart-contract/src/billing.rs @@ -198,7 +198,7 @@ impl Pallet { let seconds_elapsed = now.defensive_saturating_sub(contract_payment_state.last_updated_seconds); - let should_waive_payment = match &contract.contract_type { + let should_waive_standby_rent = match &contract.contract_type { types::ContractData::RentContract(rc) => { let node_power = pallet_tfgrid::NodePower::::get(rc.node_id); node_power.is_standby() @@ -206,7 +206,24 @@ impl Pallet { _ => false, }; - if should_waive_payment { + let should_waive_migration_billing = match &contract.contract_type { + types::ContractData::NodeContract(nc) => { + pallet_tfgrid::NodeV3BillingOptOut::::contains_key(nc.node_id) + } + types::ContractData::RentContract(rc) => { + pallet_tfgrid::NodeV3BillingOptOut::::contains_key(rc.node_id) + } + _ => false, + }; + + // For Created contracts on opted-out nodes: early return (mirrors should_waive_standby_rent). + // early return is cleaner and consistent with the should_waive_standby_rent pattern. + // GracePeriod and Deleted fall through: zero new cost + manage_contract_state runs naturally. + if should_waive_migration_billing && matches!(contract.state, types::ContractState::Created) { + return Ok(().into()); + } + + if should_waive_standby_rent { log::info!("Waiving rent for contract_id: {:?}", contract.contract_id); Self::deposit_event(Event::RentWaived { contract_id: contract.contract_id, @@ -219,7 +236,7 @@ impl Pallet { } // Calculate the due amount - let (standard_amount_due, discount_received) = if should_waive_payment { + let (standard_amount_due, discount_received) = if should_waive_standby_rent || should_waive_migration_billing { (BalanceOf::::zero(), types::DiscountLevel::None) } else { contract @@ -236,7 +253,7 @@ impl Pallet { let additional_amount_due = if let types::ContractData::RentContract(rc) = &contract.contract_type { - if should_waive_payment { + if should_waive_standby_rent || should_waive_migration_billing { BalanceOf::::zero() } else { contract.calculate_extra_fee_cost_tft(rc.node_id, seconds_elapsed) diff --git a/substrate-node/pallets/pallet-smart-contract/src/grid_contract.rs b/substrate-node/pallets/pallet-smart-contract/src/grid_contract.rs index a2fd7222a..a85dbf82f 100644 --- a/substrate-node/pallets/pallet-smart-contract/src/grid_contract.rs +++ b/substrate-node/pallets/pallet-smart-contract/src/grid_contract.rs @@ -34,6 +34,14 @@ impl Pallet { Error::::NodeNotAvailableToDeploy ); + // V3 billing opt-out guard: only twin admins can deploy on opted-out nodes + if pallet_tfgrid::NodeV3BillingOptOut::::contains_key(node_id) { + let caller_is_admin = pallet_tfgrid::AllowedTwinAdmins::::get() + .unwrap_or_default() + .contains(&account_id); + ensure!(caller_is_admin, Error::::OnlyTwinAdminCanDeployOnThisNode); + } + let farm = pallet_tfgrid::Farms::::get(node.farm_id).ok_or(Error::::FarmNotExists)?; // A node is dedicated (can only be used under a rent contract) @@ -129,6 +137,14 @@ impl Pallet { Error::::FarmNotExists ); + // V3 billing opt-out guard: only twin admins can deploy on opted-out nodes + if pallet_tfgrid::NodeV3BillingOptOut::::contains_key(node_id) { + let caller_is_admin = pallet_tfgrid::AllowedTwinAdmins::::get() + .unwrap_or_default() + .contains(&account_id); + ensure!(caller_is_admin, Error::::OnlyTwinAdminCanDeployOnThisNode); + } + let active_node_contracts = ActiveNodeContracts::::get(node_id); let farm = pallet_tfgrid::Farms::::get(node.farm_id).ok_or(Error::::FarmNotExists)?; ensure!( diff --git a/substrate-node/pallets/pallet-smart-contract/src/lib.rs b/substrate-node/pallets/pallet-smart-contract/src/lib.rs index e140c900e..14ba20f11 100644 --- a/substrate-node/pallets/pallet-smart-contract/src/lib.rs +++ b/substrate-node/pallets/pallet-smart-contract/src/lib.rs @@ -418,6 +418,7 @@ pub mod pallet { UnauthorizedToSetExtraFee, RewardDistributionError, ContractPaymentStateNotExists, + OnlyTwinAdminCanDeployOnThisNode, } #[pallet::genesis_config] diff --git a/substrate-node/pallets/pallet-smart-contract/src/mock.rs b/substrate-node/pallets/pallet-smart-contract/src/mock.rs index 3863acfd8..712a555b4 100644 --- a/substrate-node/pallets/pallet-smart-contract/src/mock.rs +++ b/substrate-node/pallets/pallet-smart-contract/src/mock.rs @@ -207,6 +207,7 @@ parameter_types! { pub const MaxInterfaceIpsLength: u32 = 5; pub const MaxInterfacesLength: u32 = 10; pub const MaxFarmPublicIps: u32 = 512; + pub const MaxTwinAdmins: u32 = 10; pub const TimestampHintDrift: u64 = 60; } @@ -234,6 +235,7 @@ impl pallet_tfgrid::Config for TestRuntime { type FarmName = TestFarmName; type MaxFarmNameLength = MaxFarmNameLength; type MaxFarmPublicIps = MaxFarmPublicIps; + type MaxTwinAdmins = MaxTwinAdmins; type MaxInterfacesLength = MaxInterfacesLength; type InterfaceName = TestInterfaceName; type InterfaceMac = TestInterfaceMac; diff --git a/substrate-node/pallets/pallet-smart-contract/src/tests.rs b/substrate-node/pallets/pallet-smart-contract/src/tests.rs index 56b5efdff..1ca11c5bc 100644 --- a/substrate-node/pallets/pallet-smart-contract/src/tests.rs +++ b/substrate-node/pallets/pallet-smart-contract/src/tests.rs @@ -5312,6 +5312,349 @@ fn prepare_solution_provider(origin: AccountId) { )); } +// ------------------------------------------ // +// V3 BILLING OPT-OUT TESTS // +// ------------------------------------------ // + +#[test] +fn test_create_node_contract_on_opted_out_node_non_admin_fails() { + new_test_ext().execute_with(|| { + run_to_block(1, None); + prepare_farm_and_node(); + let node_id = 1; + + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + + assert_noop!( + SmartContractModule::create_node_contract( + RuntimeOrigin::signed(bob()), + node_id, + generate_deployment_hash(), + get_deployment_data(), + 0, + None, + ), + Error::::OnlyTwinAdminCanDeployOnThisNode + ); + }); +} + +#[test] +fn test_create_node_contract_on_opted_out_node_admin_succeeds() { + new_test_ext().execute_with(|| { + run_to_block(1, None); + prepare_farm_and_node(); + let node_id = 1; + + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + + assert_ok!(TfgridModule::add_twin_admin( + RawOrigin::Root.into(), + bob(), + )); + + assert_ok!(SmartContractModule::create_node_contract( + RuntimeOrigin::signed(bob()), + node_id, + generate_deployment_hash(), + get_deployment_data(), + 0, + None, + )); + }); +} + +#[test] +fn test_create_node_contract_opted_out_farmer_cannot_self_deploy() { + // The farmer who opted out is NOT automatically an admin — they must be explicitly added. + // This is a distinct case from test_create_node_contract_on_opted_out_node_non_admin_fails + // which uses an unrelated account (bob). Here the farmer (alice) tries to deploy on their own node. + new_test_ext().execute_with(|| { + run_to_block(1, None); + prepare_farm_and_node(); + let node_id = 1; + + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + + assert_noop!( + SmartContractModule::create_node_contract( + RuntimeOrigin::signed(alice()), + node_id, + generate_deployment_hash(), + get_deployment_data(), + 0, + None, + ), + Error::::OnlyTwinAdminCanDeployOnThisNode + ); + }); +} + +#[test] +fn test_admin_removed_cannot_deploy_on_opted_out_node() { + new_test_ext().execute_with(|| { + run_to_block(1, None); + prepare_farm_and_node(); + let node_id = 1; + + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + + assert_ok!(TfgridModule::add_twin_admin(RawOrigin::Root.into(), bob())); + assert_ok!(TfgridModule::remove_twin_admin(RawOrigin::Root.into(), bob())); + + assert_noop!( + SmartContractModule::create_node_contract( + RuntimeOrigin::signed(bob()), + node_id, + generate_deployment_hash(), + get_deployment_data(), + 0, + None, + ), + Error::::OnlyTwinAdminCanDeployOnThisNode + ); + }); +} + +#[test] +fn test_create_rent_contract_on_opted_out_node_non_admin_fails() { + new_test_ext().execute_with(|| { + run_to_block(1, None); + prepare_dedicated_farm_and_node(); + let node_id = 1; + + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + + assert_noop!( + SmartContractModule::create_rent_contract( + RuntimeOrigin::signed(charlie()), + node_id, + None, + ), + Error::::OnlyTwinAdminCanDeployOnThisNode + ); + }); +} + +#[test] +fn test_create_rent_contract_on_opted_out_node_admin_succeeds() { + new_test_ext().execute_with(|| { + run_to_block(1, None); + prepare_dedicated_farm_and_node(); + let node_id = 1; + + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + + assert_ok!(TfgridModule::add_twin_admin( + RawOrigin::Root.into(), + charlie(), + )); + + assert_ok!(SmartContractModule::create_rent_contract( + RuntimeOrigin::signed(charlie()), + node_id, + None, + )); + }); +} + +#[test] +fn test_billing_suppressed_for_opted_out_node_contract() { + let (mut ext, mut pool_state) = new_test_ext_with_pool_state(0); + ext.execute_with(|| { + run_to_block(1, None); + prepare_farm_and_node(); + let node_id = 1; + + assert_ok!(TfgridModule::add_twin_admin(RawOrigin::Root.into(), bob())); + + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + + assert_ok!(SmartContractModule::create_node_contract( + RuntimeOrigin::signed(bob()), + node_id, + generate_deployment_hash(), + get_deployment_data(), + 0, + None, + )); + let contract_id = 1; + + push_contract_resources_used(contract_id); + + let balance_before = Balances::free_balance(&bob()); + + // OCW fires at block 11 (billing cycle), but cost is zeroed by should_waive_migration_billing + pool_state + .write() + .should_call_bill_contract(contract_id, Ok(Pays::Yes.into()), 11); + run_to_block(11, Some(&mut pool_state)); + + let balance_after = Balances::free_balance(&bob()); + + // No charge despite real resource usage — billing suppressed for opted-out node + assert_eq!(balance_before, balance_after); + + // Contract remains in Created state (not pushed to GracePeriod) + let contract = SmartContractModule::contracts(contract_id).unwrap(); + assert_eq!(contract.state, types::ContractState::Created); + }); +} + +#[test] +fn test_cancel_contract_on_opted_out_node_zero_final_bill() { + new_test_ext().execute_with(|| { + run_to_block(1, None); + prepare_farm_and_node(); + let node_id = 1; + + assert_ok!(TfgridModule::add_twin_admin(RawOrigin::Root.into(), bob())); + + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + + assert_ok!(SmartContractModule::create_node_contract( + RuntimeOrigin::signed(bob()), + node_id, + generate_deployment_hash(), + get_deployment_data(), + 0, + None, + )); + let contract_id = 1; + + push_contract_resources_used(contract_id); + + let balance_before = Balances::free_balance(&bob()); + + // Cancel triggers bill_contract inline (no OCW) with state=Deleted + assert_ok!(SmartContractModule::cancel_contract( + RuntimeOrigin::signed(bob()), + contract_id, + )); + + let balance_after = Balances::free_balance(&bob()); + + // No charge despite real resource usage — migration billing suppressed at cancellation too + assert_eq!(balance_before, balance_after); + + // Contract is cleaned up + assert!(SmartContractModule::contracts(contract_id).is_none()); + }); +} + +#[test] +fn test_grace_period_contract_restored_and_billing_free_after_opt_out() { + // Scenario: + // 1. charlie deploys on a normal node, runs out of funds → GracePeriod + // 2. Farmer opts out of v3 billing while contract is in GracePeriod + // 3. charlie tops up → next billing cycle restores contract to Created + // 4. Subsequent billing cycle: resources are present but cost is zero (migration window) + let (mut ext, mut pool_state) = new_test_ext_with_pool_state(0); + ext.execute_with(|| { + run_to_block(1, None); + prepare_farm_and_node(); + let node_id = 1; + + TFTPriceModule::set_prices(RuntimeOrigin::signed(alice()), 50, 101).unwrap(); + + // charlie (low balance) deploys — node is NOT yet opted out + assert_ok!(TfgridModule::add_twin_admin(RawOrigin::Root.into(), charlie())); + assert_ok!(SmartContractModule::create_node_contract( + RuntimeOrigin::signed(charlie()), + node_id, + generate_deployment_hash(), + get_deployment_data(), + 0, + None, + )); + let contract_id = 1; + + push_contract_resources_used(contract_id); + + // Cycle 1: charlie can pay + pool_state + .write() + .should_call_bill_contract(contract_id, Ok(Pays::Yes.into()), 11); + run_to_block(11, Some(&mut pool_state)); + + // Cycle 2: charlie runs out of funds → GracePeriod + pool_state + .write() + .should_call_bill_contract(contract_id, Ok(Pays::Yes.into()), 21); + run_to_block(21, Some(&mut pool_state)); + + let contract = SmartContractModule::contracts(contract_id).unwrap(); + assert_eq!(contract.state, types::ContractState::GracePeriod(21)); + + // Farmer opts out while contract is in GracePeriod + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + + // Cycle 3: charlie still can't pay, stays in GracePeriod + pool_state + .write() + .should_call_bill_contract(contract_id, Ok(Pays::Yes.into()), 31); + run_to_block(31, Some(&mut pool_state)); + + let contract = SmartContractModule::contracts(contract_id).unwrap(); + assert_eq!(contract.state, types::ContractState::GracePeriod(21)); + + // charlie tops up to cover the pre-opt-out overdraft + Balances::transfer(RuntimeOrigin::signed(bob()), charlie(), 100000000).unwrap(); + + // Cycle 4: sufficient funds → contract restored to Created + pool_state + .write() + .should_call_bill_contract(contract_id, Ok(Pays::Yes.into()), 41); + run_to_block(41, Some(&mut pool_state)); + + let contract = SmartContractModule::contracts(contract_id).unwrap(); + assert_eq!(contract.state, types::ContractState::Created); + + // Cycle 5: contract is Created on opted-out node with resources — billing must be free + let balance_before = Balances::free_balance(&charlie()); + pool_state + .write() + .should_call_bill_contract(contract_id, Ok(Pays::Yes.into()), 51); + run_to_block(51, Some(&mut pool_state)); + + let balance_after = Balances::free_balance(&charlie()); + + // No charge — migration window active + assert_eq!(balance_before, balance_after); + + // Contract stays Created (not pushed back to GracePeriod despite no payment) + let contract = SmartContractModule::contracts(contract_id).unwrap(); + assert_eq!(contract.state, types::ContractState::Created); + }); +} + fn record(event: RuntimeEvent) -> EventRecord { EventRecord { phase: Phase::Initialization, diff --git a/substrate-node/pallets/pallet-smart-contract/src/weights.rs b/substrate-node/pallets/pallet-smart-contract/src/weights.rs index fc3e7c640..7ec5ae660 100644 --- a/substrate-node/pallets/pallet-smart-contract/src/weights.rs +++ b/substrate-node/pallets/pallet-smart-contract/src/weights.rs @@ -2,9 +2,9 @@ //! Autogenerated weights for pallet_smart_contract //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2025-09-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2026-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ebea9d7a9918`, CPU: `AMD Ryzen 7 5800X 8-Core Processor` +//! HOSTNAME: `19750001b071`, CPU: `DO-Regular` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -67,6 +67,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `TfgridModule::Nodes` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `TfgridModule::NodePower` (r:1 w:0) /// Proof: `TfgridModule::NodePower` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `TfgridModule::Farms` (r:1 w:1) /// Proof: `TfgridModule::Farms` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::DedicatedNodesExtraFee` (r:1 w:0) @@ -95,9 +97,9 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `868` // Estimated: `4333` - // Minimum execution time: 47_449_000 picoseconds. - Weight::from_parts(48_522_000, 4333) - .saturating_add(T::DbWeight::get().reads(12_u64)) + // Minimum execution time: 125_637_000 picoseconds. + Weight::from_parts(158_842_000, 4333) + .saturating_add(T::DbWeight::get().reads(13_u64)) .saturating_add(T::DbWeight::get().writes(8_u64)) } /// Storage: `SmartContractModule::Contracts` (r:1 w:1) @@ -110,8 +112,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `869` // Estimated: `4334` - // Minimum execution time: 22_553_000 picoseconds. - Weight::from_parts(23_053_000, 4334) + // Minimum execution time: 45_372_000 picoseconds. + Weight::from_parts(73_961_000, 4334) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -133,6 +135,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `TfgridModule::TwinBoundedAccountID` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::ActiveRentContractForNode` (r:1 w:0) /// Proof: `SmartContractModule::ActiveRentContractForNode` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::BillingFrequency` (r:1 w:0) @@ -149,9 +153,9 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1650` // Estimated: `7590` - // Minimum execution time: 73_609_000 picoseconds. - Weight::from_parts(74_771_000, 7590) - .saturating_add(T::DbWeight::get().reads(13_u64)) + // Minimum execution time: 156_863_000 picoseconds. + Weight::from_parts(256_304_000, 7590) + .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } /// Storage: `TfgridModule::TwinIdByAccountID` (r:1 w:0) @@ -174,8 +178,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `340` // Estimated: `3805` - // Minimum execution time: 24_006_000 picoseconds. - Weight::from_parts(24_456_000, 3805) + // Minimum execution time: 71_124_000 picoseconds. + Weight::from_parts(77_955_000, 3805) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -201,8 +205,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `949` // Estimated: `4414` - // Minimum execution time: 50_195_000 picoseconds. - Weight::from_parts(51_317_000, 4414) + // Minimum execution time: 113_856_000 picoseconds. + Weight::from_parts(166_357_000, 4414) .saturating_add(T::DbWeight::get().reads(8_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -224,8 +228,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1286` // Estimated: `4751` - // Minimum execution time: 36_339_000 picoseconds. - Weight::from_parts(36_919_000, 4751) + // Minimum execution time: 101_287_000 picoseconds. + Weight::from_parts(116_239_000, 4751) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -241,8 +245,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `765` // Estimated: `4230` - // Minimum execution time: 22_412_000 picoseconds. - Weight::from_parts(23_384_000, 4230) + // Minimum execution time: 45_075_000 picoseconds. + Weight::from_parts(70_218_000, 4230) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -252,6 +256,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `TfgridModule::Nodes` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `TfgridModule::Farms` (r:1 w:0) /// Proof: `TfgridModule::Farms` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::ActiveNodeContracts` (r:1 w:0) /// Proof: `SmartContractModule::ActiveNodeContracts` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `TfgridModule::TwinIdByAccountID` (r:1 w:0) @@ -272,9 +278,9 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `776` // Estimated: `4241` - // Minimum execution time: 33_453_000 picoseconds. - Weight::from_parts(34_145_000, 4241) - .saturating_add(T::DbWeight::get().reads(9_u64)) + // Minimum execution time: 69_351_000 picoseconds. + Weight::from_parts(109_988_000, 4241) + .saturating_add(T::DbWeight::get().reads(10_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } /// Storage: `SmartContractModule::Contracts` (r:1 w:1) @@ -297,6 +303,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) /// Storage: `TfgridModule::NodePower` (r:1 w:0) /// Proof: `TfgridModule::NodePower` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::DedicatedNodesExtraFee` (r:1 w:0) /// Proof: `SmartContractModule::DedicatedNodesExtraFee` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::BillingFrequency` (r:1 w:0) @@ -309,9 +317,9 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1607` // Estimated: `7547` - // Minimum execution time: 70_012_000 picoseconds. - Weight::from_parts(71_505_000, 7547) - .saturating_add(T::DbWeight::get().reads(14_u64)) + // Minimum execution time: 138_767_000 picoseconds. + Weight::from_parts(147_354_000, 7547) + .saturating_add(T::DbWeight::get().reads(15_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `SmartContractModule::SolutionProviderID` (r:1 w:1) @@ -322,8 +330,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `37` // Estimated: `1522` - // Minimum execution time: 9_618_000 picoseconds. - Weight::from_parts(10_009_000, 1522) + // Minimum execution time: 19_151_000 picoseconds. + Weight::from_parts(19_702_000, 1522) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -333,8 +341,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `215` // Estimated: `3680` - // Minimum execution time: 12_484_000 picoseconds. - Weight::from_parts(12_854_000, 3680) + // Minimum execution time: 24_809_000 picoseconds. + Weight::from_parts(25_573_000, 3680) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -356,6 +364,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `TfgridModule::TwinBoundedAccountID` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::ContractBillingInformationByID` (r:1 w:1) /// Proof: `SmartContractModule::ContractBillingInformationByID` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::NodeContractResources` (r:1 w:0) @@ -374,9 +384,9 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `2077` // Estimated: `8017` - // Minimum execution time: 83_768_000 picoseconds. - Weight::from_parts(85_121_000, 8017) - .saturating_add(T::DbWeight::get().reads(17_u64)) + // Minimum execution time: 198_668_000 picoseconds. + Weight::from_parts(308_991_000, 8017) + .saturating_add(T::DbWeight::get().reads(18_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } /// Storage: `TfgridModule::TwinIdByAccountID` (r:2 w:0) @@ -389,8 +399,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `395` // Estimated: `6335` - // Minimum execution time: 17_804_000 picoseconds. - Weight::from_parts(18_284_000, 6335) + // Minimum execution time: 51_524_000 picoseconds. + Weight::from_parts(58_527_000, 6335) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -402,8 +412,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `489` // Estimated: `3954` - // Minimum execution time: 15_980_000 picoseconds. - Weight::from_parts(16_271_000, 3954) + // Minimum execution time: 31_567_000 picoseconds. + Weight::from_parts(52_961_000, 3954) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -415,8 +425,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `489` // Estimated: `3954` - // Minimum execution time: 15_880_000 picoseconds. - Weight::from_parts(16_190_000, 3954) + // Minimum execution time: 33_377_000 picoseconds. + Weight::from_parts(48_525_000, 3954) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -428,8 +438,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `502` // Estimated: `3967` - // Minimum execution time: 16_311_000 picoseconds. - Weight::from_parts(16_672_000, 3967) + // Minimum execution time: 45_324_000 picoseconds. + Weight::from_parts(56_352_000, 3967) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -441,8 +451,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `502` // Estimated: `3967` - // Minimum execution time: 16_271_000 picoseconds. - Weight::from_parts(17_142_000, 3967) + // Minimum execution time: 47_713_000 picoseconds. + Weight::from_parts(50_466_000, 3967) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -454,8 +464,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `502` // Estimated: `3967` - // Minimum execution time: 15_620_000 picoseconds. - Weight::from_parts(15_930_000, 3967) + // Minimum execution time: 44_626_000 picoseconds. + Weight::from_parts(51_600_000, 3967) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -473,8 +483,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `841` // Estimated: `6781` - // Minimum execution time: 28_193_000 picoseconds. - Weight::from_parts(28_955_000, 6781) + // Minimum execution time: 63_936_000 picoseconds. + Weight::from_parts(91_117_000, 6781) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -484,8 +494,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `37` // Estimated: `1522` - // Minimum execution time: 7_585_000 picoseconds. - Weight::from_parts(7_805_000, 1522) + // Minimum execution time: 16_676_000 picoseconds. + Weight::from_parts(25_396_000, 1522) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -499,8 +509,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `965` // Estimated: `4430` - // Minimum execution time: 21_100_000 picoseconds. - Weight::from_parts(21_641_000, 4430) + // Minimum execution time: 43_672_000 picoseconds. + Weight::from_parts(62_786_000, 4430) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -520,8 +530,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `733` // Estimated: `4198` - // Minimum execution time: 22_243_000 picoseconds. - Weight::from_parts(23_034_000, 4198) + // Minimum execution time: 45_803_000 picoseconds. + Weight::from_parts(69_341_000, 4198) .saturating_add(T::DbWeight::get().reads(5_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -543,6 +553,8 @@ impl WeightInfo for SubstrateWeight { /// Proof: `TfgridModule::TwinBoundedAccountID` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::ActiveRentContractForNode` (r:1 w:0) /// Proof: `SmartContractModule::ActiveRentContractForNode` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::BillingFrequency` (r:1 w:0) @@ -559,9 +571,9 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `1650` // Estimated: `7590` - // Minimum execution time: 71_696_000 picoseconds. - Weight::from_parts(73_088_000, 7590) - .saturating_add(T::DbWeight::get().reads(13_u64)) + // Minimum execution time: 148_314_000 picoseconds. + Weight::from_parts(230_693_000, 7590) + .saturating_add(T::DbWeight::get().reads(14_u64)) .saturating_add(T::DbWeight::get().writes(7_u64)) } } @@ -574,6 +586,8 @@ impl WeightInfo for () { /// Proof: `TfgridModule::Nodes` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `TfgridModule::NodePower` (r:1 w:0) /// Proof: `TfgridModule::NodePower` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `TfgridModule::Farms` (r:1 w:1) /// Proof: `TfgridModule::Farms` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::DedicatedNodesExtraFee` (r:1 w:0) @@ -602,9 +616,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `868` // Estimated: `4333` - // Minimum execution time: 47_449_000 picoseconds. - Weight::from_parts(48_522_000, 4333) - .saturating_add(RocksDbWeight::get().reads(12_u64)) + // Minimum execution time: 125_637_000 picoseconds. + Weight::from_parts(158_842_000, 4333) + .saturating_add(RocksDbWeight::get().reads(13_u64)) .saturating_add(RocksDbWeight::get().writes(8_u64)) } /// Storage: `SmartContractModule::Contracts` (r:1 w:1) @@ -617,8 +631,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `869` // Estimated: `4334` - // Minimum execution time: 22_553_000 picoseconds. - Weight::from_parts(23_053_000, 4334) + // Minimum execution time: 45_372_000 picoseconds. + Weight::from_parts(73_961_000, 4334) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -640,6 +654,8 @@ impl WeightInfo for () { /// Proof: `TfgridModule::TwinBoundedAccountID` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::ActiveRentContractForNode` (r:1 w:0) /// Proof: `SmartContractModule::ActiveRentContractForNode` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::BillingFrequency` (r:1 w:0) @@ -656,9 +672,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1650` // Estimated: `7590` - // Minimum execution time: 73_609_000 picoseconds. - Weight::from_parts(74_771_000, 7590) - .saturating_add(RocksDbWeight::get().reads(13_u64)) + // Minimum execution time: 156_863_000 picoseconds. + Weight::from_parts(256_304_000, 7590) + .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } /// Storage: `TfgridModule::TwinIdByAccountID` (r:1 w:0) @@ -681,8 +697,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `340` // Estimated: `3805` - // Minimum execution time: 24_006_000 picoseconds. - Weight::from_parts(24_456_000, 3805) + // Minimum execution time: 71_124_000 picoseconds. + Weight::from_parts(77_955_000, 3805) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -708,8 +724,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `949` // Estimated: `4414` - // Minimum execution time: 50_195_000 picoseconds. - Weight::from_parts(51_317_000, 4414) + // Minimum execution time: 113_856_000 picoseconds. + Weight::from_parts(166_357_000, 4414) .saturating_add(RocksDbWeight::get().reads(8_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -731,8 +747,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1286` // Estimated: `4751` - // Minimum execution time: 36_339_000 picoseconds. - Weight::from_parts(36_919_000, 4751) + // Minimum execution time: 101_287_000 picoseconds. + Weight::from_parts(116_239_000, 4751) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -748,8 +764,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `765` // Estimated: `4230` - // Minimum execution time: 22_412_000 picoseconds. - Weight::from_parts(23_384_000, 4230) + // Minimum execution time: 45_075_000 picoseconds. + Weight::from_parts(70_218_000, 4230) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -759,6 +775,8 @@ impl WeightInfo for () { /// Proof: `TfgridModule::Nodes` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `TfgridModule::Farms` (r:1 w:0) /// Proof: `TfgridModule::Farms` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::ActiveNodeContracts` (r:1 w:0) /// Proof: `SmartContractModule::ActiveNodeContracts` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `TfgridModule::TwinIdByAccountID` (r:1 w:0) @@ -779,9 +797,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `776` // Estimated: `4241` - // Minimum execution time: 33_453_000 picoseconds. - Weight::from_parts(34_145_000, 4241) - .saturating_add(RocksDbWeight::get().reads(9_u64)) + // Minimum execution time: 69_351_000 picoseconds. + Weight::from_parts(109_988_000, 4241) + .saturating_add(RocksDbWeight::get().reads(10_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } /// Storage: `SmartContractModule::Contracts` (r:1 w:1) @@ -804,6 +822,8 @@ impl WeightInfo for () { /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) /// Storage: `TfgridModule::NodePower` (r:1 w:0) /// Proof: `TfgridModule::NodePower` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::DedicatedNodesExtraFee` (r:1 w:0) /// Proof: `SmartContractModule::DedicatedNodesExtraFee` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::BillingFrequency` (r:1 w:0) @@ -816,9 +836,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1607` // Estimated: `7547` - // Minimum execution time: 70_012_000 picoseconds. - Weight::from_parts(71_505_000, 7547) - .saturating_add(RocksDbWeight::get().reads(14_u64)) + // Minimum execution time: 138_767_000 picoseconds. + Weight::from_parts(147_354_000, 7547) + .saturating_add(RocksDbWeight::get().reads(15_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `SmartContractModule::SolutionProviderID` (r:1 w:1) @@ -829,8 +849,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `37` // Estimated: `1522` - // Minimum execution time: 9_618_000 picoseconds. - Weight::from_parts(10_009_000, 1522) + // Minimum execution time: 19_151_000 picoseconds. + Weight::from_parts(19_702_000, 1522) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -840,8 +860,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `215` // Estimated: `3680` - // Minimum execution time: 12_484_000 picoseconds. - Weight::from_parts(12_854_000, 3680) + // Minimum execution time: 24_809_000 picoseconds. + Weight::from_parts(25_573_000, 3680) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -863,6 +883,8 @@ impl WeightInfo for () { /// Proof: `TfgridModule::TwinBoundedAccountID` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::ContractBillingInformationByID` (r:1 w:1) /// Proof: `SmartContractModule::ContractBillingInformationByID` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::NodeContractResources` (r:1 w:0) @@ -881,9 +903,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `2077` // Estimated: `8017` - // Minimum execution time: 83_768_000 picoseconds. - Weight::from_parts(85_121_000, 8017) - .saturating_add(RocksDbWeight::get().reads(17_u64)) + // Minimum execution time: 198_668_000 picoseconds. + Weight::from_parts(308_991_000, 8017) + .saturating_add(RocksDbWeight::get().reads(18_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } /// Storage: `TfgridModule::TwinIdByAccountID` (r:2 w:0) @@ -896,8 +918,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `395` // Estimated: `6335` - // Minimum execution time: 17_804_000 picoseconds. - Weight::from_parts(18_284_000, 6335) + // Minimum execution time: 51_524_000 picoseconds. + Weight::from_parts(58_527_000, 6335) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -909,8 +931,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `489` // Estimated: `3954` - // Minimum execution time: 15_980_000 picoseconds. - Weight::from_parts(16_271_000, 3954) + // Minimum execution time: 31_567_000 picoseconds. + Weight::from_parts(52_961_000, 3954) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -922,8 +944,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `489` // Estimated: `3954` - // Minimum execution time: 15_880_000 picoseconds. - Weight::from_parts(16_190_000, 3954) + // Minimum execution time: 33_377_000 picoseconds. + Weight::from_parts(48_525_000, 3954) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -935,8 +957,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `502` // Estimated: `3967` - // Minimum execution time: 16_311_000 picoseconds. - Weight::from_parts(16_672_000, 3967) + // Minimum execution time: 45_324_000 picoseconds. + Weight::from_parts(56_352_000, 3967) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -948,8 +970,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `502` // Estimated: `3967` - // Minimum execution time: 16_271_000 picoseconds. - Weight::from_parts(17_142_000, 3967) + // Minimum execution time: 47_713_000 picoseconds. + Weight::from_parts(50_466_000, 3967) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -961,8 +983,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `502` // Estimated: `3967` - // Minimum execution time: 15_620_000 picoseconds. - Weight::from_parts(15_930_000, 3967) + // Minimum execution time: 44_626_000 picoseconds. + Weight::from_parts(51_600_000, 3967) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -980,8 +1002,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `841` // Estimated: `6781` - // Minimum execution time: 28_193_000 picoseconds. - Weight::from_parts(28_955_000, 6781) + // Minimum execution time: 63_936_000 picoseconds. + Weight::from_parts(91_117_000, 6781) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -991,8 +1013,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `37` // Estimated: `1522` - // Minimum execution time: 7_585_000 picoseconds. - Weight::from_parts(7_805_000, 1522) + // Minimum execution time: 16_676_000 picoseconds. + Weight::from_parts(25_396_000, 1522) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1006,8 +1028,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `965` // Estimated: `4430` - // Minimum execution time: 21_100_000 picoseconds. - Weight::from_parts(21_641_000, 4430) + // Minimum execution time: 43_672_000 picoseconds. + Weight::from_parts(62_786_000, 4430) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1027,8 +1049,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `733` // Estimated: `4198` - // Minimum execution time: 22_243_000 picoseconds. - Weight::from_parts(23_034_000, 4198) + // Minimum execution time: 45_803_000 picoseconds. + Weight::from_parts(69_341_000, 4198) .saturating_add(RocksDbWeight::get().reads(5_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1050,6 +1072,8 @@ impl WeightInfo for () { /// Proof: `TfgridModule::TwinBoundedAccountID` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Timestamp::Now` (r:1 w:0) /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:0) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::ActiveRentContractForNode` (r:1 w:0) /// Proof: `SmartContractModule::ActiveRentContractForNode` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `SmartContractModule::BillingFrequency` (r:1 w:0) @@ -1066,9 +1090,9 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `1650` // Estimated: `7590` - // Minimum execution time: 71_696_000 picoseconds. - Weight::from_parts(73_088_000, 7590) - .saturating_add(RocksDbWeight::get().reads(13_u64)) + // Minimum execution time: 148_314_000 picoseconds. + Weight::from_parts(230_693_000, 7590) + .saturating_add(RocksDbWeight::get().reads(14_u64)) .saturating_add(RocksDbWeight::get().writes(7_u64)) } } diff --git a/substrate-node/pallets/pallet-tfgrid/src/benchmarking.rs b/substrate-node/pallets/pallet-tfgrid/src/benchmarking.rs index 1bf13bc87..28362fe40 100644 --- a/substrate-node/pallets/pallet-tfgrid/src/benchmarking.rs +++ b/substrate-node/pallets/pallet-tfgrid/src/benchmarking.rs @@ -3,7 +3,7 @@ use super::*; use crate::Pallet as TfgridModule; use frame_benchmarking::{account, benchmarks, whitelisted_caller}; -use frame_support::{assert_ok, BoundedVec}; +use frame_support::{assert_ok, traits::Get, BoundedVec}; use frame_system::{pallet_prelude::BlockNumberFor, EventRecord, Pallet as System, RawOrigin}; // use hex; // use scale_info::prelude::format; @@ -844,6 +844,64 @@ benchmarks! { assert_last_event::(Event::NodeUptimeReported(node_id, now, uptime).into()); } + // opt_out_of_v3_billing() + opt_out_of_v3_billing { + let caller: T::AccountId = whitelisted_caller(); + _prepare_farm_with_node::(caller.clone()); + let node_id = 1; + }: _(RawOrigin::Signed(caller), node_id) + verify { + assert!(TfgridModule::::node_v3_billing_opt_out(node_id).is_some()); + assert_last_event::(Event::NodeV3BillingOptedOut { + node_id, + opted_out_at: TfgridModule::::node_v3_billing_opt_out(node_id).unwrap(), + }.into()); + } + + // add_twin_admin() + // Worst case: list is at MaxTwinAdmins - 1 before the final insert. + // n ranges from 0 to MaxTwinAdmins - 1; the extrinsic itself adds the (n+1)-th entry. + add_twin_admin { + let n in 0 .. (T::MaxTwinAdmins::get() - 1); + for i in 0..n { + let existing: T::AccountId = account("existing", i, 0); + assert_ok!(TfgridModule::::add_twin_admin( + RawOrigin::Root.into(), + existing, + )); + } + let caller: T::AccountId = account("Alice", 0, 0); + }: _(RawOrigin::Root, caller.clone()) + verify { + let admins = TfgridModule::::allowed_twin_admins().unwrap_or_default(); + assert!(admins.contains(&caller)); + assert_last_event::(Event::TwinAdminAdded(caller).into()); + } + + // remove_twin_admin() + // Worst case: list is at MaxTwinAdmins before the remove. + // n ranges from 1 to MaxTwinAdmins; the extrinsic removes one entry from an n-element list. + remove_twin_admin { + let n in 1 .. T::MaxTwinAdmins::get(); + let caller: T::AccountId = account("Alice", 0, 0); + assert_ok!(TfgridModule::::add_twin_admin( + RawOrigin::Root.into(), + caller.clone(), + )); + for i in 1..n { + let existing: T::AccountId = account("existing", i, 0); + assert_ok!(TfgridModule::::add_twin_admin( + RawOrigin::Root.into(), + existing, + )); + } + }: _(RawOrigin::Root, caller.clone()) + verify { + let admins = TfgridModule::::allowed_twin_admins().unwrap_or_default(); + assert!(!admins.contains(&caller)); + assert_last_event::(Event::TwinAdminRemoved(caller).into()); + } + // Calling the `impl_benchmark_test_suite` macro inside the `benchmarks` // block will generate one #[test] function per benchmark impl_benchmark_test_suite!(TfgridModule, crate::mock::new_test_ext(), crate::mock::TestRuntime) diff --git a/substrate-node/pallets/pallet-tfgrid/src/lib.rs b/substrate-node/pallets/pallet-tfgrid/src/lib.rs index 2ecbd4ab1..212bd3dc1 100644 --- a/substrate-node/pallets/pallet-tfgrid/src/lib.rs +++ b/substrate-node/pallets/pallet-tfgrid/src/lib.rs @@ -11,6 +11,7 @@ pub mod terms_cond; pub mod twin; pub mod twin_transfer; pub mod types; +pub mod v3_billing_opt_out; pub mod weights; #[cfg(test)] @@ -253,6 +254,20 @@ pub mod pallet { #[pallet::getter(fn zos_version)] pub type ZosVersion = StorageValue<_, Vec, ValueQuery>; + // Keyed by node_id. Present = node has opted out of v3 billing. + #[pallet::storage] + #[pallet::getter(fn node_v3_billing_opt_out)] + pub type NodeV3BillingOptOut = + StorageMap<_, Blake2_128Concat, u32, u64, OptionQuery>; + + // Global list of accounts authorized to deploy on opted-out nodes. + // None = list not initialized (treat as empty = no one allowed). + // Bounded to prevent unbounded storage growth. + #[pallet::storage] + #[pallet::getter(fn allowed_twin_admins)] + pub type AllowedTwinAdmins = + StorageValue<_, BoundedVec, OptionQuery>; + // This storage map maps a node ID to a power state, they node can modify this state // to indicate that it has shut down or came back alive #[pallet::storage] @@ -405,6 +420,9 @@ pub mod pallet { #[pallet::constant] type MaxFarmPublicIps: Get; + #[pallet::constant] + type MaxTwinAdmins: Get; + #[pallet::constant] type MaxInterfacesLength: Get; @@ -469,6 +487,11 @@ pub mod pallet { power_state: PowerState>, }, + // V3 billing opt-out + NodeV3BillingOptedOut { node_id: u32, opted_out_at: u64 }, + TwinAdminAdded(T::AccountId), + TwinAdminRemoved(T::AccountId), + // Twin ownership transfer lifecycle TwinTransferRequested { request_id: u64, @@ -629,6 +652,12 @@ pub mod pallet { TwinTransferRequestNotFound, TwinTransferNewAccountHasTwin, TwinTransferPendingExists, + + // V3 billing opt-out errors + NodeV3BillingOptOutAlreadyEnabled, + AlreadyTwinAdmin, + NotTwinAdmin, + TwinAdminListFull, } #[pallet::genesis_config] @@ -1323,5 +1352,38 @@ pub mod pallet { ) -> DispatchResultWithPostInfo { Self::_cancel_twin_transfer(origin, request_id) } + + // Farmer opts their node out of v3 billing + #[pallet::call_index(43)] + #[pallet::weight(::WeightInfo::opt_out_of_v3_billing())] + pub fn opt_out_of_v3_billing( + origin: OriginFor, + node_id: u32, + ) -> DispatchResultWithPostInfo { + let account_id = ensure_signed(origin)?; + Self::_opt_out_of_v3_billing(account_id, node_id) + } + + // Council adds an account to the twin admin list (allowed to deploy on opted-out nodes) + #[pallet::call_index(44)] + #[pallet::weight(::WeightInfo::add_twin_admin())] + pub fn add_twin_admin( + origin: OriginFor, + account: T::AccountId, + ) -> DispatchResultWithPostInfo { + T::RestrictedOrigin::ensure_origin(origin)?; + Self::_add_twin_admin(account) + } + + // Council removes an account from the twin admin list + #[pallet::call_index(45)] + #[pallet::weight(::WeightInfo::remove_twin_admin())] + pub fn remove_twin_admin( + origin: OriginFor, + account: T::AccountId, + ) -> DispatchResultWithPostInfo { + T::RestrictedOrigin::ensure_origin(origin)?; + Self::_remove_twin_admin(account) + } } } diff --git a/substrate-node/pallets/pallet-tfgrid/src/mock.rs b/substrate-node/pallets/pallet-tfgrid/src/mock.rs index 0f516d9cc..c44dc1c29 100644 --- a/substrate-node/pallets/pallet-tfgrid/src/mock.rs +++ b/substrate-node/pallets/pallet-tfgrid/src/mock.rs @@ -105,6 +105,7 @@ parameter_types! { pub const MaxInterfaceIpsLength: u32 = 5; pub const MaxInterfacesLength: u32 = 10; pub const MaxFarmPublicIps: u32 = 512; + pub const MaxTwinAdmins: u32 = 10; pub const TimestampHintDrift: u64 = 60; } @@ -133,6 +134,7 @@ impl Config for TestRuntime { type FarmName = TestFarmName; type MaxFarmNameLength = MaxFarmNameLength; type MaxFarmPublicIps = MaxFarmPublicIps; + type MaxTwinAdmins = MaxTwinAdmins; type InterfaceName = TestInterfaceName; type InterfaceMac = TestInterfaceMac; type InterfaceIP = TestInterfaceIp; diff --git a/substrate-node/pallets/pallet-tfgrid/src/node.rs b/substrate-node/pallets/pallet-tfgrid/src/node.rs index c440c97fb..88ad28bfe 100644 --- a/substrate-node/pallets/pallet-tfgrid/src/node.rs +++ b/substrate-node/pallets/pallet-tfgrid/src/node.rs @@ -275,6 +275,7 @@ impl Pallet { T::NodeChanged::node_deleted(&node); Nodes::::remove(node_id); + NodeV3BillingOptOut::::remove(node_id); Self::deposit_event(Event::NodeDeleted(node_id)); diff --git a/substrate-node/pallets/pallet-tfgrid/src/tests.rs b/substrate-node/pallets/pallet-tfgrid/src/tests.rs index 1bb52ef5e..60d7c98cf 100644 --- a/substrate-node/pallets/pallet-tfgrid/src/tests.rs +++ b/substrate-node/pallets/pallet-tfgrid/src/tests.rs @@ -2843,6 +2843,217 @@ fn record(event: RuntimeEvent) -> EventRecord { } // Attach given farming policy to farm 1 that contains node 1 +// ------------------------------------ // +// V3 BILLING OPT-OUT TESTS // +// ------------------------------------ // + +#[test] +fn test_opt_out_of_v3_billing_works() { + ExternalityBuilder::build().execute_with(|| { + create_twin(); + create_farm(); + create_node(); + let node_id = 1; + + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + + assert!(TfgridModule::node_v3_billing_opt_out(node_id).is_some()); + + let our_events = System::events(); + assert!(our_events.iter().any(|e| matches!( + &e.event, + MockEvent::TfgridModule(TfgridEvent::::NodeV3BillingOptedOut { + node_id: 1, + .. + }) + ))); + }); +} + +#[test] +fn test_opt_out_of_v3_billing_not_farmer_fails() { + ExternalityBuilder::build().execute_with(|| { + create_twin(); + create_twin_bob(); + create_farm(); + create_node(); + let node_id = 1; + + assert_noop!( + TfgridModule::opt_out_of_v3_billing(RuntimeOrigin::signed(bob()), node_id), + Error::::NodeUpdateNotAuthorized + ); + }); +} + +#[test] +fn test_opt_out_of_v3_billing_node_not_exists_fails() { + ExternalityBuilder::build().execute_with(|| { + create_twin(); + create_farm(); + + assert_noop!( + TfgridModule::opt_out_of_v3_billing(RuntimeOrigin::signed(alice()), 999), + Error::::NodeNotExists + ); + }); +} + +#[test] +fn test_opt_out_of_v3_billing_already_opted_out_fails() { + ExternalityBuilder::build().execute_with(|| { + create_twin(); + create_farm(); + create_node(); + let node_id = 1; + + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + + assert_noop!( + TfgridModule::opt_out_of_v3_billing(RuntimeOrigin::signed(alice()), node_id), + Error::::NodeV3BillingOptOutAlreadyEnabled + ); + }); +} + +#[test] +fn test_add_twin_admin_works() { + ExternalityBuilder::build().execute_with(|| { + assert_ok!(TfgridModule::add_twin_admin( + RawOrigin::Root.into(), + alice(), + )); + + let admins = TfgridModule::allowed_twin_admins().unwrap_or_default(); + assert!(admins.contains(&alice())); + + let our_events = System::events(); + assert!(our_events.iter().any(|e| matches!( + &e.event, + MockEvent::TfgridModule(TfgridEvent::::TwinAdminAdded(_)) + ))); + }); +} + +#[test] +fn test_add_twin_admin_not_council_fails() { + ExternalityBuilder::build().execute_with(|| { + assert_noop!( + TfgridModule::add_twin_admin(RuntimeOrigin::signed(alice()), alice()), + sp_runtime::DispatchError::BadOrigin + ); + }); +} + +#[test] +fn test_add_twin_admin_duplicate_fails() { + ExternalityBuilder::build().execute_with(|| { + assert_ok!(TfgridModule::add_twin_admin( + RawOrigin::Root.into(), + alice(), + )); + + assert_noop!( + TfgridModule::add_twin_admin(RawOrigin::Root.into(), alice()), + Error::::AlreadyTwinAdmin + ); + }); +} + +#[test] +fn test_remove_twin_admin_works() { + ExternalityBuilder::build().execute_with(|| { + assert_ok!(TfgridModule::add_twin_admin( + RawOrigin::Root.into(), + alice(), + )); + + assert_ok!(TfgridModule::remove_twin_admin( + RawOrigin::Root.into(), + alice(), + )); + + let admins = TfgridModule::allowed_twin_admins().unwrap_or_default(); + assert!(!admins.contains(&alice())); + + let our_events = System::events(); + assert!(our_events.iter().any(|e| matches!( + &e.event, + MockEvent::TfgridModule(TfgridEvent::::TwinAdminRemoved(_)) + ))); + }); +} + +#[test] +fn test_remove_twin_admin_not_council_fails() { + ExternalityBuilder::build().execute_with(|| { + assert_noop!( + TfgridModule::remove_twin_admin(RuntimeOrigin::signed(alice()), alice()), + sp_runtime::DispatchError::BadOrigin + ); + }); +} + +#[test] +fn test_remove_twin_admin_not_exists_fails() { + ExternalityBuilder::build().execute_with(|| { + assert_noop!( + TfgridModule::remove_twin_admin(RawOrigin::Root.into(), alice()), + Error::::NotTwinAdmin + ); + }); +} + +#[test] +fn test_add_twin_admin_list_full() { + ExternalityBuilder::build().execute_with(|| { + // Fill the list up to MaxTwinAdmins (= 10 in test config) + for i in 0..10u64 { + let account = AccountId::from([i as u8; 32]); + assert_ok!(TfgridModule::add_twin_admin( + RawOrigin::Root.into(), + account, + )); + } + + // The 11th add must fail with TwinAdminListFull + let overflow = AccountId::from([99u8; 32]); + assert_noop!( + TfgridModule::add_twin_admin(RawOrigin::Root.into(), overflow), + Error::::TwinAdminListFull + ); + }); +} + +#[test] +fn test_delete_opted_out_node_cleans_up_storage() { + ExternalityBuilder::build().execute_with(|| { + create_twin(); + create_farm(); + create_node(); + let node_id = 1; + + assert_ok!(TfgridModule::opt_out_of_v3_billing( + RuntimeOrigin::signed(alice()), + node_id, + )); + assert!(TfgridModule::node_v3_billing_opt_out(node_id).is_some()); + + assert_ok!(TfgridModule::delete_node( + RuntimeOrigin::signed(alice()), + node_id, + )); + + assert!(TfgridModule::node_v3_billing_opt_out(node_id).is_none()); + }); +} + fn test_attach_farming_policy_flow(farming_policy_id: u32) { create_twin(); create_farm(); diff --git a/substrate-node/pallets/pallet-tfgrid/src/v3_billing_opt_out.rs b/substrate-node/pallets/pallet-tfgrid/src/v3_billing_opt_out.rs new file mode 100644 index 000000000..a1327da07 --- /dev/null +++ b/substrate-node/pallets/pallet-tfgrid/src/v3_billing_opt_out.rs @@ -0,0 +1,77 @@ +use crate::pallet::{ + AllowedTwinAdmins, Error, Event, Farms, NodeV3BillingOptOut, Nodes, TwinIdByAccountID, +}; +use crate::Config; +use frame_support::{dispatch::DispatchResultWithPostInfo, ensure, BoundedVec}; +use sp_runtime::SaturatedConversion; +use sp_std::vec; + +impl crate::Pallet { + pub fn _opt_out_of_v3_billing( + account_id: T::AccountId, + node_id: u32, + ) -> DispatchResultWithPostInfo { + let caller_twin_id = + TwinIdByAccountID::::get(&account_id).ok_or(Error::::TwinNotExists)?; + + let node = Nodes::::get(node_id).ok_or(Error::::NodeNotExists)?; + + let farm = Farms::::get(node.farm_id).ok_or(Error::::FarmNotExists)?; + + ensure!( + caller_twin_id == farm.twin_id, + Error::::NodeUpdateNotAuthorized + ); + + ensure!( + !NodeV3BillingOptOut::::contains_key(node_id), + Error::::NodeV3BillingOptOutAlreadyEnabled + ); + + let now: u64 = + >::get().saturated_into::() / 1000; + + NodeV3BillingOptOut::::insert(node_id, now); + + Self::deposit_event(Event::NodeV3BillingOptedOut { + node_id, + opted_out_at: now, + }); + + Ok(().into()) + } + + pub fn _add_twin_admin(account: T::AccountId) -> DispatchResultWithPostInfo { + let mut admins = AllowedTwinAdmins::::get() + .unwrap_or_else(|| BoundedVec::new()); + + let location = admins + .binary_search(&account) + .err() + .ok_or(Error::::AlreadyTwinAdmin)?; + + admins + .try_insert(location, account.clone()) + .map_err(|_| Error::::TwinAdminListFull)?; + + AllowedTwinAdmins::::put(admins); + + Self::deposit_event(Event::TwinAdminAdded(account)); + + Ok(().into()) + } + + pub fn _remove_twin_admin(account: T::AccountId) -> DispatchResultWithPostInfo { + let mut admins = AllowedTwinAdmins::::get().ok_or(Error::::NotTwinAdmin)?; + let location = admins + .binary_search(&account) + .ok() + .ok_or(Error::::NotTwinAdmin)?; + admins.remove(location); + AllowedTwinAdmins::::put(admins); + + Self::deposit_event(Event::TwinAdminRemoved(account)); + + Ok(().into()) + } +} diff --git a/substrate-node/pallets/pallet-tfgrid/src/weights.rs b/substrate-node/pallets/pallet-tfgrid/src/weights.rs index e9d1ffa27..342baef22 100644 --- a/substrate-node/pallets/pallet-tfgrid/src/weights.rs +++ b/substrate-node/pallets/pallet-tfgrid/src/weights.rs @@ -2,9 +2,9 @@ //! Autogenerated weights for pallet_tfgrid //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2025-09-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2026-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ebea9d7a9918`, CPU: `AMD Ryzen 7 5800X 8-Core Processor` +//! HOSTNAME: `19750001b071`, CPU: `DO-Regular` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -68,6 +68,9 @@ pub trait WeightInfo { fn change_power_target() -> Weight; fn bond_twin_account() -> Weight; fn report_uptime_v2() -> Weight; + fn opt_out_of_v3_billing() -> Weight; + fn add_twin_admin() -> Weight; + fn remove_twin_admin() -> Weight; } /// Weights for pallet_tfgrid using the Substrate node and recommended hardware. @@ -79,8 +82,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_284_000 picoseconds. - Weight::from_parts(2_405_000, 0) + // Minimum execution time: 7_760_000 picoseconds. + Weight::from_parts(9_173_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `TfgridModule::TwinIdByAccountID` (r:1 w:0) @@ -97,8 +100,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `496` // Estimated: `3961` - // Minimum execution time: 18_746_000 picoseconds. - Weight::from_parts(19_337_000, 3961) + // Minimum execution time: 37_380_000 picoseconds. + Weight::from_parts(50_833_000, 3961) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -112,8 +115,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `507` // Estimated: `3972` - // Minimum execution time: 20_800_000 picoseconds. - Weight::from_parts(21_331_000, 3972) + // Minimum execution time: 60_031_000 picoseconds. + Weight::from_parts(65_299_000, 3972) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -127,8 +130,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `453` // Estimated: `3918` - // Minimum execution time: 14_998_000 picoseconds. - Weight::from_parts(15_429_000, 3918) + // Minimum execution time: 31_146_000 picoseconds. + Weight::from_parts(47_051_000, 3918) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -138,8 +141,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `412` // Estimated: `3877` - // Minimum execution time: 12_654_000 picoseconds. - Weight::from_parts(13_035_000, 3877) + // Minimum execution time: 36_321_000 picoseconds. + Weight::from_parts(40_473_000, 3877) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -151,8 +154,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `569` // Estimated: `4034` - // Minimum execution time: 17_192_000 picoseconds. - Weight::from_parts(17_713_000, 4034) + // Minimum execution time: 38_151_000 picoseconds. + Weight::from_parts(52_836_000, 4034) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -164,8 +167,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `569` // Estimated: `4034` - // Minimum execution time: 16_260_000 picoseconds. - Weight::from_parts(16_882_000, 4034) + // Minimum execution time: 32_423_000 picoseconds. + Weight::from_parts(46_829_000, 4034) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -193,8 +196,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `905` // Estimated: `11795` - // Minimum execution time: 46_238_000 picoseconds. - Weight::from_parts(47_430_000, 11795) + // Minimum execution time: 90_029_000 picoseconds. + Weight::from_parts(130_789_000, 11795) .saturating_add(T::DbWeight::get().reads(12_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -210,8 +213,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `661` // Estimated: `4126` - // Minimum execution time: 26_069_000 picoseconds. - Weight::from_parts(26_841_000, 4126) + // Minimum execution time: 51_884_000 picoseconds. + Weight::from_parts(85_305_000, 4126) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -225,8 +228,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `956` // Estimated: `11846` - // Minimum execution time: 32_842_000 picoseconds. - Weight::from_parts(33_854_000, 11846) + // Minimum execution time: 78_839_000 picoseconds. + Weight::from_parts(99_655_000, 11846) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -242,8 +245,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `454` // Estimated: `3919` - // Minimum execution time: 17_933_000 picoseconds. - Weight::from_parts(18_254_000, 3919) + // Minimum execution time: 33_838_000 picoseconds. + Weight::from_parts(50_283_000, 3919) .saturating_add(T::DbWeight::get().reads(4_u64)) } /// Storage: `TfgridModule::Farms` (r:1 w:0) @@ -256,8 +259,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `779` // Estimated: `4244` - // Minimum execution time: 23_605_000 picoseconds. - Weight::from_parts(24_676_000, 4244) + // Minimum execution time: 60_613_000 picoseconds. + Weight::from_parts(62_014_000, 4244) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -273,14 +276,16 @@ impl WeightInfo for SubstrateWeight { /// Proof: `SmartContractModule::ActiveRentContractForNode` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Dao::FarmWeight` (r:1 w:1) /// Proof: `Dao::FarmWeight` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:0 w:1) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) fn delete_node() -> Weight { // Proof Size summary in bytes: // Measured: `682` // Estimated: `4147` - // Minimum execution time: 26_640_000 picoseconds. - Weight::from_parts(27_292_000, 4147) + // Minimum execution time: 58_291_000 picoseconds. + Weight::from_parts(78_853_000, 4147) .saturating_add(T::DbWeight::get().reads(6_u64)) - .saturating_add(T::DbWeight::get().writes(3_u64)) + .saturating_add(T::DbWeight::get().writes(4_u64)) } /// Storage: `TfgridModule::UsersTermsAndConditions` (r:1 w:0) /// Proof: `TfgridModule::UsersTermsAndConditions` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -294,8 +299,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `235` // Estimated: `3700` - // Minimum execution time: 14_107_000 picoseconds. - Weight::from_parts(14_448_000, 3700) + // Minimum execution time: 27_602_000 picoseconds. + Weight::from_parts(42_395_000, 3700) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -307,8 +312,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `428` // Estimated: `3893` - // Minimum execution time: 14_458_000 picoseconds. - Weight::from_parts(14_858_000, 3893) + // Minimum execution time: 41_364_000 picoseconds. + Weight::from_parts(43_444_000, 3893) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -322,8 +327,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `134` // Estimated: `3599` - // Minimum execution time: 12_073_000 picoseconds. - Weight::from_parts(12_394_000, 3599) + // Minimum execution time: 35_299_000 picoseconds. + Weight::from_parts(39_112_000, 3599) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -337,8 +342,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `382` // Estimated: `3847` - // Minimum execution time: 16_020_000 picoseconds. - Weight::from_parts(16_551_000, 3847) + // Minimum execution time: 44_802_000 picoseconds. + Weight::from_parts(49_756_000, 3847) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -350,8 +355,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `134` // Estimated: `1619` - // Minimum execution time: 9_868_000 picoseconds. - Weight::from_parts(10_139_000, 1619) + // Minimum execution time: 30_200_000 picoseconds. + Weight::from_parts(33_059_000, 1619) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -363,8 +368,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `140` // Estimated: `3605` - // Minimum execution time: 7_134_000 picoseconds. - Weight::from_parts(7_604_000, 3605) + // Minimum execution time: 13_830_000 picoseconds. + Weight::from_parts(22_516_000, 3605) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -384,8 +389,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `527` // Estimated: `6467` - // Minimum execution time: 22_352_000 picoseconds. - Weight::from_parts(22_903_000, 6467) + // Minimum execution time: 64_775_000 picoseconds. + Weight::from_parts(69_397_000, 6467) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -401,8 +406,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `605` // Estimated: `4070` - // Minimum execution time: 25_308_000 picoseconds. - Weight::from_parts(25_959_000, 4070) + // Minimum execution time: 50_576_000 picoseconds. + Weight::from_parts(55_237_000, 4070) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -414,8 +419,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `403` // Estimated: `3868` - // Minimum execution time: 12_684_000 picoseconds. - Weight::from_parts(13_095_000, 3868) + // Minimum execution time: 24_901_000 picoseconds. + Weight::from_parts(26_998_000, 3868) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -439,8 +444,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `828` // Estimated: `4293` - // Minimum execution time: 31_390_000 picoseconds. - Weight::from_parts(31_870_000, 4293) + // Minimum execution time: 60_135_000 picoseconds. + Weight::from_parts(62_199_000, 4293) .saturating_add(T::DbWeight::get().reads(7_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -450,8 +455,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `412` // Estimated: `3877` - // Minimum execution time: 13_085_000 picoseconds. - Weight::from_parts(13_495_000, 3877) + // Minimum execution time: 37_384_000 picoseconds. + Weight::from_parts(41_357_000, 3877) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -461,8 +466,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `412` // Estimated: `3877` - // Minimum execution time: 13_355_000 picoseconds. - Weight::from_parts(13_636_000, 3877) + // Minimum execution time: 25_288_000 picoseconds. + Weight::from_parts(38_313_000, 3877) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -472,8 +477,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_430_000 picoseconds. - Weight::from_parts(5_671_000, 0) + // Minimum execution time: 18_095_000 picoseconds. + Weight::from_parts(22_993_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `TfgridModule::AllowedNodeCertifiers` (r:1 w:1) @@ -482,8 +487,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `355` // Estimated: `1840` - // Minimum execution time: 9_378_000 picoseconds. - Weight::from_parts(9_708_000, 1840) + // Minimum execution time: 18_474_000 picoseconds. + Weight::from_parts(30_915_000, 1840) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -493,8 +498,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `413` // Estimated: `1898` - // Minimum execution time: 11_522_000 picoseconds. - Weight::from_parts(11_943_000, 1898) + // Minimum execution time: 31_528_000 picoseconds. + Weight::from_parts(41_091_000, 1898) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -504,8 +509,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `294` // Estimated: `3759` - // Minimum execution time: 12_774_000 picoseconds. - Weight::from_parts(13_095_000, 3759) + // Minimum execution time: 37_342_000 picoseconds. + Weight::from_parts(40_293_000, 3759) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -519,8 +524,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `572` // Estimated: `4037` - // Minimum execution time: 21_541_000 picoseconds. - Weight::from_parts(22_332_000, 4037) + // Minimum execution time: 43_415_000 picoseconds. + Weight::from_parts(63_666_000, 4037) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -530,8 +535,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `134` // Estimated: `1619` - // Minimum execution time: 7_715_000 picoseconds. - Weight::from_parts(8_015_000, 1619) + // Minimum execution time: 15_467_000 picoseconds. + Weight::from_parts(17_654_000, 1619) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -547,8 +552,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `621` // Estimated: `4086` - // Minimum execution time: 21_741_000 picoseconds. - Weight::from_parts(22_542_000, 4086) + // Minimum execution time: 62_484_000 picoseconds. + Weight::from_parts(70_463_000, 4086) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -568,8 +573,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `792` // Estimated: `4257` - // Minimum execution time: 25_217_000 picoseconds. - Weight::from_parts(26_030_000, 4257) + // Minimum execution time: 71_117_000 picoseconds. + Weight::from_parts(79_965_000, 4257) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -581,8 +586,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `387` // Estimated: `3852` - // Minimum execution time: 11_622_000 picoseconds. - Weight::from_parts(12_113_000, 3852) + // Minimum execution time: 23_082_000 picoseconds. + Weight::from_parts(36_426_000, 3852) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -598,10 +603,51 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `454` // Estimated: `3919` - // Minimum execution time: 17_093_000 picoseconds. - Weight::from_parts(17_382_000, 3919) + // Minimum execution time: 36_465_000 picoseconds. + Weight::from_parts(49_740_000, 3919) .saturating_add(T::DbWeight::get().reads(4_u64)) } + /// Storage: `TfgridModule::TwinIdByAccountID` (r:1 w:0) + /// Proof: `TfgridModule::TwinIdByAccountID` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::Nodes` (r:1 w:0) + /// Proof: `TfgridModule::Nodes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::Farms` (r:1 w:0) + /// Proof: `TfgridModule::Farms` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:1) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Timestamp::Now` (r:1 w:0) + /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + fn opt_out_of_v3_billing() -> Weight { + // Proof Size summary in bytes: + // Measured: `669` + // Estimated: `4134` + // Minimum execution time: 41_441_000 picoseconds. + Weight::from_parts(66_855_000, 4134) + .saturating_add(T::DbWeight::get().reads(5_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `TfgridModule::AllowedTwinAdmins` (r:1 w:1) + /// Proof: `TfgridModule::AllowedTwinAdmins` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn add_twin_admin() -> Weight { + // Proof Size summary in bytes: + // Measured: `134` + // Estimated: `1619` + // Minimum execution time: 24_015_000 picoseconds. + Weight::from_parts(27_477_000, 1619) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: `TfgridModule::AllowedTwinAdmins` (r:1 w:1) + /// Proof: `TfgridModule::AllowedTwinAdmins` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn remove_twin_admin() -> Weight { + // Proof Size summary in bytes: + // Measured: `189` + // Estimated: `1674` + // Minimum execution time: 18_618_000 picoseconds. + Weight::from_parts(28_136_000, 1674) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } } // For backwards compatibility and tests @@ -612,8 +658,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_284_000 picoseconds. - Weight::from_parts(2_405_000, 0) + // Minimum execution time: 7_760_000 picoseconds. + Weight::from_parts(9_173_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `TfgridModule::TwinIdByAccountID` (r:1 w:0) @@ -630,8 +676,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `496` // Estimated: `3961` - // Minimum execution time: 18_746_000 picoseconds. - Weight::from_parts(19_337_000, 3961) + // Minimum execution time: 37_380_000 picoseconds. + Weight::from_parts(50_833_000, 3961) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -645,8 +691,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `507` // Estimated: `3972` - // Minimum execution time: 20_800_000 picoseconds. - Weight::from_parts(21_331_000, 3972) + // Minimum execution time: 60_031_000 picoseconds. + Weight::from_parts(65_299_000, 3972) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -660,8 +706,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `453` // Estimated: `3918` - // Minimum execution time: 14_998_000 picoseconds. - Weight::from_parts(15_429_000, 3918) + // Minimum execution time: 31_146_000 picoseconds. + Weight::from_parts(47_051_000, 3918) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -671,8 +717,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `412` // Estimated: `3877` - // Minimum execution time: 12_654_000 picoseconds. - Weight::from_parts(13_035_000, 3877) + // Minimum execution time: 36_321_000 picoseconds. + Weight::from_parts(40_473_000, 3877) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -684,8 +730,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `569` // Estimated: `4034` - // Minimum execution time: 17_192_000 picoseconds. - Weight::from_parts(17_713_000, 4034) + // Minimum execution time: 38_151_000 picoseconds. + Weight::from_parts(52_836_000, 4034) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -697,8 +743,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `569` // Estimated: `4034` - // Minimum execution time: 16_260_000 picoseconds. - Weight::from_parts(16_882_000, 4034) + // Minimum execution time: 32_423_000 picoseconds. + Weight::from_parts(46_829_000, 4034) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -726,8 +772,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `905` // Estimated: `11795` - // Minimum execution time: 46_238_000 picoseconds. - Weight::from_parts(47_430_000, 11795) + // Minimum execution time: 90_029_000 picoseconds. + Weight::from_parts(130_789_000, 11795) .saturating_add(RocksDbWeight::get().reads(12_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -743,8 +789,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `661` // Estimated: `4126` - // Minimum execution time: 26_069_000 picoseconds. - Weight::from_parts(26_841_000, 4126) + // Minimum execution time: 51_884_000 picoseconds. + Weight::from_parts(85_305_000, 4126) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -758,8 +804,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `956` // Estimated: `11846` - // Minimum execution time: 32_842_000 picoseconds. - Weight::from_parts(33_854_000, 11846) + // Minimum execution time: 78_839_000 picoseconds. + Weight::from_parts(99_655_000, 11846) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -775,8 +821,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `454` // Estimated: `3919` - // Minimum execution time: 17_933_000 picoseconds. - Weight::from_parts(18_254_000, 3919) + // Minimum execution time: 33_838_000 picoseconds. + Weight::from_parts(50_283_000, 3919) .saturating_add(RocksDbWeight::get().reads(4_u64)) } /// Storage: `TfgridModule::Farms` (r:1 w:0) @@ -789,8 +835,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `779` // Estimated: `4244` - // Minimum execution time: 23_605_000 picoseconds. - Weight::from_parts(24_676_000, 4244) + // Minimum execution time: 60_613_000 picoseconds. + Weight::from_parts(62_014_000, 4244) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -806,14 +852,16 @@ impl WeightInfo for () { /// Proof: `SmartContractModule::ActiveRentContractForNode` (`max_values`: None, `max_size`: None, mode: `Measured`) /// Storage: `Dao::FarmWeight` (r:1 w:1) /// Proof: `Dao::FarmWeight` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:0 w:1) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) fn delete_node() -> Weight { // Proof Size summary in bytes: // Measured: `682` // Estimated: `4147` - // Minimum execution time: 26_640_000 picoseconds. - Weight::from_parts(27_292_000, 4147) + // Minimum execution time: 58_291_000 picoseconds. + Weight::from_parts(78_853_000, 4147) .saturating_add(RocksDbWeight::get().reads(6_u64)) - .saturating_add(RocksDbWeight::get().writes(3_u64)) + .saturating_add(RocksDbWeight::get().writes(4_u64)) } /// Storage: `TfgridModule::UsersTermsAndConditions` (r:1 w:0) /// Proof: `TfgridModule::UsersTermsAndConditions` (`max_values`: None, `max_size`: None, mode: `Measured`) @@ -827,8 +875,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `235` // Estimated: `3700` - // Minimum execution time: 14_107_000 picoseconds. - Weight::from_parts(14_448_000, 3700) + // Minimum execution time: 27_602_000 picoseconds. + Weight::from_parts(42_395_000, 3700) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -840,8 +888,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `428` // Estimated: `3893` - // Minimum execution time: 14_458_000 picoseconds. - Weight::from_parts(14_858_000, 3893) + // Minimum execution time: 41_364_000 picoseconds. + Weight::from_parts(43_444_000, 3893) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -855,8 +903,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `134` // Estimated: `3599` - // Minimum execution time: 12_073_000 picoseconds. - Weight::from_parts(12_394_000, 3599) + // Minimum execution time: 35_299_000 picoseconds. + Weight::from_parts(39_112_000, 3599) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -870,8 +918,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `382` // Estimated: `3847` - // Minimum execution time: 16_020_000 picoseconds. - Weight::from_parts(16_551_000, 3847) + // Minimum execution time: 44_802_000 picoseconds. + Weight::from_parts(49_756_000, 3847) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -883,8 +931,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `134` // Estimated: `1619` - // Minimum execution time: 9_868_000 picoseconds. - Weight::from_parts(10_139_000, 1619) + // Minimum execution time: 30_200_000 picoseconds. + Weight::from_parts(33_059_000, 1619) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -896,8 +944,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `140` // Estimated: `3605` - // Minimum execution time: 7_134_000 picoseconds. - Weight::from_parts(7_604_000, 3605) + // Minimum execution time: 13_830_000 picoseconds. + Weight::from_parts(22_516_000, 3605) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -917,8 +965,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `527` // Estimated: `6467` - // Minimum execution time: 22_352_000 picoseconds. - Weight::from_parts(22_903_000, 6467) + // Minimum execution time: 64_775_000 picoseconds. + Weight::from_parts(69_397_000, 6467) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -934,8 +982,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `605` // Estimated: `4070` - // Minimum execution time: 25_308_000 picoseconds. - Weight::from_parts(25_959_000, 4070) + // Minimum execution time: 50_576_000 picoseconds. + Weight::from_parts(55_237_000, 4070) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -947,8 +995,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `403` // Estimated: `3868` - // Minimum execution time: 12_684_000 picoseconds. - Weight::from_parts(13_095_000, 3868) + // Minimum execution time: 24_901_000 picoseconds. + Weight::from_parts(26_998_000, 3868) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -972,8 +1020,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `828` // Estimated: `4293` - // Minimum execution time: 31_390_000 picoseconds. - Weight::from_parts(31_870_000, 4293) + // Minimum execution time: 60_135_000 picoseconds. + Weight::from_parts(62_199_000, 4293) .saturating_add(RocksDbWeight::get().reads(7_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -983,8 +1031,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `412` // Estimated: `3877` - // Minimum execution time: 13_085_000 picoseconds. - Weight::from_parts(13_495_000, 3877) + // Minimum execution time: 37_384_000 picoseconds. + Weight::from_parts(41_357_000, 3877) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -994,8 +1042,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `412` // Estimated: `3877` - // Minimum execution time: 13_355_000 picoseconds. - Weight::from_parts(13_636_000, 3877) + // Minimum execution time: 25_288_000 picoseconds. + Weight::from_parts(38_313_000, 3877) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1005,8 +1053,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 5_430_000 picoseconds. - Weight::from_parts(5_671_000, 0) + // Minimum execution time: 18_095_000 picoseconds. + Weight::from_parts(22_993_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `TfgridModule::AllowedNodeCertifiers` (r:1 w:1) @@ -1015,8 +1063,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `355` // Estimated: `1840` - // Minimum execution time: 9_378_000 picoseconds. - Weight::from_parts(9_708_000, 1840) + // Minimum execution time: 18_474_000 picoseconds. + Weight::from_parts(30_915_000, 1840) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1026,8 +1074,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `413` // Estimated: `1898` - // Minimum execution time: 11_522_000 picoseconds. - Weight::from_parts(11_943_000, 1898) + // Minimum execution time: 31_528_000 picoseconds. + Weight::from_parts(41_091_000, 1898) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1037,8 +1085,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `294` // Estimated: `3759` - // Minimum execution time: 12_774_000 picoseconds. - Weight::from_parts(13_095_000, 3759) + // Minimum execution time: 37_342_000 picoseconds. + Weight::from_parts(40_293_000, 3759) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1052,8 +1100,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `572` // Estimated: `4037` - // Minimum execution time: 21_541_000 picoseconds. - Weight::from_parts(22_332_000, 4037) + // Minimum execution time: 43_415_000 picoseconds. + Weight::from_parts(63_666_000, 4037) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1063,8 +1111,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `134` // Estimated: `1619` - // Minimum execution time: 7_715_000 picoseconds. - Weight::from_parts(8_015_000, 1619) + // Minimum execution time: 15_467_000 picoseconds. + Weight::from_parts(17_654_000, 1619) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1080,8 +1128,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `621` // Estimated: `4086` - // Minimum execution time: 21_741_000 picoseconds. - Weight::from_parts(22_542_000, 4086) + // Minimum execution time: 62_484_000 picoseconds. + Weight::from_parts(70_463_000, 4086) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1101,8 +1149,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `792` // Estimated: `4257` - // Minimum execution time: 25_217_000 picoseconds. - Weight::from_parts(26_030_000, 4257) + // Minimum execution time: 71_117_000 picoseconds. + Weight::from_parts(79_965_000, 4257) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1114,8 +1162,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `387` // Estimated: `3852` - // Minimum execution time: 11_622_000 picoseconds. - Weight::from_parts(12_113_000, 3852) + // Minimum execution time: 23_082_000 picoseconds. + Weight::from_parts(36_426_000, 3852) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -1131,8 +1179,49 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `454` // Estimated: `3919` - // Minimum execution time: 17_093_000 picoseconds. - Weight::from_parts(17_382_000, 3919) + // Minimum execution time: 36_465_000 picoseconds. + Weight::from_parts(49_740_000, 3919) .saturating_add(RocksDbWeight::get().reads(4_u64)) } + /// Storage: `TfgridModule::TwinIdByAccountID` (r:1 w:0) + /// Proof: `TfgridModule::TwinIdByAccountID` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::Nodes` (r:1 w:0) + /// Proof: `TfgridModule::Nodes` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::Farms` (r:1 w:0) + /// Proof: `TfgridModule::Farms` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `TfgridModule::NodeV3BillingOptOut` (r:1 w:1) + /// Proof: `TfgridModule::NodeV3BillingOptOut` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `Timestamp::Now` (r:1 w:0) + /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`) + fn opt_out_of_v3_billing() -> Weight { + // Proof Size summary in bytes: + // Measured: `669` + // Estimated: `4134` + // Minimum execution time: 41_441_000 picoseconds. + Weight::from_parts(66_855_000, 4134) + .saturating_add(RocksDbWeight::get().reads(5_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `TfgridModule::AllowedTwinAdmins` (r:1 w:1) + /// Proof: `TfgridModule::AllowedTwinAdmins` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn add_twin_admin() -> Weight { + // Proof Size summary in bytes: + // Measured: `134` + // Estimated: `1619` + // Minimum execution time: 24_015_000 picoseconds. + Weight::from_parts(27_477_000, 1619) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: `TfgridModule::AllowedTwinAdmins` (r:1 w:1) + /// Proof: `TfgridModule::AllowedTwinAdmins` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn remove_twin_admin() -> Weight { + // Proof Size summary in bytes: + // Measured: `189` + // Estimated: `1674` + // Minimum execution time: 18_618_000 picoseconds. + Weight::from_parts(28_136_000, 1674) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } } diff --git a/substrate-node/pallets/pallet-tft-bridge/src/weights.rs b/substrate-node/pallets/pallet-tft-bridge/src/weights.rs index 8225b3306..7888a45d1 100644 --- a/substrate-node/pallets/pallet-tft-bridge/src/weights.rs +++ b/substrate-node/pallets/pallet-tft-bridge/src/weights.rs @@ -2,9 +2,9 @@ //! Autogenerated weights for pallet_tft_bridge //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2025-09-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2026-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ebea9d7a9918`, CPU: `AMD Ryzen 7 5800X 8-Core Processor` +//! HOSTNAME: `19750001b071`, CPU: `DO-Regular` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -55,8 +55,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `256` // Estimated: `1741` - // Minimum execution time: 6_913_000 picoseconds. - Weight::from_parts(7_134_000, 1741) + // Minimum execution time: 12_995_000 picoseconds. + Weight::from_parts(13_449_000, 1741) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -66,8 +66,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `289` // Estimated: `1774` - // Minimum execution time: 6_813_000 picoseconds. - Weight::from_parts(7_003_000, 1774) + // Minimum execution time: 12_691_000 picoseconds. + Weight::from_parts(13_252_000, 1774) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -77,8 +77,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_254_000 picoseconds. - Weight::from_parts(2_385_000, 0) + // Minimum execution time: 7_516_000 picoseconds. + Weight::from_parts(8_563_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `TFTBridgeModule::WithdrawFee` (r:0 w:1) @@ -87,8 +87,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_184_000 picoseconds. - Weight::from_parts(2_275_000, 0) + // Minimum execution time: 4_364_000 picoseconds. + Weight::from_parts(4_978_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `TFTBridgeModule::DepositFee` (r:0 w:1) @@ -97,8 +97,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_164_000 picoseconds. - Weight::from_parts(2_244_000, 0) + // Minimum execution time: 4_378_000 picoseconds. + Weight::from_parts(4_693_000, 0) .saturating_add(T::DbWeight::get().writes(1_u64)) } /// Storage: `TFTBridgeModule::WithdrawFee` (r:1 w:0) @@ -115,8 +115,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `253` // Estimated: `3593` - // Minimum execution time: 42_621_000 picoseconds. - Weight::from_parts(43_412_000, 3593) + // Minimum execution time: 82_305_000 picoseconds. + Weight::from_parts(137_671_000, 3593) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -136,8 +136,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `499` // Estimated: `3964` - // Minimum execution time: 61_707_000 picoseconds. - Weight::from_parts(62_769_000, 3964) + // Minimum execution time: 113_489_000 picoseconds. + Weight::from_parts(198_034_000, 3964) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -151,8 +151,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `631` // Estimated: `4096` - // Minimum execution time: 24_806_000 picoseconds. - Weight::from_parts(25_419_000, 4096) + // Minimum execution time: 48_359_000 picoseconds. + Weight::from_parts(76_577_000, 4096) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -166,8 +166,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `571` // Estimated: `4036` - // Minimum execution time: 17_683_000 picoseconds. - Weight::from_parts(17_964_000, 4036) + // Minimum execution time: 34_698_000 picoseconds. + Weight::from_parts(50_986_000, 4036) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -179,8 +179,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3850` - // Minimum execution time: 20_929_000 picoseconds. - Weight::from_parts(21_421_000, 3850) + // Minimum execution time: 43_040_000 picoseconds. + Weight::from_parts(67_738_000, 3850) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -194,8 +194,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `560` // Estimated: `4025` - // Minimum execution time: 17_773_000 picoseconds. - Weight::from_parts(18_355_000, 4025) + // Minimum execution time: 34_994_000 picoseconds. + Weight::from_parts(55_424_000, 4025) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -209,8 +209,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `256` // Estimated: `1741` - // Minimum execution time: 6_913_000 picoseconds. - Weight::from_parts(7_134_000, 1741) + // Minimum execution time: 12_995_000 picoseconds. + Weight::from_parts(13_449_000, 1741) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -220,8 +220,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `289` // Estimated: `1774` - // Minimum execution time: 6_813_000 picoseconds. - Weight::from_parts(7_003_000, 1774) + // Minimum execution time: 12_691_000 picoseconds. + Weight::from_parts(13_252_000, 1774) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -231,8 +231,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_254_000 picoseconds. - Weight::from_parts(2_385_000, 0) + // Minimum execution time: 7_516_000 picoseconds. + Weight::from_parts(8_563_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `TFTBridgeModule::WithdrawFee` (r:0 w:1) @@ -241,8 +241,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_184_000 picoseconds. - Weight::from_parts(2_275_000, 0) + // Minimum execution time: 4_364_000 picoseconds. + Weight::from_parts(4_978_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `TFTBridgeModule::DepositFee` (r:0 w:1) @@ -251,8 +251,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `0` // Estimated: `0` - // Minimum execution time: 2_164_000 picoseconds. - Weight::from_parts(2_244_000, 0) + // Minimum execution time: 4_378_000 picoseconds. + Weight::from_parts(4_693_000, 0) .saturating_add(RocksDbWeight::get().writes(1_u64)) } /// Storage: `TFTBridgeModule::WithdrawFee` (r:1 w:0) @@ -269,8 +269,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `253` // Estimated: `3593` - // Minimum execution time: 42_621_000 picoseconds. - Weight::from_parts(43_412_000, 3593) + // Minimum execution time: 82_305_000 picoseconds. + Weight::from_parts(137_671_000, 3593) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -290,8 +290,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `499` // Estimated: `3964` - // Minimum execution time: 61_707_000 picoseconds. - Weight::from_parts(62_769_000, 3964) + // Minimum execution time: 113_489_000 picoseconds. + Weight::from_parts(198_034_000, 3964) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -305,8 +305,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `631` // Estimated: `4096` - // Minimum execution time: 24_806_000 picoseconds. - Weight::from_parts(25_419_000, 4096) + // Minimum execution time: 48_359_000 picoseconds. + Weight::from_parts(76_577_000, 4096) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -320,8 +320,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `571` // Estimated: `4036` - // Minimum execution time: 17_683_000 picoseconds. - Weight::from_parts(17_964_000, 4036) + // Minimum execution time: 34_698_000 picoseconds. + Weight::from_parts(50_986_000, 4036) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -333,8 +333,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `385` // Estimated: `3850` - // Minimum execution time: 20_929_000 picoseconds. - Weight::from_parts(21_421_000, 3850) + // Minimum execution time: 43_040_000 picoseconds. + Weight::from_parts(67_738_000, 3850) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -348,8 +348,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `560` // Estimated: `4025` - // Minimum execution time: 17_773_000 picoseconds. - Weight::from_parts(18_355_000, 4025) + // Minimum execution time: 34_994_000 picoseconds. + Weight::from_parts(55_424_000, 4025) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } diff --git a/substrate-node/pallets/pallet-tft-price/src/weights.rs b/substrate-node/pallets/pallet-tft-price/src/weights.rs index a62725ab6..811946a7c 100644 --- a/substrate-node/pallets/pallet-tft-price/src/weights.rs +++ b/substrate-node/pallets/pallet-tft-price/src/weights.rs @@ -2,9 +2,9 @@ //! Autogenerated weights for pallet_tft_price //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2025-09-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2026-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ebea9d7a9918`, CPU: `AMD Ryzen 7 5800X 8-Core Processor` +//! HOSTNAME: `19750001b071`, CPU: `DO-Regular` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -61,8 +61,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `235` // Estimated: `6175` - // Minimum execution time: 29_376_000 picoseconds. - Weight::from_parts(30_267_000, 6175) + // Minimum execution time: 83_061_000 picoseconds. + Weight::from_parts(117_132_000, 6175) .saturating_add(T::DbWeight::get().reads(6_u64)) .saturating_add(T::DbWeight::get().writes(5_u64)) } @@ -74,8 +74,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `93` // Estimated: `1578` - // Minimum execution time: 4_960_000 picoseconds. - Weight::from_parts(5_109_000, 1578) + // Minimum execution time: 12_908_000 picoseconds. + Weight::from_parts(15_567_000, 1578) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -87,8 +87,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `93` // Estimated: `1578` - // Minimum execution time: 4_929_000 picoseconds. - Weight::from_parts(5_090_000, 1578) + // Minimum execution time: 14_158_000 picoseconds. + Weight::from_parts(15_182_000, 1578) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -116,8 +116,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `235` // Estimated: `6175` - // Minimum execution time: 29_376_000 picoseconds. - Weight::from_parts(30_267_000, 6175) + // Minimum execution time: 83_061_000 picoseconds. + Weight::from_parts(117_132_000, 6175) .saturating_add(RocksDbWeight::get().reads(6_u64)) .saturating_add(RocksDbWeight::get().writes(5_u64)) } @@ -129,8 +129,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `93` // Estimated: `1578` - // Minimum execution time: 4_960_000 picoseconds. - Weight::from_parts(5_109_000, 1578) + // Minimum execution time: 12_908_000 picoseconds. + Weight::from_parts(15_567_000, 1578) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -142,8 +142,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `93` // Estimated: `1578` - // Minimum execution time: 4_929_000 picoseconds. - Weight::from_parts(5_090_000, 1578) + // Minimum execution time: 14_158_000 picoseconds. + Weight::from_parts(15_182_000, 1578) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate-node/pallets/pallet-validator/src/weights.rs b/substrate-node/pallets/pallet-validator/src/weights.rs index 8e0bacce9..acf9c16af 100644 --- a/substrate-node/pallets/pallet-validator/src/weights.rs +++ b/substrate-node/pallets/pallet-validator/src/weights.rs @@ -2,9 +2,9 @@ //! Autogenerated weights for pallet_validator //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2025-09-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2026-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ebea9d7a9918`, CPU: `AMD Ryzen 7 5800X 8-Core Processor` +//! HOSTNAME: `19750001b071`, CPU: `DO-Regular` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -50,8 +50,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `42` // Estimated: `3507` - // Minimum execution time: 9_378_000 picoseconds. - Weight::from_parts(9_668_000, 3507) + // Minimum execution time: 31_144_000 picoseconds. + Weight::from_parts(32_794_000, 3507) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -65,8 +65,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `365` // Estimated: `3830` - // Minimum execution time: 23_925_000 picoseconds. - Weight::from_parts(24_466_000, 3830) + // Minimum execution time: 50_987_000 picoseconds. + Weight::from_parts(78_213_000, 3830) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -80,8 +80,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `431` // Estimated: `3896` - // Minimum execution time: 32_140_000 picoseconds. - Weight::from_parts(33_153_000, 3896) + // Minimum execution time: 64_184_000 picoseconds. + Weight::from_parts(104_970_000, 3896) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(3_u64)) } @@ -91,8 +91,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `42` // Estimated: `3507` - // Minimum execution time: 8_345_000 picoseconds. - Weight::from_parts(8_717_000, 3507) + // Minimum execution time: 17_493_000 picoseconds. + Weight::from_parts(27_153_000, 3507) .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -110,8 +110,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `494` // Estimated: `4687` - // Minimum execution time: 24_096_000 picoseconds. - Weight::from_parts(24_967_000, 4687) + // Minimum execution time: 74_761_000 picoseconds. + Weight::from_parts(79_702_000, 4687) .saturating_add(T::DbWeight::get().reads(3_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -131,8 +131,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `558` // Estimated: `4687` - // Minimum execution time: 21_440_000 picoseconds. - Weight::from_parts(21_822_000, 4687) + // Minimum execution time: 65_334_000 picoseconds. + Weight::from_parts(69_925_000, 4687) .saturating_add(T::DbWeight::get().reads(4_u64)) .saturating_add(T::DbWeight::get().writes(4_u64)) } @@ -146,8 +146,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `42` // Estimated: `3507` - // Minimum execution time: 9_378_000 picoseconds. - Weight::from_parts(9_668_000, 3507) + // Minimum execution time: 31_144_000 picoseconds. + Weight::from_parts(32_794_000, 3507) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -161,8 +161,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `365` // Estimated: `3830` - // Minimum execution time: 23_925_000 picoseconds. - Weight::from_parts(24_466_000, 3830) + // Minimum execution time: 50_987_000 picoseconds. + Weight::from_parts(78_213_000, 3830) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -176,8 +176,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `431` // Estimated: `3896` - // Minimum execution time: 32_140_000 picoseconds. - Weight::from_parts(33_153_000, 3896) + // Minimum execution time: 64_184_000 picoseconds. + Weight::from_parts(104_970_000, 3896) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(3_u64)) } @@ -187,8 +187,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `42` // Estimated: `3507` - // Minimum execution time: 8_345_000 picoseconds. - Weight::from_parts(8_717_000, 3507) + // Minimum execution time: 17_493_000 picoseconds. + Weight::from_parts(27_153_000, 3507) .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -206,8 +206,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `494` // Estimated: `4687` - // Minimum execution time: 24_096_000 picoseconds. - Weight::from_parts(24_967_000, 4687) + // Minimum execution time: 74_761_000 picoseconds. + Weight::from_parts(79_702_000, 4687) .saturating_add(RocksDbWeight::get().reads(3_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } @@ -227,8 +227,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `558` // Estimated: `4687` - // Minimum execution time: 21_440_000 picoseconds. - Weight::from_parts(21_822_000, 4687) + // Minimum execution time: 65_334_000 picoseconds. + Weight::from_parts(69_925_000, 4687) .saturating_add(RocksDbWeight::get().reads(4_u64)) .saturating_add(RocksDbWeight::get().writes(4_u64)) } diff --git a/substrate-node/pallets/substrate-validator-set/src/weights.rs b/substrate-node/pallets/substrate-validator-set/src/weights.rs index f65ce65a1..3607020a1 100644 --- a/substrate-node/pallets/substrate-validator-set/src/weights.rs +++ b/substrate-node/pallets/substrate-validator-set/src/weights.rs @@ -2,9 +2,9 @@ //! Autogenerated weights for substrate_validator_set //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2025-09-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2026-02-19, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` //! WORST CASE MAP SIZE: `1000000` -//! HOSTNAME: `ebea9d7a9918`, CPU: `AMD Ryzen 7 5800X 8-Core Processor` +//! HOSTNAME: `19750001b071`, CPU: `DO-Regular` //! EXECUTION: , WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: @@ -49,8 +49,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `139` // Estimated: `1624` - // Minimum execution time: 13_355_000 picoseconds. - Weight::from_parts(13_676_000, 1624) + // Minimum execution time: 39_555_000 picoseconds. + Weight::from_parts(45_269_000, 1624) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(2_u64)) } @@ -62,8 +62,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `205` // Estimated: `1690` - // Minimum execution time: 10_951_000 picoseconds. - Weight::from_parts(11_181_000, 1690) + // Minimum execution time: 29_890_000 picoseconds. + Weight::from_parts(36_141_000, 1690) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -75,8 +75,8 @@ impl WeightInfo for SubstrateWeight { // Proof Size summary in bytes: // Measured: `172` // Estimated: `1657` - // Minimum execution time: 12_073_000 picoseconds. - Weight::from_parts(12_424_000, 1657) + // Minimum execution time: 32_245_000 picoseconds. + Weight::from_parts(37_468_000, 1657) .saturating_add(T::DbWeight::get().reads(2_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } @@ -92,8 +92,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `139` // Estimated: `1624` - // Minimum execution time: 13_355_000 picoseconds. - Weight::from_parts(13_676_000, 1624) + // Minimum execution time: 39_555_000 picoseconds. + Weight::from_parts(45_269_000, 1624) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(2_u64)) } @@ -105,8 +105,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `205` // Estimated: `1690` - // Minimum execution time: 10_951_000 picoseconds. - Weight::from_parts(11_181_000, 1690) + // Minimum execution time: 29_890_000 picoseconds. + Weight::from_parts(36_141_000, 1690) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } @@ -118,8 +118,8 @@ impl WeightInfo for () { // Proof Size summary in bytes: // Measured: `172` // Estimated: `1657` - // Minimum execution time: 12_073_000 picoseconds. - Weight::from_parts(12_424_000, 1657) + // Minimum execution time: 32_245_000 picoseconds. + Weight::from_parts(37_468_000, 1657) .saturating_add(RocksDbWeight::get().reads(2_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } diff --git a/substrate-node/runtime/src/lib.rs b/substrate-node/runtime/src/lib.rs index f353df18a..b243719b3 100644 --- a/substrate-node/runtime/src/lib.rs +++ b/substrate-node/runtime/src/lib.rs @@ -154,7 +154,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("substrate-threefold"), impl_name: create_runtime_str!("substrate-threefold"), authoring_version: 1, - spec_version: 155, + spec_version: 156, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 2, @@ -359,6 +359,7 @@ parameter_types! { pub const MaxInterfaceIpsLength: u32 = 10; pub const MaxInterfacesLength: u32 = 10; pub const MaxFarmPublicIps: u32 = 512; + pub const MaxTwinAdmins: u32 = 100; pub const TimestampHintDrift: u64 = 60; } @@ -372,6 +373,7 @@ impl pallet_tfgrid::Config for Runtime { type TermsAndConditions = pallet_tfgrid::terms_cond::TermsAndConditions; type MaxFarmNameLength = MaxFarmNameLength; type MaxFarmPublicIps = MaxFarmPublicIps; + type MaxTwinAdmins = MaxTwinAdmins; type FarmName = pallet_tfgrid::farm::FarmName; type MaxInterfacesLength = MaxInterfacesLength; type InterfaceName = pallet_tfgrid::interface::InterfaceName; diff --git a/tools/fork-off-substrate/package.json b/tools/fork-off-substrate/package.json index c4b773c77..9879fca2c 100644 --- a/tools/fork-off-substrate/package.json +++ b/tools/fork-off-substrate/package.json @@ -1,6 +1,6 @@ { "name": "fork-off-substrate", - "version": "2.10.1", + "version": "2.11.0", "description": "This script allows bootstrapping a new substrate chain with the current state of a live chain", "main": "index.js", "scripts": {