Skip to content

map mycelium to twin identity #1037

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions clients/tfchain-client-go/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ type TwinEntityRemoved struct {
Topics []types.Hash
}

type MyceliumTwinUpdated struct {
Phase types.Phase
MyceliumPk []byte `json:"mycelium_pk"`
TwinId types.U32 `json:"twin_id"`
Topics []types.Hash
}

type TwinAccountBounded struct {
Phase types.Phase
Twin types.U32 `json:"twin_id"`
Expand Down Expand Up @@ -414,12 +421,13 @@ type EventRecords struct {
TfgridModule_EntityDeleted []EntityDeleted //nolint:stylecheck,golint

// twin events
TfgridModule_TwinStored []TwinStored //nolint:stylecheck,golint
TfgridModule_TwinUpdated []TwinStored //nolint:stylecheck,golint
TfgridModule_TwinDeleted []TwinDeleted //nolint:stylecheck,golint
TfgridModule_TwinEntityStored []TwinEntityStored //nolint:stylecheck,golint
TfgridModule_TwinEntityRemoved []TwinEntityRemoved //nolint:stylecheck,golint
TfgridModule_TwinAccountBounded []TwinAccountBounded //nolint:stylecheck,golint
TfgridModule_TwinStored []TwinStored //nolint:stylecheck,golint
TfgridModule_TwinUpdated []TwinStored //nolint:stylecheck,golint
TfgridModule_TwinDeleted []TwinDeleted //nolint:stylecheck,golint
TfgridModule_TwinEntityStored []TwinEntityStored //nolint:stylecheck,golint
TfgridModule_TwinEntityRemoved []TwinEntityRemoved //nolint:stylecheck,golint
TfgridModule_TwinAccountBounded []TwinAccountBounded //nolint:stylecheck,golint
TfgridModule_MyceliumTwinUpdated []MyceliumTwinUpdated //nolint:stylecheck,golint

// policy events
TfgridModule_PricingPolicyStored []PricingPolicyStored //nolint:stylecheck,golint
Expand Down
66 changes: 66 additions & 0 deletions clients/tfchain-client-go/twin.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,69 @@ func (s *Substrate) UpdateTwin(identity Identity, relay string, pk []byte) (uint

return s.GetTwinByPubKey(identity.PublicKey())
}

// SetMyceliumTwin sets the mycelium public key mapping for a twin
//
// Parameters:
// - identity: The identity for signing the transaction
// - myceliumPK: The mycelium public key (hex string), ip will work as well
// - twinID: The twin ID to map to the mycelium public key
//
// Returns:
// - error: nil on success, error on failure
func (s *Substrate) SetMyceliumTwin(identity Identity, myceliumPK string, twinID uint32) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add tests to the client

cl, meta, err := s.GetClient()
if err != nil {
return err
}

bytes := []byte(myceliumPK)
c, err := types.NewCall(meta, "TfgridModule.set_mycelium_twin", bytes, twinID)
if err != nil {
return errors.Wrap(err, "failed to create call")
}

if _, err := s.Call(cl, meta, identity, c); err != nil {
return errors.Wrap(err, "failed to set mycelium twin")
}

return nil
}

// GetMyceliumTwin gets the twin ID associated with a mycelium public key
//
// Parameters:
// - myceliumPK: The mycelium public key (hex string)
//
// Returns:
// - uint32: The twin ID associated with the mycelium public key
// - error: nil on success, error on failure (including ErrNotFound if no twin is found)
func (s *Substrate) GetMyceliumTwin(myceliumPK string) (uint32, error) {
cl, meta, err := s.GetClient()
if err != nil {
return 0, err
}

// must use encode to convert byte slice to encoded format
bytes, err := Encode(myceliumPK)
if err != nil {
return 0, errors.Wrap(err, "substrate: encoding error building query arguments")
}

key, err := types.CreateStorageKey(meta, "TfgridModule", "MyceliumTwin", bytes, nil)
if err != nil {
return 0, errors.Wrap(err, "failed to create substrate query key")
}

var twinID types.U32
ok, err := cl.RPC.State.GetStorageLatest(key, &twinID)
if err != nil {
return 0, errors.Wrap(err, "failed to lookup twin by mycelium pk")
}

if !ok || twinID == 0 {
return 0, errors.Wrap(ErrNotFound, "twin not found for mycelium pk")
}

return uint32(twinID), nil
}
23 changes: 22 additions & 1 deletion clients/tfchain-client-js/lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ const {
} = require('./entity')
const {
createTwin, getTwin, getTwinIdByAccountId, updateTwin,
deleteTwin, addTwinEntity, deleteTwinEntity, listTwins
deleteTwin, addTwinEntity, deleteTwinEntity, listTwins,
setMyceliumTwin, getMyceliumTwin
} = require('./twin')
const {
createFarm, getFarm, deleteFarm,
Expand Down Expand Up @@ -161,6 +162,26 @@ class Client {
return deleteTwinEntity(this, twinID, entityID, callback)
}

/**
* Sets the mycelium public key mapping for a twin
* @param {string} myceliumPk - The mycelium public key (hex string)
* @param {number} twinId - The twin ID to map to the mycelium public key
* @param {Function} callback - Optional callback function
* @returns {Promise} Transaction result
*/
async setMyceliumTwin(myceliumPk, twinId, callback) {
return setMyceliumTwin(this, myceliumPk, twinId, callback)
}

/**
* Gets the twin ID associated with a mycelium public key
* @param {string} myceliumPk - The mycelium public key (hex string)
* @returns {Promise<number>} The twin ID associated with the mycelium public key
*/
async getMyceliumTwin(myceliumPk) {
return getMyceliumTwin(this, myceliumPk)
}

async createFarm(name, certificationType, publicIPs, callback) {
return createFarm(this, name, certificationType, publicIPs, callback)
}
Expand Down
38 changes: 37 additions & 1 deletion clients/tfchain-client-js/lib/twin.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,40 @@ async function deleteTwin (self, id, callback) {
.signAndSend(self.key, { nonce }, callback)
}

/**
* Sets the mycelium public key mapping for a twin
* @param {Object} self - The client instance
* @param {string} myceliumPk - The mycelium public key (hex string)
* @param {number} twinId - The twin ID to map to the mycelium public key
* @param {Function} callback - Optional callback function
* @returns {Promise} Transaction result
*/
async function setMyceliumTwin (self, myceliumPk, twinId, callback) {
const setMyceliumTx = self.api.tx.tfgridModule.setMyceliumTwin(myceliumPk, twinId)
const nonce = await self.api.rpc.system.accountNextIndex(self.address)

return setMyceliumTx.signAndSend(self.key, { nonce }, callback)
}

/**
* Gets the twin ID associated with a mycelium public key
* @param {Object} self - The client instance
* @param {string} myceliumPk - The mycelium public key (hex string)
* @returns {Promise<number>} The twin ID associated with the mycelium public key
* @throws {Error} If no twin is found for the given mycelium public key
*/
async function getMyceliumTwin (self, myceliumPk) {
// Get the twin ID from the mycelium PK mapping using the storage getter
const twinIdResult = await self.api.query.tfgridModule.myceliumTwin(myceliumPk)
const twinId = twinIdResult.toJSON()

if (!twinId || twinId === 0) {
throw Error(`Couldn't find a twin for mycelium pk: ${myceliumPk}`)
}

return twinId
}

module.exports = {
createTwin,
updateTwin,
Expand All @@ -100,5 +134,7 @@ module.exports = {
deleteTwin,
addTwinEntity,
deleteTwinEntity,
listTwins
listTwins,
setMyceliumTwin,
getMyceliumTwin
}
32 changes: 32 additions & 0 deletions clients/tfchain-client-rs/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,38 @@ impl Client {
current::get_twin_id_by_account(self, account).await
}

/// Sets the mycelium public key mapping for a twin
///
/// # Arguments
/// * `kp` - The keypair for signing the transaction
/// * `mycelium_pk` - The mycelium public key (as bytes)
/// * `twin_id` - The twin ID to map to the mycelium public key
///
/// # Returns
/// * `Result<Hash, Error>` - The block hash on success
pub async fn set_mycelium_twin(
&self,
kp: &KeyPair,
mycelium_pk: Vec<u8>,
twin_id: u32,
) -> Result<Hash, Error> {
current::set_mycelium_twin(self, kp, mycelium_pk, twin_id).await
}

/// Gets the twin ID associated with a mycelium public key
///
/// # Arguments
/// * `mycelium_pk` - The mycelium public key (as bytes)
///
/// # Returns
/// * `Result<Option<u32>, Error>` - The twin ID if found, None otherwise
pub async fn get_mycelium_twin(
&self,
mycelium_pk: Vec<u8>,
) -> Result<Option<u32>, Error> {
current::get_mycelium_twin(self, mycelium_pk).await
}

pub async fn get_farm_by_id(&self, id: u32) -> Result<Option<Farm>, Error> {
current::get_farm_by_id(self, id).await
}
Expand Down
40 changes: 40 additions & 0 deletions clients/tfchain-client-rs/src/runtimes/current.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,43 @@ pub async fn get_balance(
.fetch(&current::storage().system().account(account))
.await?)
}

pub async fn set_mycelium_twin(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are updating the rs client, you need to re-generate the client scale file

cl: &Client,
kp: &KeyPair,
mycelium_pk: Vec<u8>,
twin_id: u32,
) -> Result<H256, Error> {
let set_mycelium_tx = current::tx().tfgrid_module().set_mycelium_twin(
BoundedVec(mycelium_pk),
twin_id,
);

let signer = kp.signer();

let set_mycelium = cl
.api
.tx()
.sign_and_submit_then_watch_default(&set_mycelium_tx, &signer)
.await?
.wait_for_finalized_success()
.await?;

Ok(set_mycelium.block_hash())
}

pub async fn get_mycelium_twin(
cl: &Client,
mycelium_pk: Vec<u8>,
) -> Result<Option<u32>, Error> {
// Query the storage directly using the mycelium pk to get twin ID
let twin_id = cl
.api
.storage()
.at_latest()
.await?
.fetch(&current::storage().tfgrid_module().mycelium_twin(BoundedVec(mycelium_pk)))
.await?;

Ok(twin_id)
}
32 changes: 32 additions & 0 deletions scripts/activate/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module github.com/threefoldtech/tfchain/activate

go 1.21

require github.com/threefoldtech/tfchain/clients/tfchain-client-go v0.0.0-00010101000000-000000000000

require (
github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/centrifuge/go-substrate-rpc-client/v4 v4.0.12 // indirect
github.com/cosmos/go-bip39 v1.0.0 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/base58 v1.0.4 // indirect
github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect
github.com/ethereum/go-ethereum v1.10.20 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/gtank/merlin v0.1.1 // indirect
github.com/gtank/ristretto255 v0.1.2 // indirect
github.com/jbenet/go-base58 v0.0.0-20150317085156-6237cf65f3a6 // indirect
github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b // indirect
github.com/pierrec/xxHash v0.1.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rs/cors v1.8.2 // indirect
github.com/rs/zerolog v1.26.0 // indirect
github.com/vedhavyas/go-subkey v1.0.3 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/sys v0.6.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
)

replace github.com/threefoldtech/tfchain/clients/tfchain-client-go => ../../clients/tfchain-client-go
Loading