From c13274c3811da39d38fbad9cf838aeb206d1ae67 Mon Sep 17 00:00:00 2001 From: despiegk Date: Wed, 17 Sep 2025 14:56:55 +0200 Subject: [PATCH] ... --- lib/threefold/models_ledger/accountpolicy.v | 160 +++++++ lib/threefold/models_ledger/member.v | 159 +++++++ lib/threefold/models_ledger/notary.v | 134 ++++++ lib/threefold/models_ledger/signature.v | 133 ++++++ lib/threefold/models_ledger/userkvs.v | 119 ++++++ lib/threefold/models_ledger/userkvsitem.v | 133 ++++++ lib/threefold/models_tfgrid/bid.v | 176 ++++++++ lib/threefold/models_tfgrid/contract.v | 248 +++++++++++ lib/threefold/models_tfgrid/mod.v | 8 + lib/threefold/models_tfgrid/node.v | 445 ++++++++++++++++++++ lib/threefold/models_tfgrid/nodegroup.v | 159 +++++++ lib/threefold/models_tfgrid/reputation.v | 157 +++++++ 12 files changed, 2031 insertions(+) create mode 100644 lib/threefold/models_ledger/accountpolicy.v create mode 100644 lib/threefold/models_ledger/member.v create mode 100644 lib/threefold/models_ledger/notary.v create mode 100644 lib/threefold/models_ledger/signature.v create mode 100644 lib/threefold/models_ledger/userkvs.v create mode 100644 lib/threefold/models_ledger/userkvsitem.v create mode 100644 lib/threefold/models_tfgrid/bid.v create mode 100644 lib/threefold/models_tfgrid/contract.v create mode 100644 lib/threefold/models_tfgrid/mod.v create mode 100644 lib/threefold/models_tfgrid/node.v create mode 100644 lib/threefold/models_tfgrid/nodegroup.v create mode 100644 lib/threefold/models_tfgrid/reputation.v diff --git a/lib/threefold/models_ledger/accountpolicy.v b/lib/threefold/models_ledger/accountpolicy.v new file mode 100644 index 00000000..844f4bdd --- /dev/null +++ b/lib/threefold/models_ledger/accountpolicy.v @@ -0,0 +1,160 @@ +module models_ledger + +import freeflowuniverse.herolib.data.encoder +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db + +// AccountPolicy represents a set of rules for an account +@[heap] +pub struct AccountPolicy { + db.Base +pub mut: + policy_id u32 @[index] + min_signatures u32 + max_tx_amount f64 + daily_limit f64 + whitelist []u32 + blacklist []u32 + require_2fa bool + lockout_period u64 + is_multisig bool +} + +pub struct DBAccountPolicy { +pub mut: + db &db.DB @[skip; str: skip] +} + + +pub fn (self AccountPolicy) type_name() string { + return 'accountpolicy' +} + +pub fn (self AccountPolicy) description(methodname string) string { + match methodname { + 'set' { + return 'Create or update an account policy. Returns the ID of the policy.' + } + 'get' { + return 'Retrieve an account policy by ID. Returns the policy object.' + } + 'delete' { + return 'Delete an account policy by ID. Returns true if successful.' + } + 'exist' { + return 'Check if an account policy exists by ID. Returns true or false.' + } + 'list' { + return 'List all account policies. Returns an array of policy objects.' + } + else { + return 'Account policy management operations' + } + } +} + +pub fn (self AccountPolicy) example(methodname string) (string, string) { + match methodname { + 'set' { + return '{"accountpolicy": {"policy_id": 1, "min_signatures": 2, "max_tx_amount": 10000.0, "daily_limit": 50000.0, "is_multisig": true}}', '1' + } + 'get' { + return '{"id": 1}', '{"policy_id": 1, "min_signatures": 2, "is_multisig": true}' + } + 'delete' { + return '{"id": 1}', 'true' + } + 'exist' { + return '{"id": 1}', 'true' + } + 'list' { + return '{}', '[{"policy_id": 1, "min_signatures": 2, "is_multisig": true}]' + } + else { + return '{}', '{}' + } + } +} + +pub fn (self AccountPolicy) dump(mut e encoder.Encoder) ! { + e.add_u32(self.policy_id) + e.add_u32(self.min_signatures) + e.add_f64(self.max_tx_amount) + e.add_f64(self.daily_limit) + e.add_list_u32(self.whitelist) + e.add_list_u32(self.blacklist) + e.add_bool(self.require_2fa) + e.add_u64(self.lockout_period) + e.add_bool(self.is_multisig) +} + +fn (mut self DBAccountPolicy) load(mut o AccountPolicy, mut e encoder.Decoder) ! { + o.policy_id = e.get_u32()! + o.min_signatures = e.get_u32()! + o.max_tx_amount = e.get_f64()! + o.daily_limit = e.get_f64()! + o.whitelist = e.get_list_u32()! + o.blacklist = e.get_list_u32()! + o.require_2fa = e.get_bool()! + o.lockout_period = e.get_u64()! + o.is_multisig = e.get_bool()! +} + +@[params] +pub struct AccountPolicyArg { +pub mut: + name string + description string + policy_id u32 + min_signatures u32 + max_tx_amount f64 + daily_limit f64 + whitelist []u32 + blacklist []u32 + require_2fa bool + lockout_period u64 + is_multisig bool +} + +pub fn (mut self DBAccountPolicy) new(args AccountPolicyArg) !AccountPolicy { + mut o := AccountPolicy{ + policy_id: args.policy_id + min_signatures: args.min_signatures + max_tx_amount: args.max_tx_amount + daily_limit: args.daily_limit + whitelist: args.whitelist + blacklist: args.blacklist + require_2fa: args.require_2fa + lockout_period: args.lockout_period + is_multisig: args.is_multisig + } + + o.name = args.name + o.description = args.description + o.updated_at = ourtime.now().unix() + + return o +} + +pub fn (mut self DBAccountPolicy) set(o AccountPolicy) !AccountPolicy { + return self.db.set[AccountPolicy](o)! +}_ + +pub fn (mut self DBAccountPolicy) delete(id u32) ! { + self.db.delete[AccountPolicy](id)! +} + +pub fn (mut self DBAccountPolicy) exist(id u32) !bool { + return self.db.exists[AccountPolicy](id)! +} + +pub fn (mut self DBAccountPolicy) get(id u32) !AccountPolicy { + mut o, data := self.db.get_data[AccountPolicy](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBAccountPolicy) list() ![]AccountPolicy { + return self.db.list[AccountPolicy]()!.map(self.get(it)!) +} \ No newline at end of file diff --git a/lib/threefold/models_ledger/member.v b/lib/threefold/models_ledger/member.v new file mode 100644 index 00000000..a012a6f4 --- /dev/null +++ b/lib/threefold/models_ledger/member.v @@ -0,0 +1,159 @@ +module models_ledger + +import freeflowuniverse.herolib.data.encoder +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db + +// MemberRole defines the role of a user within a group +pub enum MemberRole { + member + moderator + admin + owner +} + +// MemberStatus defines the status of a membership +pub enum MemberStatus { + pending + active + suspended + archived +} + +// Member represents the association of a user to a group +@[heap] +pub struct Member { + db.Base +pub mut: + group_id u32 @[index] + user_id u32 @[index] + role MemberRole + status MemberStatus + join_date u64 + last_activity u64 +} + +pub struct DBMember { +pub mut: + db &db.DB @[skip; str: skip] +} + +pub fn (self Member) type_name() string { + return 'member' +} + +pub fn (self Member) description(methodname string) string { + match methodname { + 'set' { + return 'Create or update a group member. Returns the ID of the member.' + } + 'get' { + return 'Retrieve a member by ID. Returns the member object.' + } + 'delete' { + return 'Delete a member by ID. Returns true if successful.' + } + 'exist' { + return 'Check if a member exists by ID. Returns true or false.' + } + 'list' { + return 'List all members. Returns an array of member objects.' + } + else { + return 'Member management operations' + } + } +} + +pub fn (self Member) example(methodname string) (string, string) { + match methodname { + 'set' { + return '{"member": {"group_id": 1, "user_id": 1, "role": "admin", "status": "active"}}', '1' + } + 'get' { + return '{"id": 1}', '{"group_id": 1, "user_id": 1, "role": "admin", "status": "active"}' + } + 'delete' { + return '{"id": 1}', 'true' + } + 'exist' { + return '{"id": 1}', 'true' + } + 'list' { + return '{}', '[{"group_id": 1, "user_id": 1, "role": "admin", "status": "active"}]' + } + else { + return '{}', '{}' + } + } +} + +pub fn (self Member) dump(mut e encoder.Encoder) ! { + e.add_u32(self.group_id) + e.add_u32(self.user_id) + e.add_u8(u8(self.role)) + e.add_u8(u8(self.status)) + e.add_u64(self.join_date) + e.add_u64(self.last_activity) +} + +fn (mut self DBMember) load(mut o Member, mut e encoder.Decoder) ! { + o.group_id = e.get_u32()! + o.user_id = e.get_u32()! + o.role = MemberRole(e.get_u8()!) + o.status = MemberStatus(e.get_u8()!) + o.join_date = e.get_u64()! + o.last_activity = e.get_u64()! +} + +@[params] +pub struct MemberArg { +pub mut: + name string + description string + group_id u32 + user_id u32 + role MemberRole = .member + status MemberStatus = .pending +} + +pub fn (mut self DBMember) new(args MemberArg) !Member { + now := ourtime.now().unix() + mut o := Member{ + group_id: args.group_id + user_id: args.user_id + role: args.role + status: args.status + join_date: now + last_activity: now + } + + o.name = args.name + o.description = args.description + o.updated_at = now + + return o +} + +pub fn (mut self DBMember) set(o Member) !Member { + return self.db.set[Member](o)! +} + +pub fn (mut self DBMember) delete(id u32) ! { + self.db.delete[Member](id)! +} + +pub fn (mut self DBMember) exist(id u32) !bool { + return self.db.exists[Member](id)! +} + +pub fn (mut self DBMember) get(id u32) !Member { + mut o, data := self.db.get_data[Member](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBMember) list() ![]Member { + return self.db.list[Member]()!.map(self.get(it)!) +} \ No newline at end of file diff --git a/lib/threefold/models_ledger/notary.v b/lib/threefold/models_ledger/notary.v new file mode 100644 index 00000000..9a42e2e1 --- /dev/null +++ b/lib/threefold/models_ledger/notary.v @@ -0,0 +1,134 @@ +module models_ledger + +import freeflowuniverse.herolib.data.encoder +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db + +// Notary represents a cryptographic notary in the system +@[heap] +pub struct Notary { + db.Base +pub mut: + notary_id u32 @[index] + pubkey string + address string + is_active bool +} + +pub struct DBNotary { +pub mut: + db &db.DB @[skip; str: skip] +} + +pub fn (self Notary) type_name() string { + return 'notary' +} + +pub fn (self Notary) description(methodname string) string { + match methodname { + 'set' { + return 'Create or update a notary. Returns the ID of the notary.' + } + 'get' { + return 'Retrieve a notary by ID. Returns the notary object.' + } + 'delete' { + return 'Delete a notary by ID. Returns true if successful.' + } + 'exist' { + return 'Check if a notary exists by ID. Returns true or false.' + } + 'list' { + return 'List all notaries. Returns an array of notary objects.' + } + else { + return 'Notary management operations' + } + } +} + +pub fn (self Notary) example(methodname string) (string, string) { + match methodname { + 'set' { + return '{"notary": {"notary_id": 1, "pubkey": "ed25519_pubkey", "address": "TFT_ADDRESS_XYZ", "is_active": true}}', '1' + } + 'get' { + return '{"id": 1}', '{"notary_id": 1, "pubkey": "ed25519_pubkey", "address": "TFT_ADDRESS_XYZ", "is_active": true}' + } + 'delete' { + return '{"id": 1}', 'true' + } + 'exist' { + return '{"id": 1}', 'true' + } + 'list' { + return '{}', '[{"notary_id": 1, "pubkey": "ed25519_pubkey", "address": "TFT_ADDRESS_XYZ", "is_active": true}]' + } + else { + return '{}', '{}' + } + } +} + +pub fn (self Notary) dump(mut e encoder.Encoder) ! { + e.add_u32(self.notary_id) + e.add_string(self.pubkey) + e.add_string(self.address) + e.add_bool(self.is_active) +} + +fn (mut self DBNotary) load(mut o Notary, mut e encoder.Decoder) ! { + o.notary_id = e.get_u32()! + o.pubkey = e.get_string()! + o.address = e.get_string()! + o.is_active = e.get_bool()! +} + +@[params] +pub struct NotaryArg { +pub mut: + name string + description string + notary_id u32 + pubkey string + address string + is_active bool = true +} + +pub fn (mut self DBNotary) new(args NotaryArg) !Notary { + mut o := Notary{ + notary_id: args.notary_id + pubkey: args.pubkey + address: args.address + is_active: args.is_active + } + + o.name = args.name + o.description = args.description + o.updated_at = ourtime.now().unix() + + return o +} + +pub fn (mut self DBNotary) set(o Notary) !Notary { + return self.db.set[Notary](o)! +} + +pub fn (mut self DBNotary) delete(id u32) ! { + self.db.delete[Notary](id)! +} + +pub fn (mut self DBNotary) exist(id u32) !bool { + return self.db.exists[Notary](id)! +} + +pub fn (mut self DBNotary) get(id u32) !Notary { + mut o, data := self.db.get_data[Notary](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBNotary) list() ![]Notary { + return self.db.list[Notary]()!.map(self.get(it)!) +} \ No newline at end of file diff --git a/lib/threefold/models_ledger/signature.v b/lib/threefold/models_ledger/signature.v new file mode 100644 index 00000000..7a29eb55 --- /dev/null +++ b/lib/threefold/models_ledger/signature.v @@ -0,0 +1,133 @@ +module models_ledger + +import freeflowuniverse.herolib.data.encoder +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db + +// Signature represents a digital signature in the system +@[heap] +pub struct Signature { + db.Base +pub mut: + signer_id u32 @[index] + tx_id u32 @[index] + signature string + timestamp u64 +} + +pub struct DBSignature { +pub mut: + db &db.DB @[skip; str: skip] +} + +pub fn (self Signature) type_name() string { + return 'signature' +} + +pub fn (self Signature) description(methodname string) string { + match methodname { + 'set' { + return 'Create or update a signature. Returns the ID of the signature.' + } + 'get' { + return 'Retrieve a signature by ID. Returns the signature object.' + } + 'delete' { + return 'Delete a signature by ID. Returns true if successful.' + } + 'exist' { + return 'Check if a signature exists by ID. Returns true or false.' + } + 'list' { + return 'List all signatures. Returns an array of signature objects.' + } + else { + return 'Signature management operations' + } + } +} + +pub fn (self Signature) example(methodname string) (string, string) { + match methodname { + 'set' { + return '{"signature": {"signer_id": 1, "tx_id": 123, "signature": "hex_encoded_signature"}}', '1' + } + 'get' { + return '{"id": 1}', '{"signer_id": 1, "tx_id": 123, "signature": "hex_encoded_signature"}' + } + 'delete' { + return '{"id": 1}', 'true' + } + 'exist' { + return '{"id": 1}', 'true' + } + 'list' { + return '{}', '[{"signer_id": 1, "tx_id": 123, "signature": "hex_encoded_signature"}]' + } + else { + return '{}', '{}' + } + } +} + +pub fn (self Signature) dump(mut e encoder.Encoder) ! { + e.add_u32(self.signer_id) + e.add_u32(self.tx_id) + e.add_string(self.signature) + e.add_u64(self.timestamp) +} + +fn (mut self DBSignature) load(mut o Signature, mut e encoder.Decoder) ! { + o.signer_id = e.get_u32()! + o.tx_id = e.get_u32()! + o.signature = e.get_string()! + o.timestamp = e.get_u64()! +} + +@[params] +pub struct SignatureArg { +pub mut: + name string + description string + signer_id u32 + tx_id u32 + signature string +} + +pub fn (mut self DBSignature) new(args SignatureArg) !Signature { + mut o := Signature{ + signer_id: args.signer_id + tx_id: args.tx_id + signature: args.signature + timestamp: ourtime.now().unix() + } + + o.name = args.name + o.description = args.description + o.updated_at = ourtime.now().unix() + + return o +} + +pub fn (mut self DBSignature) set(o Signature) !Signature { + return self.db.set[Signature](o)! +} + +pub fn (mut self DBSignature) delete(id u32) ! { + self.db.delete[Signature](id)! +} + +pub fn (mut self DBSignature) exist(id u32) !bool { + return self.db.exists[Signature](id)! +} + +pub fn (mut self DBSignature) get(id u32) !Signature { + mut o, data := self.db.get_data[Signature](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBSignature) list() ![]Signature { + return self.db.list[Signature]()!.map(self.get(it)!) +} \ No newline at end of file diff --git a/lib/threefold/models_ledger/userkvs.v b/lib/threefold/models_ledger/userkvs.v new file mode 100644 index 00000000..f43cc1e5 --- /dev/null +++ b/lib/threefold/models_ledger/userkvs.v @@ -0,0 +1,119 @@ +module models_ledger + +import freeflowuniverse.herolib.data.encoder +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db + +// UserKVS represents a key-value store for a user +@[heap] +pub struct UserKVS { + db.Base +pub mut: + user_id u32 @[index] +} + +pub struct DBUserKVS { +pub mut: + db &db.DB @[skip; str: skip] +} + +pub fn (self UserKVS) type_name() string { + return 'userkvs' +} + +pub fn (self UserKVS) description(methodname string) string { + match methodname { + 'set' { + return 'Create or update a user KVS. Returns the ID of the KVS.' + } + 'get' { + return 'Retrieve a user KVS by ID. Returns the KVS object.' + } + 'delete' { + return 'Delete a user KVS by ID. Returns true if successful.' + } + 'exist' { + return 'Check if a user KVS exists by ID. Returns true or false.' + } + 'list' { + return 'List all user KVS. Returns an array of KVS objects.' + } + else { + return 'User KVS management operations' + } + } +} + +pub fn (self UserKVS) example(methodname string) (string, string) { + match methodname { + 'set' { + return '{"userkvs": {"user_id": 1}}', '1' + } + 'get' { + return '{"id": 1}', '{"user_id": 1}' + } + 'delete' { + return '{"id": 1}', 'true' + } + 'exist' { + return '{"id": 1}', 'true' + } + 'list' { + return '{}', '[{"user_id": 1}]' + } + else { + return '{}', '{}' + } + } +} + +pub fn (self UserKVS) dump(mut e encoder.Encoder) ! { + e.add_u32(self.user_id) +} + +fn (mut self DBUserKVS) load(mut o UserKVS, mut e encoder.Decoder) ! { + o.user_id = e.get_u32()! +} + +@[params] +pub struct UserKVSArg { +pub mut: + name string + description string + user_id u32 +} + +pub fn (mut self DBUserKVS) new(args UserKVSArg) !UserKVS { + mut o := UserKVS{ + user_id: args.user_id + } + + o.name = args.name + o.description = args.description + o.updated_at = ourtime.now().unix() + + return o +} + +pub fn (mut self DBUserKVS) set(o UserKVS) !UserKVS { + return self.db.set[UserKVS](o)! +} + +pub fn (mut self DBUserKVS) delete(id u32) ! { + self.db.delete[UserKVS](id)! +} + +pub fn (mut self DBUserKVS) exist(id u32) !bool { + return self.db.exists[UserKVS](id)! +} + +pub fn (mut self DBUserKVS) get(id u32) !UserKVS { + mut o, data := self.db.get_data[UserKVS](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBUserKVS) list() ![]UserKVS { + return self.db.list[UserKVS]()!.map(self.get(it)!) +} \ No newline at end of file diff --git a/lib/threefold/models_ledger/userkvsitem.v b/lib/threefold/models_ledger/userkvsitem.v new file mode 100644 index 00000000..65922831 --- /dev/null +++ b/lib/threefold/models_ledger/userkvsitem.v @@ -0,0 +1,133 @@ +module models_ledger + +import freeflowuniverse.herolib.data.encoder +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db + +// UserKVSItem represents a single item in a user's key-value store +@[heap] +pub struct UserKVSItem { + db.Base +pub mut: + kvs_id u32 @[index] + key string @[index] + value string + timestamp u64 +} + +pub struct DBUserKVSItem { +pub mut: + db &db.DB @[skip; str: skip] +} + +pub fn (self UserKVSItem) type_name() string { + return 'userkvsitem' +} + +pub fn (self UserKVSItem) description(methodname string) string { + match methodname { + 'set' { + return 'Create or update a KVS item. Returns the ID of the item.' + } + 'get' { + return 'Retrieve a KVS item by ID. Returns the item object.' + } + 'delete' { + return 'Delete a KVS item by ID. Returns true if successful.' + } + 'exist' { + return 'Check if a KVS item exists by ID. Returns true or false.' + } + 'list' { + return 'List all KVS items. Returns an array of item objects.' + } + else { + return 'User KVS item management operations' + } + } +} + +pub fn (self UserKVSItem) example(methodname string) (string, string) { + match methodname { + 'set' { + return '{"userkvsitem": {"kvs_id": 1, "key": "mykey", "value": "myvalue"}}', '1' + } + 'get' { + return '{"id": 1}', '{"kvs_id": 1, "key": "mykey", "value": "myvalue"}' + } + 'delete' { + return '{"id": 1}', 'true' + } + 'exist' { + return '{"id": 1}', 'true' + } + 'list' { + return '{}', '[{"kvs_id": 1, "key": "mykey", "value": "myvalue"}]' + } + else { + return '{}', '{}' + } + } +} + +pub fn (self UserKVSItem) dump(mut e encoder.Encoder) ! { + e.add_u32(self.kvs_id) + e.add_string(self.key) + e.add_string(self.value) + e.add_u64(self.timestamp) +} + +fn (mut self DBUserKVSItem) load(mut o UserKVSItem, mut e encoder.Decoder) ! { + o.kvs_id = e.get_u32()! + o.key = e.get_string()! + o.value = e.get_string()! + o.timestamp = e.get_u64()! +} + +@[params] +pub struct UserKVSItemArg { +pub mut: + name string + description string + kvs_id u32 + key string + value string +} + +pub fn (mut self DBUserKVSItem) new(args UserKVSItemArg) !UserKVSItem { + mut o := UserKVSItem{ + kvs_id: args.kvs_id + key: args.key + value: args.value + timestamp: ourtime.now().unix() + } + + o.name = args.name + o.description = args.description + o.updated_at = ourtime.now().unix() + + return o +} + +pub fn (mut self DBUserKVSItem) set(o UserKVSItem) !UserKVSItem { + return self.db.set[UserKVSItem](o)! +} + +pub fn (mut self DBUserKVSItem) delete(id u32) ! { + self.db.delete[UserKVSItem](id)! +} + +pub fn (mut self DBUserKVSItem) exist(id u32) !bool { + return self.db.exists[UserKVSItem](id)! +} + +pub fn (mut self DBUserKVSItem) get(id u32) !UserKVSItem { + mut o, data := self.db.get_data[UserKVSItem](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBUserKVSItem) list() ![]UserKVSItem { + return self.db.list[UserKVSItem]()!.map(self.get(it)!) +} \ No newline at end of file diff --git a/lib/threefold/models_tfgrid/bid.v b/lib/threefold/models_tfgrid/bid.v new file mode 100644 index 00000000..b33a19ee --- /dev/null +++ b/lib/threefold/models_tfgrid/bid.v @@ -0,0 +1,176 @@ +module models_tfgrid + +import freeflowuniverse.herolib.data.encoder +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db +import freeflowuniverse.herolib.data.json + +// Bid - ROOT OBJECT +@[heap] +pub struct Bid { + db.Base +pub mut: + customer_id u32 // links back to customer for this capacity (user on ledger) + requirements map[string]string // e.g. compute_nodes:10, certified:true + pricing map[string]string // e.g. compute_nodes:10.2 (price per unit), certified_CU: 100.3 (price per CU) + status BidStatus + obligation bool // if obligation then will be charged and money needs to be in escrow + start_date u32 // epoch + end_date u32 + signature_user string // signature as done by a user/consumer to validate their identity and intent + billing_period BillingPeriod +} + +pub enum BidStatus { + pending + confirmed + assigned + cancelled + done +} + +pub enum BillingPeriod { + hourly + monthly + yearly + biannually + triannually +} + +pub struct DBBid { +pub mut: + db &db.DB @[skip; str: skip] +} + +pub fn (self Bid) type_name() string { + return 'bid' +} + +pub fn (self Bid) description(methodname string) string { + match methodname { + 'set' { + return 'Create or update a bid. Returns the ID of the bid.' + } + 'get' { + return 'Retrieve a bid by ID. Returns the bid object.' + } + 'delete' { + return 'Delete a bid by ID. Returns true if successful.' + } + 'exist' { + return 'Check if a bid exists by ID. Returns true or false.' + } + 'list' { + return 'List all bids. Returns an array of bid objects.' + } + else { + return 'Bid management methods for Grid4 infrastructure.' + } + } +} + +pub fn (self Bid) example(methodname string) (string, string) { + match methodname { + 'set' { + return '{"bid": {"name": "compute-bid-1", "customer_id": 456, "requirements": {"compute_slices":10}, "pricing": {"compute_slices":10.2}, "status": "pending", "obligation": true}}', '1' + } + 'get' { + return '{"id": 1}', '{"name": "compute-bid-1", "customer_id": 456, "requirements": {"compute_slices":10}, "status": "pending"}' + } + 'delete' { + return '{"id": 1}', 'true' + } + 'exist' { + return '{"id": 1}', 'true' + } + 'list' { + return '{}', '[{"name": "compute-bid-1", "customer_id": 456, "status": "pending"}]' + } + else { + return '{}', '{}' + } + } +} + +pub fn (self Bid) dump(mut e encoder.Encoder) ! { + e.add_u32(self.customer_id) + e.add_string(json.encode(self.requirements)) + e.add_string(json.encode(self.pricing)) + e.add_int(int(self.status)) + e.add_bool(self.obligation) + e.add_u32(self.start_date) + e.add_u32(self.end_date) + e.add_string(self.signature_user) + e.add_int(int(self.billing_period)) +} + +fn (mut self DBBid) load(mut o Bid, mut e encoder.Decoder) ! { + o.customer_id = e.get_u32()! + o.requirements = json.decode[map[string]string](e.get_string()!)! + o.pricing = json.decode[map[string]string](e.get_string()!)! + o.status = unsafe { BidStatus(e.get_int()!) } + o.obligation = e.get_bool()! + o.start_date = e.get_u32()! + o.end_date = e.get_u32()! + o.signature_user = e.get_string()! + o.billing_period = unsafe { BillingPeriod(e.get_int()!) } +} + +@[params] +pub struct BidArg { +pub mut: + name string + description string + customer_id u32 + requirements map[string]string + pricing map[string]string + status BidStatus + obligation bool + start_date u32 + end_date u32 + signature_user string + billing_period BillingPeriod +} + +pub fn (mut self DBBid) new(args BidArg) !Bid { + mut o := Bid{ + customer_id: args.customer_id + requirements: args.requirements + pricing: args.pricing + status: args.status + obligation: args.obligation + start_date: args.start_date + end_date: args.end_date + signature_user: args.signature_user + billing_period: args.billing_period + } + + o.name = args.name + o.description = args.description + o.updated_at = ourtime.now().unix() + + return o +} + +pub fn (mut self DBBid) set(o Bid) !Bid { + return self.db.set[Bid](o)! +} + +pub fn (mut self DBBid) delete(id u32) ! { + self.db.delete[Bid](id)! +} + +pub fn (mut self DBBid) exist(id u32) !bool { + return self.db.exists[Bid](id)! +} + +pub fn (mut self DBBid) get(id u32) !Bid { + mut o, data := self.db.get_data[Bid](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBBid) list() ![]Bid { + return self.db.list[Bid]()!.map(self.get(it)!) +} \ No newline at end of file diff --git a/lib/threefold/models_tfgrid/contract.v b/lib/threefold/models_tfgrid/contract.v new file mode 100644 index 00000000..3a3bbe7f --- /dev/null +++ b/lib/threefold/models_tfgrid/contract.v @@ -0,0 +1,248 @@ +module models_tfgrid + +import freeflowuniverse.herolib.data.encoder +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db + +// Contract - ROOT OBJECT +@[heap] +pub struct Contract { + db.Base +pub mut: + customer_id u32 // links back to customer for this capacity + compute_slices []ComputeSliceProvisioned + storage_slices []StorageSliceProvisioned + compute_slice_price f64 // price per 1 GB agreed upon + storage_slice_price f64 // price per 1 GB agreed upon + network_slice_price f64 // price per 1 GB agreed upon (transfer) + status ContractStatus + start_date u32 // epoch + end_date u32 + signature_user string // signature as done by user/consumer + signature_hoster string // signature as done by the hoster + billing_period BillingPeriod +} + +pub enum ContractStatus { + active + cancelled + error + paused +} + +// Provisioned compute slice +pub struct ComputeSliceProvisioned { +pub mut: + node_id u32 + id u16 // the id of the slice in the node + mem_gb f64 + storage_gb f64 + passmark int + vcores int + cpu_oversubscription int + tags string +} + +// Provisioned storage slice +pub struct StorageSliceProvisioned { +pub mut: + node_id u32 + id u16 // the id of the slice in the node + storage_size_gb int + tags string +} + + +pub struct DBContract { +pub mut: + db &db.DB @[skip; str: skip] +} + +pub fn (self Contract) type_name() string { + return 'contract' +} + +pub fn (self Contract) description(methodname string) string { + match methodname { + 'set' { + return 'Create or update a contract. Returns the ID of the contract.' + } + 'get' { + return 'Retrieve a contract by ID. Returns the contract object.' + } + 'delete' { + return 'Delete a contract by ID. Returns true if successful.' + } + 'exist' { + return 'Check if a contract exists by ID. Returns true or false.' + } + 'list' { + return 'List all contracts. Returns an array of contract objects.' + } + else { + return 'Contract management methods for Grid4 infrastructure.' + } + } +} + +pub fn (self Contract) example(methodname string) (string, string) { + match methodname { + 'set' { + return '{"contract": {"name": "contract-001", "customer_id": 456, "compute_slice_price": 0.05, "storage_slice_price": 0.01, "status": "active"}}', '1' + } + 'get' { + return '{"id": 1}', '{"name": "contract-001", "customer_id": 456, "status": "active"}' + } + 'delete' { + return '{"id": 1}', 'true' + } + 'exist' { + return '{"id": 1}', 'true' + } + 'list' { + return '{}', '[{"name": "contract-001", "customer_id": 456, "status": "active"}]' + } + else { + return '{}', '{}' + } + } +} + +pub fn (self Contract) dump(mut e encoder.Encoder) ! { + e.add_u32(self.customer_id) + + // Encode compute slices + e.add_int(self.compute_slices.len) + for slice in self.compute_slices { + e.add_u32(slice.node_id) + e.add_u16(slice.id) + e.add_f64(slice.mem_gb) + e.add_f64(slice.storage_gb) + e.add_int(slice.passmark) + e.add_int(slice.vcores) + e.add_int(slice.cpu_oversubscription) + e.add_string(slice.tags) + } + + // Encode storage slices + e.add_int(self.storage_slices.len) + for slice in self.storage_slices { + e.add_u32(slice.node_id) + e.add_u16(slice.id) + e.add_int(slice.storage_size_gb) + e.add_string(slice.tags) + } + + e.add_f64(self.compute_slice_price) + e.add_f64(self.storage_slice_price) + e.add_f64(self.network_slice_price) + e.add_int(int(self.status)) + e.add_u32(self.start_date) + e.add_u32(self.end_date) + e.add_string(self.signature_user) + e.add_string(self.signature_hoster) + e.add_int(int(self.billing_period)) +} + +fn (mut self DBContract) load(mut o Contract, mut e encoder.Decoder) ! { + o.customer_id = e.get_u32()! + + // Decode compute slices + compute_slices_len := e.get_int()! + o.compute_slices = []ComputeSliceProvisioned{len: compute_slices_len} + for i in 0 .. compute_slices_len { + o.compute_slices[i].node_id = e.get_u32()! + o.compute_slices[i].id = e.get_u16()! + o.compute_slices[i].mem_gb = e.get_f64()! + o.compute_slices[i].storage_gb = e.get_f64()! + o.compute_slices[i].passmark = e.get_int()! + o.compute_slices[i].vcores = e.get_int()! + o.compute_slices[i].cpu_oversubscription = e.get_int()! + o.compute_slices[i].tags = e.get_string()! + } + + // Decode storage slices + storage_slices_len := e.get_int()! + o.storage_slices = []StorageSliceProvisioned{len: storage_slices_len} + for i in 0 .. storage_slices_len { + o.storage_slices[i].node_id = e.get_u32()! + o.storage_slices[i].id = e.get_u16()! + o.storage_slices[i].storage_size_gb = e.get_int()! + o.storage_slices[i].tags = e.get_string()! + } + + o.compute_slice_price = e.get_f64()! + o.storage_slice_price = e.get_f64()! + o.network_slice_price = e.get_f64()! + o.status = unsafe { ContractStatus(e.get_int()!) } + o.start_date = e.get_u32()! + o.end_date = e.get_u32()! + o.signature_user = e.get_string()! + o.signature_hoster = e.get_string()! + o.billing_period = unsafe { BillingPeriod(e.get_int()!) } +} + +@[params] +pub struct ContractArg { +pub mut: + name string + description string + customer_id u32 + compute_slices []ComputeSliceProvisioned + storage_slices []StorageSliceProvisioned + compute_slice_price f64 + storage_slice_price f64 + network_slice_price f64 + status ContractStatus + start_date u32 + end_date u32 + signature_user string + signature_hoster string + billing_period BillingPeriod +} + +pub fn (mut self DBContract) new(args ContractArg) !Contract { + mut o := Contract{ + customer_id: args.customer_id + compute_slices: args.compute_slices + storage_slices: args.storage_slices + compute_slice_price: args.compute_slice_price + storage_slice_price: args.storage_slice_price + network_slice_price: args.network_slice_price + status: args.status + start_date: args.start_date + end_date: args.end_date + signature_user: args.signature_user + signature_hoster: args.signature_hoster + billing_period: args.billing_period + } + + o.name = args.name + o.description = args.description + o.updated_at = ourtime.now().unix() + + return o +} + +pub fn (mut self DBContract) set(o Contract) !Contract { + return self.db.set[Contract](o)! +} + +pub fn (mut self DBContract) delete(id u32) ! { + self.db.delete[Contract](id)! +} + +pub fn (mut self DBContract) exist(id u32) !bool { + return self.db.exists[Contract](id)! +} + +pub fn (mut self DBContract) get(id u32) !Contract { + mut o, data := self.db.get_data[Contract](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBContract) list() ![]Contract { + return self.db.list[Contract]()!.map(self.get(it)!) +} \ No newline at end of file diff --git a/lib/threefold/models_tfgrid/mod.v b/lib/threefold/models_tfgrid/mod.v new file mode 100644 index 00000000..49ce04cf --- /dev/null +++ b/lib/threefold/models_tfgrid/mod.v @@ -0,0 +1,8 @@ +module models_tfgrid + +// Re-export all the root objects and their supporting structures +pub use node +pub use nodegroup +pub use bid +pub use contract +pub use reputation \ No newline at end of file diff --git a/lib/threefold/models_tfgrid/node.v b/lib/threefold/models_tfgrid/node.v new file mode 100644 index 00000000..ed437ea2 --- /dev/null +++ b/lib/threefold/models_tfgrid/node.v @@ -0,0 +1,445 @@ +module models_tfgrid + +import freeflowuniverse.herolib.data.encoder +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db + +// Storage device information +pub struct StorageDevice { +pub mut: + id string // can be used in node + size_gb f64 // Size of the storage device in gigabytes + description string // Description of the storage device +} + +// Memory device information +pub struct MemoryDevice { +pub mut: + id string // can be used in node + size_gb f64 // Size of the memory device in gigabytes + description string // Description of the memory device +} + +// CPU device information +pub struct CPUDevice { +pub mut: + id string // can be used in node + cores int // Number of CPU cores + passmark int + description string // Description of the CPU + cpu_brand string // Brand of the CPU + cpu_version string // Version of the CPU +} + +// GPU device information +pub struct GPUDevice { +pub mut: + id string // can be used in node + cores int // Number of GPU cores + memory_gb f64 // Size of the GPU memory in gigabytes + description string // Description of the GPU + gpu_brand string + gpu_version string +} + +// Network device information +pub struct NetworkDevice { +pub mut: + id string // can be used in node + speed_mbps int // Network speed in Mbps + description string // Description of the network device +} + +// Aggregated device info for a node +pub struct DeviceInfo { +pub mut: + vendor string + storage []StorageDevice + memory []MemoryDevice + cpu []CPUDevice + gpu []GPUDevice + network []NetworkDevice +} + +// NodeCapacity represents the hardware capacity details of a node +pub struct NodeCapacity { +pub mut: + storage_gb f64 // Total storage in gigabytes + mem_gb f64 // Total memory in gigabytes + mem_gb_gpu f64 // Total GPU memory in gigabytes + passmark int // Passmark score for the node + vcores int // Total virtual cores +} + +// Pricing policy for slices +pub struct PricingPolicy { +pub mut: + name string // Human friendly policy name (e.g. "fixed", "market") + details string // Optional free-form details as JSON-encoded string + marketplace_year_discounts []int // e.g. [30, 40, 50] means if user has more CC than 1Y utilization, 30% discount, etc. +} + +// SLA policy for slices +pub struct SLAPolicy { +pub mut: + uptime f32 // Uptime in percentage (0..100) + max_response_time_ms u32 // Max response time in ms + sla_bandwidth_mbit int // minimal mbits we can expect avg over 1h per node, 0 means we don't guarantee + sla_penalty int // 0-100, percent of money given back in relation to month if sla breached +} + +// Compute slice (typically represents a base unit of compute) +pub struct ComputeSlice { +pub mut: + id int // the id of the slice in the node + mem_gb f64 + storage_gb f64 + passmark int + vcores int + cpu_oversubscription int + storage_oversubscription int + price_range []f64 // Min/max allowed price range for validation + gpus u8 // nr of GPU's see node to know what GPU's are + price_cc f64 // price per slice in cloud credits + pricing_policy PricingPolicy + sla_policy SLAPolicy +} + +// Storage slice (typically 1GB of storage) +pub struct StorageSlice { +pub mut: + id int // the id of the slice in the node + price_cc f64 // price per slice in cloud credits + pricing_policy PricingPolicy + sla_policy SLAPolicy +} + +// Grid4 Node model - ROOT OBJECT +@[heap] +pub struct Node { + db.Base +pub mut: + nodegroupid int // Link to node group + uptime int // Uptime percentage 0..100 + computeslices []ComputeSlice + storageslices []StorageSlice + devices DeviceInfo + country string // 2 letter code + capacity NodeCapacity // Hardware capacity details + birthtime u32 // first time node was active + pubkey string + signature_node string // signature done on node to validate pubkey with privkey + signature_farmer string // signature as done by farmers to validate their identity +} + +pub struct DBNode { +pub mut: + db &db.DB @[skip; str: skip] +} + +pub fn (self Node) type_name() string { + return 'node' +} + +pub fn (self Node) description(methodname string) string { + match methodname { + 'set' { + return 'Create or update a node. Returns the ID of the node.' + } + 'get' { + return 'Retrieve a node by ID. Returns the node object.' + } + 'delete' { + return 'Delete a node by ID. Returns true if successful.' + } + 'exist' { + return 'Check if a node exists by ID. Returns true or false.' + } + 'list' { + return 'List all nodes. Returns an array of node objects.' + } + else { + return 'Node management methods for Grid4 infrastructure.' + } + } +} + +pub fn (self Node) example(methodname string) (string, string) { + match methodname { + 'set' { + return '{"node": {"name": "node-001", "nodegroupid": 1, "uptime": 99, "country": "BE", "devices": {"vendor": "Dell"}, "capacity": {"storage_gb": 1000, "mem_gb": 64, "vcores": 16, "passmark": 15000}}}', '1' + } + 'get' { + return '{"id": 1}', '{"name": "node-001", "nodegroupid": 1, "uptime": 99, "country": "BE"}' + } + 'delete' { + return '{"id": 1}', 'true' + } + 'exist' { + return '{"id": 1}', 'true' + } + 'list' { + return '{}', '[{"name": "node-001", "nodegroupid": 1, "uptime": 99, "country": "BE"}]' + } + else { + return '{}', '{}' + } + } +} + +pub fn (self Node) dump(mut e encoder.Encoder) ! { + e.add_int(self.nodegroupid) + e.add_int(self.uptime) + + // Encode compute slices + e.add_int(self.computeslices.len) + for slice in self.computeslices { + e.add_int(slice.id) + e.add_f64(slice.mem_gb) + e.add_f64(slice.storage_gb) + e.add_int(slice.passmark) + e.add_int(slice.vcores) + e.add_int(slice.cpu_oversubscription) + e.add_int(slice.storage_oversubscription) + e.add_list_f64(slice.price_range) + e.add_u8(slice.gpus) + e.add_f64(slice.price_cc) + e.add_string(slice.pricing_policy.name) + e.add_string(slice.pricing_policy.details) + e.add_list_int(slice.pricing_policy.marketplace_year_discounts) + e.add_f32(slice.sla_policy.uptime) + e.add_u32(slice.sla_policy.max_response_time_ms) + e.add_int(slice.sla_policy.sla_bandwidth_mbit) + e.add_int(slice.sla_policy.sla_penalty) + } + + // Encode storage slices + e.add_int(self.storageslices.len) + for slice in self.storageslices { + e.add_int(slice.id) + e.add_f64(slice.price_cc) + e.add_string(slice.pricing_policy.name) + e.add_string(slice.pricing_policy.details) + e.add_list_int(slice.pricing_policy.marketplace_year_discounts) + e.add_f32(slice.sla_policy.uptime) + e.add_u32(slice.sla_policy.max_response_time_ms) + e.add_int(slice.sla_policy.sla_bandwidth_mbit) + e.add_int(slice.sla_policy.sla_penalty) + } + + // Encode devices + e.add_string(self.devices.vendor) + e.add_int(self.devices.storage.len) + for device in self.devices.storage { + e.add_string(device.id) + e.add_f64(device.size_gb) + e.add_string(device.description) + } + e.add_int(self.devices.memory.len) + for device in self.devices.memory { + e.add_string(device.id) + e.add_f64(device.size_gb) + e.add_string(device.description) + } + e.add_int(self.devices.cpu.len) + for device in self.devices.cpu { + e.add_string(device.id) + e.add_int(device.cores) + e.add_int(device.passmark) + e.add_string(device.description) + e.add_string(device.cpu_brand) + e.add_string(device.cpu_version) + } + e.add_int(self.devices.gpu.len) + for device in self.devices.gpu { + e.add_string(device.id) + e.add_int(device.cores) + e.add_f64(device.memory_gb) + e.add_string(device.description) + e.add_string(device.gpu_brand) + e.add_string(device.gpu_version) + } + e.add_int(self.devices.network.len) + for device in self.devices.network { + e.add_string(device.id) + e.add_int(device.speed_mbps) + e.add_string(device.description) + } + + e.add_string(self.country) + e.add_f64(self.capacity.storage_gb) + e.add_f64(self.capacity.mem_gb) + e.add_f64(self.capacity.mem_gb_gpu) + e.add_int(self.capacity.passmark) + e.add_int(self.capacity.vcores) + e.add_u32(self.birthtime) + e.add_string(self.pubkey) + e.add_string(self.signature_node) + e.add_string(self.signature_farmer) +} + +fn (mut self DBNode) load(mut o Node, mut e encoder.Decoder) ! { + o.nodegroupid = e.get_int()! + o.uptime = e.get_int()! + + // Decode compute slices + compute_slices_len := e.get_int()! + o.computeslices = []ComputeSlice{len: compute_slices_len} + for i in 0 .. compute_slices_len { + o.computeslices[i].id = e.get_int()! + o.computeslices[i].mem_gb = e.get_f64()! + o.computeslices[i].storage_gb = e.get_f64()! + o.computeslices[i].passmark = e.get_int()! + o.computeslices[i].vcores = e.get_int()! + o.computeslices[i].cpu_oversubscription = e.get_int()! + o.computeslices[i].storage_oversubscription = e.get_int()! + o.computeslices[i].price_range = e.get_list_f64()! + o.computeslices[i].gpus = e.get_u8()! + o.computeslices[i].price_cc = e.get_f64()! + o.computeslices[i].pricing_policy.name = e.get_string()! + o.computeslices[i].pricing_policy.details = e.get_string()! + o.computeslices[i].pricing_policy.marketplace_year_discounts = e.get_list_int()! + o.computeslices[i].sla_policy.uptime = e.get_f32()! + o.computeslices[i].sla_policy.max_response_time_ms = e.get_u32()! + o.computeslices[i].sla_policy.sla_bandwidth_mbit = e.get_int()! + o.computeslices[i].sla_policy.sla_penalty = e.get_int()! + } + + // Decode storage slices + storage_slices_len := e.get_int()! + o.storageslices = []StorageSlice{len: storage_slices_len} + for i in 0 .. storage_slices_len { + o.storageslices[i].id = e.get_int()! + o.storageslices[i].price_cc = e.get_f64()! + o.storageslices[i].pricing_policy.name = e.get_string()! + o.storageslices[i].pricing_policy.details = e.get_string()! + o.storageslices[i].pricing_policy.marketplace_year_discounts = e.get_list_int()! + o.storageslices[i].sla_policy.uptime = e.get_f32()! + o.storageslices[i].sla_policy.max_response_time_ms = e.get_u32()! + o.storageslices[i].sla_policy.sla_bandwidth_mbit = e.get_int()! + o.storageslices[i].sla_policy.sla_penalty = e.get_int()! + } + + // Decode devices + o.devices.vendor = e.get_string()! + + storage_devices_len := e.get_int()! + o.devices.storage = []StorageDevice{len: storage_devices_len} + for i in 0 .. storage_devices_len { + o.devices.storage[i].id = e.get_string()! + o.devices.storage[i].size_gb = e.get_f64()! + o.devices.storage[i].description = e.get_string()! + } + + memory_devices_len := e.get_int()! + o.devices.memory = []MemoryDevice{len: memory_devices_len} + for i in 0 .. memory_devices_len { + o.devices.memory[i].id = e.get_string()! + o.devices.memory[i].size_gb = e.get_f64()! + o.devices.memory[i].description = e.get_string()! + } + + cpu_devices_len := e.get_int()! + o.devices.cpu = []CPUDevice{len: cpu_devices_len} + for i in 0 .. cpu_devices_len { + o.devices.cpu[i].id = e.get_string()! + o.devices.cpu[i].cores = e.get_int()! + o.devices.cpu[i].passmark = e.get_int()! + o.devices.cpu[i].description = e.get_string()! + o.devices.cpu[i].cpu_brand = e.get_string()! + o.devices.cpu[i].cpu_version = e.get_string()! + } + + gpu_devices_len := e.get_int()! + o.devices.gpu = []GPUDevice{len: gpu_devices_len} + for i in 0 .. gpu_devices_len { + o.devices.gpu[i].id = e.get_string()! + o.devices.gpu[i].cores = e.get_int()! + o.devices.gpu[i].memory_gb = e.get_f64()! + o.devices.gpu[i].description = e.get_string()! + o.devices.gpu[i].gpu_brand = e.get_string()! + o.devices.gpu[i].gpu_version = e.get_string()! + } + + network_devices_len := e.get_int()! + o.devices.network = []NetworkDevice{len: network_devices_len} + for i in 0 .. network_devices_len { + o.devices.network[i].id = e.get_string()! + o.devices.network[i].speed_mbps = e.get_int()! + o.devices.network[i].description = e.get_string()! + } + + o.country = e.get_string()! + o.capacity.storage_gb = e.get_f64()! + o.capacity.mem_gb = e.get_f64()! + o.capacity.mem_gb_gpu = e.get_f64()! + o.capacity.passmark = e.get_int()! + o.capacity.vcores = e.get_int()! + o.birthtime = e.get_u32()! + o.pubkey = e.get_string()! + o.signature_node = e.get_string()! + o.signature_farmer = e.get_string()! +} + +@[params] +pub struct NodeArg { +pub mut: + name string + description string + nodegroupid int + uptime int + computeslices []ComputeSlice + storageslices []StorageSlice + devices DeviceInfo + country string + capacity NodeCapacity + birthtime u32 + pubkey string + signature_node string + signature_farmer string +} + +pub fn (mut self DBNode) new(args NodeArg) !Node { + mut o := Node{ + nodegroupid: args.nodegroupid + uptime: args.uptime + computeslices: args.computeslices + storageslices: args.storageslices + devices: args.devices + country: args.country + capacity: args.capacity + birthtime: args.birthtime + pubkey: args.pubkey + signature_node: args.signature_node + signature_farmer: args.signature_farmer + } + + o.name = args.name + o.description = args.description + o.updated_at = ourtime.now().unix() + + return o +} + +pub fn (mut self DBNode) set(o Node) !Node { + return self.db.set[Node](o)! +} + +pub fn (mut self DBNode) delete(id u32) ! { + self.db.delete[Node](id)! +} + +pub fn (mut self DBNode) exist(id u32) !bool { + return self.db.exists[Node](id)! +} + +pub fn (mut self DBNode) get(id u32) !Node { + mut o, data := self.db.get_data[Node](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBNode) list() ![]Node { + return self.db.list[Node]()!.map(self.get(it)!) +} \ No newline at end of file diff --git a/lib/threefold/models_tfgrid/nodegroup.v b/lib/threefold/models_tfgrid/nodegroup.v new file mode 100644 index 00000000..6a7a8240 --- /dev/null +++ b/lib/threefold/models_tfgrid/nodegroup.v @@ -0,0 +1,159 @@ +module models_tfgrid + +import freeflowuniverse.herolib.data.encoder +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db + +// NodeGroup - ROOT OBJECT +@[heap] +pub struct NodeGroup { + db.Base +pub mut: + farmerid u32 // link back to farmer who owns the nodegroup + secret string // only visible by farmer, in future encrypted, used to boot a node + slapolicy SLAPolicy + pricingpolicy PricingPolicy + compute_slice_normalized_pricing_cc f64 // pricing in CC - cloud credit, per 2GB node slice + storage_slice_normalized_pricing_cc f64 // pricing in CC - cloud credit, per 1GB storage slice + signature_farmer string // signature as done by farmers to validate that they created this group +} + +pub struct DBNodeGroup { +pub mut: + db &db.DB @[skip; str: skip] +} + +pub fn (self NodeGroup) type_name() string { + return 'nodegroup' +} + +pub fn (self NodeGroup) description(methodname string) string { + match methodname { + 'set' { + return 'Create or update a node group. Returns the ID of the node group.' + } + 'get' { + return 'Retrieve a node group by ID. Returns the node group object.' + } + 'delete' { + return 'Delete a node group by ID. Returns true if successful.' + } + 'exist' { + return 'Check if a node group exists by ID. Returns true or false.' + } + 'list' { + return 'List all node groups. Returns an array of node group objects.' + } + else { + return 'Node group management methods for Grid4 infrastructure.' + } + } +} + +pub fn (self NodeGroup) example(methodname string) (string, string) { + match methodname { + 'set' { + return '{"nodegroup": {"name": "farmer-group-1", "farmerid": 123, "compute_slice_normalized_pricing_cc": 0.05, "storage_slice_normalized_pricing_cc": 0.01}}', '1' + } + 'get' { + return '{"id": 1}', '{"name": "farmer-group-1", "farmerid": 123, "compute_slice_normalized_pricing_cc": 0.05}' + } + 'delete' { + return '{"id": 1}', 'true' + } + 'exist' { + return '{"id": 1}', 'true' + } + 'list' { + return '{}', '[{"name": "farmer-group-1", "farmerid": 123, "compute_slice_normalized_pricing_cc": 0.05}]' + } + else { + return '{}', '{}' + } + } +} + +pub fn (self NodeGroup) dump(mut e encoder.Encoder) ! { + e.add_u32(self.farmerid) + e.add_string(self.secret) + e.add_f32(self.slapolicy.uptime) + e.add_u32(self.slapolicy.max_response_time_ms) + e.add_int(self.slapolicy.sla_bandwidth_mbit) + e.add_int(self.slapolicy.sla_penalty) + e.add_string(self.pricingpolicy.name) + e.add_string(self.pricingpolicy.details) + e.add_list_int(self.pricingpolicy.marketplace_year_discounts) + e.add_f64(self.compute_slice_normalized_pricing_cc) + e.add_f64(self.storage_slice_normalized_pricing_cc) + e.add_string(self.signature_farmer) +} + +fn (mut self DBNodeGroup) load(mut o NodeGroup, mut e encoder.Decoder) ! { + o.farmerid = e.get_u32()! + o.secret = e.get_string()! + o.slapolicy.uptime = e.get_f32()! + o.slapolicy.max_response_time_ms = e.get_u32()! + o.slapolicy.sla_bandwidth_mbit = e.get_int()! + o.slapolicy.sla_penalty = e.get_int()! + o.pricingpolicy.name = e.get_string()! + o.pricingpolicy.details = e.get_string()! + o.pricingpolicy.marketplace_year_discounts = e.get_list_int()! + o.compute_slice_normalized_pricing_cc = e.get_f64()! + o.storage_slice_normalized_pricing_cc = e.get_f64()! + o.signature_farmer = e.get_string()! +} + +@[params] +pub struct NodeGroupArg { +pub mut: + name string + description string + farmerid u32 + secret string + slapolicy SLAPolicy + pricingpolicy PricingPolicy + compute_slice_normalized_pricing_cc f64 + storage_slice_normalized_pricing_cc f64 + signature_farmer string +} + +pub fn (mut self DBNodeGroup) new(args NodeGroupArg) !NodeGroup { + mut o := NodeGroup{ + farmerid: args.farmerid + secret: args.secret + slapolicy: args.slapolicy + pricingpolicy: args.pricingpolicy + compute_slice_normalized_pricing_cc: args.compute_slice_normalized_pricing_cc + storage_slice_normalized_pricing_cc: args.storage_slice_normalized_pricing_cc + signature_farmer: args.signature_farmer + } + + o.name = args.name + o.description = args.description + o.updated_at = ourtime.now().unix() + + return o +} + +pub fn (mut self DBNodeGroup) set(o NodeGroup) !NodeGroup { + return self.db.set[NodeGroup](o)! +} + +pub fn (mut self DBNodeGroup) delete(id u32) ! { + self.db.delete[NodeGroup](id)! +} + +pub fn (mut self DBNodeGroup) exist(id u32) !bool { + return self.db.exists[NodeGroup](id)! +} + +pub fn (mut self DBNodeGroup) get(id u32) !NodeGroup { + mut o, data := self.db.get_data[NodeGroup](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBNodeGroup) list() ![]NodeGroup { + return self.db.list[NodeGroup]()!.map(self.get(it)!) +} \ No newline at end of file diff --git a/lib/threefold/models_tfgrid/reputation.v b/lib/threefold/models_tfgrid/reputation.v new file mode 100644 index 00000000..be8ca718 --- /dev/null +++ b/lib/threefold/models_tfgrid/reputation.v @@ -0,0 +1,157 @@ +module models_tfgrid + +import freeflowuniverse.herolib.data.encoder +import freeflowuniverse.herolib.data.ourtime +import freeflowuniverse.herolib.hero.db + +// Individual node reputation information +pub struct NodeReputation { +pub mut: + node_id u32 + reputation int = 50 // between 0 and 100, earned over time + uptime int // between 0 and 100, set by system +} + +// NodeGroupReputation - ROOT OBJECT +@[heap] +pub struct NodeGroupReputation { + db.Base +pub mut: + nodegroup_id u32 + reputation int = 50 // between 0 and 100, earned over time + uptime int // between 0 and 100, set by system, farmer has no ability to set this + nodes []NodeReputation +} + +pub struct DBNodeGroupReputation { +pub mut: + db &db.DB @[skip; str: skip] +} + +pub fn (self NodeGroupReputation) type_name() string { + return 'nodegroupreputation' +} + +pub fn (self NodeGroupReputation) description(methodname string) string { + match methodname { + 'set' { + return 'Create or update node group reputation. Returns the ID.' + } + 'get' { + return 'Retrieve node group reputation by ID. Returns the reputation object.' + } + 'delete' { + return 'Delete node group reputation by ID. Returns true if successful.' + } + 'exist' { + return 'Check if node group reputation exists by ID. Returns true or false.' + } + 'list' { + return 'List all node group reputations. Returns an array of reputation objects.' + } + else { + return 'Reputation management methods for Grid4 node groups.' + } + } +} + +pub fn (self NodeGroupReputation) example(methodname string) (string, string) { + match methodname { + 'set' { + return '{"reputation": {"name": "group-1-reputation", "nodegroup_id": 1, "reputation": 85, "uptime": 99}}', '1' + } + 'get' { + return '{"id": 1}', '{"name": "group-1-reputation", "nodegroup_id": 1, "reputation": 85, "uptime": 99}' + } + 'delete' { + return '{"id": 1}', 'true' + } + 'exist' { + return '{"id": 1}', 'true' + } + 'list' { + return '{}', '[{"name": "group-1-reputation", "nodegroup_id": 1, "reputation": 85, "uptime": 99}]' + } + else { + return '{}', '{}' + } + } +} + +pub fn (self NodeGroupReputation) dump(mut e encoder.Encoder) ! { + e.add_u32(self.nodegroup_id) + e.add_int(self.reputation) + e.add_int(self.uptime) + + // Encode node reputations + e.add_int(self.nodes.len) + for node in self.nodes { + e.add_u32(node.node_id) + e.add_int(node.reputation) + e.add_int(node.uptime) + } +} + +fn (mut self DBNodeGroupReputation) load(mut o NodeGroupReputation, mut e encoder.Decoder) ! { + o.nodegroup_id = e.get_u32()! + o.reputation = e.get_int()! + o.uptime = e.get_int()! + + // Decode node reputations + nodes_len := e.get_int()! + o.nodes = []NodeReputation{len: nodes_len} + for i in 0 .. nodes_len { + o.nodes[i].node_id = e.get_u32()! + o.nodes[i].reputation = e.get_int()! + o.nodes[i].uptime = e.get_int()! + } +} + +@[params] +pub struct NodeGroupReputationArg { +pub mut: + name string + description string + nodegroup_id u32 + reputation int = 50 + uptime int + nodes []NodeReputation +} + +pub fn (mut self DBNodeGroupReputation) new(args NodeGroupReputationArg) !NodeGroupReputation { + mut o := NodeGroupReputation{ + nodegroup_id: args.nodegroup_id + reputation: args.reputation + uptime: args.uptime + nodes: args.nodes + } + + o.name = args.name + o.description = args.description + o.updated_at = ourtime.now().unix() + + return o +} + +pub fn (mut self DBNodeGroupReputation) set(o NodeGroupReputation) !NodeGroupReputation { + return self.db.set[NodeGroupReputation](o)! +} + +pub fn (mut self DBNodeGroupReputation) delete(id u32) ! { + self.db.delete[NodeGroupReputation](id)! +} + +pub fn (mut self DBNodeGroupReputation) exist(id u32) !bool { + return self.db.exists[NodeGroupReputation](id)! +} + +pub fn (mut self DBNodeGroupReputation) get(id u32) !NodeGroupReputation { + mut o, data := self.db.get_data[NodeGroupReputation](id)! + mut e_decoder := encoder.decoder_new(data) + self.load(mut o, mut e_decoder)! + return o +} + +pub fn (mut self DBNodeGroupReputation) list() ![]NodeGroupReputation { + return self.db.list[NodeGroupReputation]()!.map(self.get(it)!) +} \ No newline at end of file