getClosestNodes
getClosestNodes
is a useful function that returns a list of the closest node IDs to the specified hash
. The function takes in two parameters:
hash
is astring
that represents the hash with which to compare the node IDs.count
is anumber
that represents the number of node IDs to return in the list.
This function can be extremely useful when you need the network to automatically change the state in some way on its own. This function allows you to grab the IDs of the closest nodes to a given hash, so if you seemingly randomize the hash, you can have the network do things like randomly choose 1 node to submit a transaction.
We found this useful if you're building a confirmation email transaction. Since Shardus transactions get routed to shards and there's always going to be more than 1 node per shard, we need a way to have only 1 node actually send the verification email, because we don't want to spam the user. For security reasons, it's better if this node is chosen at random as well.
This can be accomplished by using getClosestNodes
. So, imagine 5 nodes per shard, and destructuring the first (closest) item in the list. Then we can check to see if we are the closest and continue executing the code. The closest node must also gossip the hash of the verification number so that when the next transaction validation occurs, the other nodes will know what to verify with.
switch (tx.type) {
case 'email': {
const source: UserAccount = wrappedStates[tx.signedTx.from].data
const nodeId = dapp.getNodeId()
const { address } = dapp.getNode(nodeId)
const [closest] = dapp.getClosestNodes(tx.signedTx.from, 5)
if (nodeId === closest) {
const baseNumber = 99999
const randomNumber = Math.floor(Math.random() * 899999) + 1
const verificationNumber = baseNumber + randomNumber
axios.post('http://arimaa.com/mailAPI/index.cgi', {
from: 'liberdus.verify',
to: `${tx.email}`,
subject: 'Verify your email for liberdus',
message: `Please verify your email address by sending a "verify" transaction with the number: ${verificationNumber}`,
secret: 'some-secret',
})
dapp.put({
type: 'gossip_email_hash',
nodeId,
account: source.id,
from: address,
emailHash: tx.signedTx.emailHash,
verified: crypto.hash(`${verificationNumber}`),
timestamp: Date.now(),
})
}
dapp.log('Applied email tx', source)
break
}
}