Skip to content

Commit 135adcf

Browse files
committed
map mycelium identity to twin id
- add storage map from myc-pk -> twin-id - add setter function to set twin-id for myc-pk - update clients with setter/getter functions
1 parent 77e684b commit 135adcf

File tree

8 files changed

+284
-2
lines changed

8 files changed

+284
-2
lines changed

clients/tfchain-client-go/twin.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,49 @@ func (s *Substrate) UpdateTwin(identity Identity, relay string, pk []byte) (uint
182182

183183
return s.GetTwinByPubKey(identity.PublicKey())
184184
}
185+
186+
// SetTwinMyceliumPK sets the mycelium public key for a twin
187+
func (s *Substrate) SetTwinMyceliumPK(identity Identity, twinID uint32, myceliumPK []byte) error {
188+
cl, meta, err := s.GetClient()
189+
if err != nil {
190+
return err
191+
}
192+
193+
c, err := types.NewCall(meta, "TfgridModule.set_twin_mycelium_pk", twinID, myceliumPK)
194+
if err != nil {
195+
return errors.Wrap(err, "failed to create call")
196+
}
197+
198+
if _, err := s.Call(cl, meta, identity, c); err != nil {
199+
return errors.Wrap(err, "failed to set twin mycelium pk")
200+
}
201+
202+
return nil
203+
}
204+
205+
// GetTwinByMyceliumPK gets a twin by mycelium public key
206+
func (s *Substrate) GetTwinByMyceliumPK(myceliumPK []byte) (*Twin, error) {
207+
cl, meta, err := s.GetClient()
208+
if err != nil {
209+
return nil, err
210+
}
211+
212+
// First, get the twin ID from the mycelium PK mapping
213+
key, err := types.CreateStorageKey(meta, "TfgridModule", "TwinByMyceliumPk", myceliumPK, nil)
214+
if err != nil {
215+
return nil, errors.Wrap(err, "failed to create substrate query key")
216+
}
217+
218+
var twinID types.U32
219+
ok, err := cl.RPC.State.GetStorageLatest(key, &twinID)
220+
if err != nil {
221+
return nil, errors.Wrap(err, "failed to lookup twin by mycelium pk")
222+
}
223+
224+
if !ok || twinID == 0 {
225+
return nil, errors.Wrap(ErrNotFound, "twin not found for mycelium pk")
226+
}
227+
228+
// Now get the full twin object using the twin ID
229+
return s.GetTwin(uint32(twinID))
230+
}

clients/tfchain-client-js/lib/client.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ const {
1010
} = require('./entity')
1111
const {
1212
createTwin, getTwin, getTwinIdByAccountId, updateTwin,
13-
deleteTwin, addTwinEntity, deleteTwinEntity, listTwins
13+
deleteTwin, addTwinEntity, deleteTwinEntity, listTwins,
14+
setTwinMyceliumPK, getTwinByMyceliumPK
1415
} = require('./twin')
1516
const {
1617
createFarm, getFarm, deleteFarm,
@@ -161,6 +162,14 @@ class Client {
161162
return deleteTwinEntity(this, twinID, entityID, callback)
162163
}
163164

165+
async setTwinMyceliumPK(twinId, myceliumPk, callback) {
166+
return setTwinMyceliumPK(this, twinId, myceliumPk, callback)
167+
}
168+
169+
async getTwinByMyceliumPK(myceliumPk) {
170+
return getTwinByMyceliumPK(this, myceliumPk)
171+
}
172+
164173
async createFarm(name, certificationType, publicIPs, callback) {
165174
return createFarm(this, name, certificationType, publicIPs, callback)
166175
}

clients/tfchain-client-js/lib/twin.js

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,28 @@ async function deleteTwin (self, id, callback) {
9292
.signAndSend(self.key, { nonce }, callback)
9393
}
9494

95+
// setTwinMyceliumPK sets the mycelium public key for a twin
96+
async function setTwinMyceliumPK (self, twinId, myceliumPk, callback) {
97+
const setMyceliumPk = self.api.tx.tfgridModule.setTwinMyceliumPk(twinId, myceliumPk)
98+
const nonce = await self.api.rpc.system.accountNextIndex(self.address)
99+
100+
return setMyceliumPk.signAndSend(self.key, { nonce }, callback)
101+
}
102+
103+
// getTwinByMyceliumPK gets a twin by mycelium public key
104+
async function getTwinByMyceliumPK (self, myceliumPk) {
105+
// First, get the twin ID from the mycelium PK mapping
106+
const twinIdResult = await self.api.query.tfgridModule.twinByMyceliumPk(myceliumPk)
107+
const twinId = twinIdResult.toJSON()
108+
109+
if (!twinId || twinId === 0) {
110+
throw Error(`Couldn't find a twin for mycelium pk: ${myceliumPk}`)
111+
}
112+
113+
// Now get the full twin object using the twin ID
114+
return getTwin(self, twinId)
115+
}
116+
95117
module.exports = {
96118
createTwin,
97119
updateTwin,
@@ -100,5 +122,7 @@ module.exports = {
100122
deleteTwin,
101123
addTwinEntity,
102124
deleteTwinEntity,
103-
listTwins
125+
listTwins,
126+
setTwinMyceliumPK,
127+
getTwinByMyceliumPK
104128
}

clients/tfchain-client-rs/src/client.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,26 @@ impl Client {
152152
current::get_twin_id_by_account(self, account).await
153153
}
154154

155+
// Sets mycelium public key for a twin and checks for success, blockhash is returned on success
156+
pub async fn set_twin_mycelium_pk(
157+
&self,
158+
kp: &KeyPair,
159+
twin_id: u32,
160+
mycelium_pk: Vec<u8>,
161+
) -> Result<Hash, Error> {
162+
current::set_twin_mycelium_pk(self, kp, twin_id, mycelium_pk).await
163+
}
164+
165+
// Gets a twin by mycelium public key and returns the full twin object
166+
pub async fn get_twin_by_mycelium_pk(
167+
&self,
168+
mycelium_pk: Vec<u8>,
169+
) -> Result<Option<Twin>, Error> {
170+
// We pass a dummy keypair since it's not used in the implementation
171+
let dummy_kp = KeyPair::Sr25519(sr25519::Pair::from_seed(&[0u8; 32]));
172+
current::get_twin_by_mycelium_pk(self, &dummy_kp, mycelium_pk).await
173+
}
174+
155175
pub async fn get_farm_by_id(&self, id: u32) -> Result<Option<Farm>, Error> {
156176
current::get_farm_by_id(self, id).await
157177
}

clients/tfchain-client-rs/src/runtimes/current.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,48 @@ pub async fn get_balance(
201201
.fetch(&current::storage().system().account(account))
202202
.await?)
203203
}
204+
205+
pub async fn set_twin_mycelium_pk(
206+
cl: &Client,
207+
kp: &KeyPair,
208+
twin_id: u32,
209+
mycelium_pk: Vec<u8>,
210+
) -> Result<H256, Error> {
211+
let set_mycelium_pk_tx = current::tx().tfgrid_module().set_twin_mycelium_pk(
212+
twin_id,
213+
BoundedVec(mycelium_pk),
214+
);
215+
216+
let signer = kp.signer();
217+
218+
let set_mycelium_pk = cl
219+
.api
220+
.tx()
221+
.sign_and_submit_then_watch_default(&set_mycelium_pk_tx, &signer)
222+
.await?
223+
.wait_for_finalized_success()
224+
.await?;
225+
226+
Ok(set_mycelium_pk.block_hash())
227+
}
228+
229+
pub async fn get_twin_by_mycelium_pk(
230+
cl: &Client,
231+
_kp: &KeyPair,
232+
mycelium_pk: Vec<u8>,
233+
) -> Result<Option<Twin>, Error> {
234+
// Query the storage directly using the mycelium pk to get twin ID
235+
let twin_id = cl
236+
.api
237+
.storage()
238+
.at_latest()
239+
.await?
240+
.fetch(&current::storage().tfgrid_module().twin_by_mycelium_pk(BoundedVec(mycelium_pk)))
241+
.await?;
242+
243+
if let Some(id) = twin_id {
244+
get_twin_by_id(cl, id).await
245+
} else {
246+
Ok(None)
247+
}
248+
}

substrate-node/pallets/pallet-tfgrid/src/benchmarking.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,36 @@ benchmarks! {
737737
assert_last_event::<T>(Event::NodeUptimeReported(node_id, now, uptime).into());
738738
}
739739

740+
// set_twin_mycelium_pk
741+
set_twin_mycelium_pk {
742+
let caller: T::AccountId = whitelisted_caller();
743+
_create_twin::<T>(caller.clone());
744+
let twin_id = 1;
745+
let mycelium_pk = get_mycelium_pk_input(b"some_mycelium_pk");
746+
}: _(RawOrigin::Signed(caller), twin_id, mycelium_pk.clone())
747+
verify {
748+
assert_eq!(TfgridModule::<T>::twin_by_mycelium_pk(&mycelium_pk), Some(twin_id));
749+
}
750+
751+
// get_twin_by_mycelium_pk
752+
// get_twin_by_mycelium_pk {
753+
// let caller: T::AccountId = whitelisted_caller();
754+
// _create_twin::<T>(caller.clone());
755+
// let twin_id = 1;
756+
// let mycelium_pk = get_mycelium_pk_input(b"some_mycelium_pk");
757+
758+
// // First set the mycelium pk
759+
// assert_ok!(TfgridModule::<T>::set_twin_mycelium_pk(
760+
// RawOrigin::Signed(caller.clone()).into(),
761+
// twin_id,
762+
// mycelium_pk.clone()
763+
// ));
764+
// }: _(RawOrigin::Signed(caller), mycelium_pk.clone())
765+
// verify {
766+
// let twin = TfgridModule::<T>::twins(twin_id).unwrap();
767+
// assert_last_event::<T>(Event::TwinStored(twin).into());
768+
// }
769+
740770
// Calling the `impl_benchmark_test_suite` macro inside the `benchmarks`
741771
// block will generate one #[test] function per benchmark
742772
impl_benchmark_test_suite!(TfgridModule, crate::mock::new_test_ext(), crate::mock::TestRuntime)
@@ -1022,3 +1052,7 @@ pub(crate) fn get_pub_config_gw6_input(gw6_input: &[u8]) -> Gw6Input {
10221052
pub(crate) fn get_pub_config_domain_input(domain_input: &[u8]) -> DomainInput {
10231053
BoundedVec::try_from(domain_input.to_vec()).expect("Invalid domain input.")
10241054
}
1055+
1056+
// pub(crate) fn get_mycelium_pk_input(mycelium_pk_input: &[u8]) -> MyceliumPkInput {
1057+
// BoundedVec::try_from(mycelium_pk_input.to_vec()).expect("Invalid mycelium pk input.")
1058+
// }

substrate-node/pallets/pallet-tfgrid/src/lib.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ pub mod pallet {
146146
// Concrete type for entity
147147
pub type TfgridEntity<T> = types::Entity<AccountIdOf<T>, CityNameOf<T>, CountryNameOf<T>>;
148148

149+
pub type MyceliumPkInput = BoundedVec<u8, ConstU32<{ types::MAX_PK_LENGTH }>>;
150+
149151
#[pallet::storage]
150152
#[pallet::getter(fn nodes)]
151153
pub type Nodes<T> = StorageMap<_, Blake2_128Concat, u32, TfgridNode<T>, OptionQuery>;
@@ -263,6 +265,16 @@ pub mod pallet {
263265
ValueQuery,
264266
>;
265267

268+
#[pallet::storage]
269+
#[pallet::getter(fn twin_by_mycelium_pk)]
270+
pub type TwinByMyceliumPk<T: Config> = StorageMap<
271+
_,
272+
Blake2_128Concat,
273+
MyceliumPkInput, // key is mycelium pk
274+
u32, // value is twin id
275+
OptionQuery, // returns None if pk not found
276+
>;
277+
266278
#[pallet::config]
267279
pub trait Config: frame_system::Config + pallet_timestamp::Config {
268280
type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
@@ -1238,5 +1250,45 @@ pub mod pallet {
12381250
// Deprecated! Use index 40 for next extrinsic
12391251
// #[pallet::call_index(39)]
12401252
// #[pallet::weight(<T as Config>::WeightInfo::set_node_gpu_status())]
1253+
1254+
#[pallet::call_index(40)]
1255+
#[pallet::weight(<T as Config>::WeightInfo::set_twin_mycelium_pk())]
1256+
pub fn set_twin_mycelium_pk(
1257+
origin: OriginFor<T>,
1258+
twin_id: u32,
1259+
mycelium_pk: MyceliumPkInput,
1260+
) -> DispatchResultWithPostInfo {
1261+
let account_id = ensure_signed(origin)?;
1262+
1263+
// Ensure the caller owns this twin
1264+
let twin = Twins::<T>::get(twin_id).ok_or(Error::<T>::TwinNotExists)?;
1265+
ensure!(twin.account_id == account_id, Error::<T>::UnauthorizedToUpdateTwin);
1266+
1267+
// Store the mapping
1268+
TwinByMyceliumPk::<T>::insert(&mycelium_pk, twin_id);
1269+
1270+
Ok(().into())
1271+
}
1272+
1273+
// #[pallet::call_index(41)]
1274+
// #[pallet::weight(<T as Config>::WeightInfo::get_twin_by_mycelium_pk())]
1275+
// pub fn get_twin_by_mycelium_pk(
1276+
// origin: OriginFor<T>,
1277+
// mycelium_pk: MyceliumPkInput,
1278+
// ) -> DispatchResultWithPostInfo {
1279+
// let _account_id = ensure_signed(origin)?;
1280+
1281+
// // Get twin ID from mycelium pk
1282+
// let twin_id = TwinByMyceliumPk::<T>::get(&mycelium_pk).ok_or(Error::<T>::TwinNotExists)?;
1283+
1284+
// // Get the full twin object
1285+
// let twin = Twins::<T>::get(twin_id).ok_or(Error::<T>::TwinNotExists)?;
1286+
1287+
// // For now, we'll just return success. In a real implementation, you might want to
1288+
// // emit an event or return the twin data in some way
1289+
// Self::deposit_event(Event::TwinStored(twin));
1290+
1291+
// Ok(().into())
1292+
// }
12411293
}
12421294
}

substrate-node/pallets/pallet-tfgrid/src/weights.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ pub trait WeightInfo {
6565
fn change_power_target() -> Weight;
6666
fn bond_twin_account() -> Weight;
6767
fn report_uptime_v2() -> Weight;
68+
fn set_twin_mycelium_pk() -> Weight;
69+
// fn get_twin_by_mycelium_pk() -> Weight;
6870
}
6971

7072
/// Weights for pallet_tfgrid using the Substrate node and recommended hardware.
@@ -548,6 +550,31 @@ impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
548550
Weight::from_parts(18_465_000, 3919)
549551
.saturating_add(T::DbWeight::get().reads(4_u64))
550552
}
553+
/// Storage: `TfgridModule::Twins` (r:1 w:0)
554+
/// Proof: `TfgridModule::Twins` (`max_values`: None, `max_size`: None, mode: `Measured`)
555+
/// Storage: `TfgridModule::TwinByMyceliumPk` (r:0 w:1)
556+
/// Proof: `TfgridModule::TwinByMyceliumPk` (`max_values`: None, `max_size`: None, mode: `Measured`)
557+
fn set_twin_mycelium_pk() -> Weight {
558+
// Proof Size summary in bytes:
559+
// Measured: `387`
560+
// Estimated: `3852`
561+
// Minimum execution time: 11_743_000 picoseconds.
562+
Weight::from_parts(12_053_000, 3852)
563+
.saturating_add(T::DbWeight::get().reads(1_u64))
564+
.saturating_add(T::DbWeight::get().writes(1_u64))
565+
}
566+
// / Storage: `TfgridModule::TwinByMyceliumPk` (r:1 w:0)
567+
// / Proof: `TfgridModule::TwinByMyceliumPk` (`max_values`: None, `max_size`: None, mode: `Measured`)
568+
// / Storage: `TfgridModule::Twins` (r:1 w:0)
569+
// / Proof: `TfgridModule::Twins` (`max_values`: None, `max_size`: None, mode: `Measured`)
570+
// fn get_twin_by_mycelium_pk() -> Weight {
571+
// // Proof Size summary in bytes:
572+
// // Measured: `387`
573+
// // Estimated: `3852`
574+
// // Minimum execution time: 11_743_000 picoseconds.
575+
// Weight::from_parts(12_053_000, 3852)
576+
// .saturating_add(T::DbWeight::get().reads(2_u64))
577+
// }
551578
}
552579

553580
// For backwards compatibility and tests
@@ -1030,4 +1057,29 @@ impl WeightInfo for () {
10301057
Weight::from_parts(18_465_000, 3919)
10311058
.saturating_add(RocksDbWeight::get().reads(4_u64))
10321059
}
1060+
/// Storage: `TfgridModule::Twins` (r:1 w:0)
1061+
/// Proof: `TfgridModule::Twins` (`max_values`: None, `max_size`: None, mode: `Measured`)
1062+
/// Storage: `TfgridModule::TwinByMyceliumPk` (r:0 w:1)
1063+
/// Proof: `TfgridModule::TwinByMyceliumPk` (`max_values`: None, `max_size`: None, mode: `Measured`)
1064+
fn set_twin_mycelium_pk() -> Weight {
1065+
// Proof Size summary in bytes:
1066+
// Measured: `387`
1067+
// Estimated: `3852`
1068+
// Minimum execution time: 11_743_000 picoseconds.
1069+
Weight::from_parts(12_053_000, 3852)
1070+
.saturating_add(RocksDbWeight::get().reads(1_u64))
1071+
.saturating_add(RocksDbWeight::get().writes(1_u64))
1072+
}
1073+
// / Storage: `TfgridModule::TwinByMyceliumPk` (r:1 w:0)
1074+
// / Proof: `TfgridModule::TwinByMyceliumPk` (`max_values`: None, `max_size`: None, mode: `Measured`)
1075+
// / Storage: `TfgridModule::Twins` (r:1 w:0)
1076+
// / Proof: `TfgridModule::Twins` (`max_values`: None, `max_size`: None, mode: `Measured`)
1077+
// fn get_twin_by_mycelium_pk() -> Weight {
1078+
// // Proof Size summary in bytes:
1079+
// // Measured: `387`
1080+
// // Estimated: `3852`
1081+
// // Minimum execution time: 11_743_000 picoseconds.
1082+
// Weight::from_parts(12_053_000, 3852)
1083+
// .saturating_add(RocksDbWeight::get().reads(2_u64))
1084+
// }
10331085
}

0 commit comments

Comments
 (0)