Share your account’s importance securely with a node and get rewarded.
Delegated harvesting enables accounts to receive rewards from creating new blocks without running a node. At the same time, it allows nodes to benefit from an account’s (possibly higher) importance score.
Note
Node owners have access to the node’s configuration so it’s more convenient for them to use Remote harvesting instead.
This guide explains how to manually activate delegated harvesting using the SDK or the CLI interface and is therefore intended for developers. Users should use the Desktop Wallet guide instead.
Required steps:
Delegate the main account (M) importance to a remote account (R) using an AccountKeyLinkTransaction.
Link the main account M to a VRF account (V) for randomized block production and account selection using a VrfKeyLinkTransaction.
Link the main account M to a node in order to harvest through that node using a NodeKeyLinkTransaction.
Request the node to add the remote account R as a harvester using a Persistent Delegation Request Transaction. Conversely, if the node configuration is accessible, the remote account’s private key can be set in the node configuration.
Please note that it is entirely up to the node to comply with the request. Some nodes can be asked for their current list of delegated harvesters but this information is not always available (see Verifying activation below).
Complete the sending mosaics and messages between two accounts guide to have a basic understanding of transactions.
Before you can activate delegated harvesting, you need the following items:
A Main account (M) with at least 10,000 symbol.xym
to be eligible and then some more to pay for transaction fees. The account also has to have an importance score greater than zero (this score is calculated every 12h). This is the account that will receive the harvesting fees. Keep its private key secret at all times.
A Remote account (R) that will act as a proxy between M and the node. This account must have never sent or received any transaction, and it cannot be involved in any transaction while it is a delegated account.
A VRF account (V) that has never sent or received any transactions. It is a regular account used to add randomness to the account selection process.
The node’s public TLS key. This is the key the node uses to authenticate data for transport over TLS and is typically provided by the node owner.
Refer to the Creating an account guide to know how to create new accounts if you need to.
Note
The following bash code snippets make use of symbol-cli and assume that the main account (M) is set as the default profile. Use the ‑‑profile
parameter if this is not the case.
Create an AccountKeyLinkTransaction to delegate M’s importance to R. Sign the transaction with M and announce it to the network.
const accountLinkTransaction = AccountKeyLinkTransaction.create(
Deadline.create(epochAdjustment),
remoteAccount.publicKey,
LinkAction.Link,
networkType,
UInt64.fromUint(2000000),
);
symbol-cli transaction accountkeylink \
--linked-public-key <REMOTE_PUBLIC_KEY> \
--action Link \
--sync
Create a VrfKeyLinkTransaction to link M to a VRF key. Sign the transaction with M and announce it to the network.
const vrfLinkTransaction = VrfKeyLinkTransaction.create(
Deadline.create(epochAdjustment),
vrfAccount.publicKey,
LinkAction.Link,
networkType,
UInt64.fromUint(2000000),
); // Absolute number
symbol-cli transaction vrfkeylink \
--linked-public-key <VRF_PUBLIC_KEY> \
--action Link \
--sync
Create a NodeKeyLinkTransaction to link M to a node’s TLS key. Sign the NodeKeyLinkTransaction with M and announce it to the network.
Note
The node’s public TLS key is typically provided by the node owner. However, Dual nodes (being both Peer and API nodes) running a version of the REST Gateway higher than 2.2.0 offer this information through the nodePublicKey
field of the node/info
REST endpoint.
Just point your browser to NODE_URL /node/info
.
const nodeLinkTransaction = NodeKeyLinkTransaction.create(
Deadline.create(epochAdjustment),
nodeAccount.publicKey,
LinkAction.Link,
networkType,
UInt64.fromUint(2000000),
); // Absolute number
symbol-cli transaction nodekeylink \
--linked-public-key <NODE_PUBLIC_TLS_KEY> \
--action Link \
--sync
Once the transactions are confirmed, the next step is to share R’s private key with the node. This can be done in one of two ways depending on whether you are the node owner and have access to the node’s configuration or not.
If you are the node owner, you simply need to set the remote account’s private signing key in the harvesterSigningPrivateKey
field in the Harvesting Configuration.
Otherwise, a Persistent Delegation Request Transaction must be used. As the private key will be shared in an encrypted message, only the node will be able to see it. Moreover, R does not own any mosaic.
The harvesting fees will be sent to M as it has established a link with the node through the NodeKeyLinkTransaction.
Sign the Persistent Delegation Request Transaction with M and announce it to the network.
const persistentDelegationRequestTransaction = PersistentDelegationRequestTransaction.createPersistentDelegationRequestTransaction(
Deadline.create(epochAdjustment),
remoteAccount.privateKey,
vrfAccount.privateKey,
nodeAccount.publicKey,
networkType,
UInt64.fromUint(2000000),
);
# Optionally use --profile announcer
symbol-cli transaction persistentharvestdelegation \
--remote-private-key <REMOTE_PRIVATE_KEY> \
--recipient-public-key <NODE_PUBLIC_TLS_KEY> \
--vrf-private-key <VRF_PRIVATE_KEY> \
--sync
Note
All the above transactions can be announced together in a single Aggregate Transaction.
If everything is successful, the node will receive the encrypted message through WebSockets. Once the node decrypts the private key of the potential delegated harvester, the node owner may add R as a delegated harvester if the following requirements are met:
The node permits delegated harvesting.
The node has harvesting slots available (See next section).
The remote account has never sent or received transactions before.
As the remote private key is saved on disk by the node, even if the node disconnects temporarily the persistent delegated harvesters will be reestablished once the node reconnects to the network.
Additionally, the use of an encrypted message creates a backup of the information for the nodes. If the disk containing the delegated keys becomes corrupted or destroyed, the node owner can still retrieve the data by querying the blockchain.
When requesting delegation through a Persistent Delegation Request Transaction instead of directly configuring the node, whether the node enables delegated harvesting depends entirely on the node and not on the network. It is entirely up to the node to comply with the request or even to lie about its state.
Therefore, there is no reliable way to know if your account has become a harvester or not (besides waiting to see if any blocks appear on the blockchain signed by your remote account and your main account starts collecting harvesting fees).
That said, nodes configured to act as Dual nodes (being both Peer and API nodes) can be queried for their current list of delegated harvesters. To reiterate, this information comes from the node and is not backed up by the blockchain, so take it with a grain of salt.
You can retrieve this list using the getUnlockedAccount
API endpoint (point your browser to NODE_URL /node/unlockedaccount
) or the Typescript SDK for example). It contains the public keys of all registered delegated harvesters in the node, so your remote account (R) public key should appear here.
By default a node can have up to 5 delegated harvesters (harvesting slots) and excess requests can be priorized as the node sees fit. This can be configured on the node through the maxUnlockedAccounts
and delegatePrioritizationPolicy
Harvesting Configuration.
Accounts with higher importance are selected more often to perform harvesting. Even if you successfully register as a delegated harvester with a node, you will not harvest any block (nor receive any fees) unless your importance score is high enough.
Importance score calculation does not happen continuously. By default, account importance scores are recalculated every 1440 blocks (about every 12 hours). See the importanceGrouping
property in the Configuring network properties guide.
Finally, as explained in Verifying activation above, announcing a Harvesting Delegation request does not guarantee being added as a delegated harvester. Nodes are free to comply with the request or even to lie about its status.