Pooling Protocol
Notes
- MMX addresses are encoded via bech32 string
- Hashes and signatures are encoded via little-endian upper-case hex string, without
0x
prefix - Account address = Payout address
Pool Server API
POST /partial
Endpoint to post a partial.
Content-Type: application/json
Payload: Object
height
: Block height the proof is forhash
: Message hash for signature (see below)contract
: Plot NFT addressaccount
: Payout address (can be multiple per NFT, first partial creates account)pool_url
: The base URL used to make this requestharvester
: Harvester name, usually hostnamelookup_time_ms
: Harvester lookup time (ms)proof
: Proof, can be Proof of Space or Proof of Stake (see below)farmer_sig
: Farmer signature based onhash
andproof.farmer_key
__type
:mmx.Partial
The proof
is an object as follows:
__type
: Proof type (alwaysmmx.ProofOfSpaceNFT
)score
: Proof scoreplot_id
: Plot IDchallenge
: challenge hash for this height and forkdifficulty
: Partial difficulty used when performing lookup (might be different than current setting)farmer_key
: Farmer Public Key
For proof.__type
== mmx.ProofOfSpaceNFT
the following additional fields will be present:
ksize
: Plot k-sizeseed
: Plot random seedproof_xs
: List of proof X values (256)contract
: Plot NFT contract address
Returns status 200 with application/json
object as follows:
error_code
: Integer error code (see below)error_message
: Message string
Example partial
TODO: update
{ __type: 'mmx.Partial', account: 'mmx1kx69pm743rshqac5lgcstlr8nq4t93hzm8gumkkxmp5y9fglnkes6ve09z', challenge: 'CA98DB6504B2C85D876BEC1881F41E805D49FDE33DFE548A26C3277CFAE7EFF9', contract: 'mmx19hxc7mfkdalx0khe5nr4r50t338z8sg4avn7vqu7ts4mpkxeg0lqhesvzl', farmer_sig: '3CDCD57B151254835100F47F16834F91ED87838F5C68E113F236FD88169133643D06A4D50B6FB96859BECB73A73CE0E449262717B9907E70F05659F487C14F4B', harvester: 'prime', hash: 'B7269935091572E1004B48C327EEF2070DA0176A94AE2129AD8E68A9059FD95F', height: 845490, lookup_time_ms: 82, difficulty: 1, pool_url: 'http://localhost:8080', proof: { __type: 'mmx.ProofOfSpaceNFT', contract: 'mmx19hxc7mfkdalx0khe5nr4r50t338z8sg4avn7vqu7ts4mpkxeg0lqhesvzl', farmer_key: '027D7562FB5A8967E57A22F876302F75BA3AE3980607FB32E4439681F820AE398F', ksize: 26, plot_id: '22F0CA184633E07F32C5289B0ACF39597637CD6685D3CD4E7CD87CD56FAF8761', proof_xs: [ 61796699, 13346431, 24374059, 22439072, 65129000, 58802027, ... 250 more items ], score: 25993, seed: '091B11F9A066A9120AAD4BF8D30D933E4CED2EB3BF2CCA1DA72D8BA8E68BDA96' }}
GET /difficulty
Returns current partial difficulty. If farmer account does not exist yet, it should return a default starting difficulty.
Will be polled by farmers every 300 sec by default.
Query parameters:
id
: Farmer account address (payout address)
Always returns status 200 with application/json
object as follows:
difficulty
: Integer value
POST /set_difficulty
Endpoint for custom partial difficulty settings. Support for this is optional.
Partial difficulty is set per account (ie. payout address), not per plot NFT.
Content-Type: application/json
Payload: Object
account
: Account addresstype
:static
ordynamic
value
: Static difficulty value, or partials per hour (integer) in case of dynamictime
: POSIX timestamp in secondspublic_key
: Public key for account addresssignature
: Signature for message andpublic_key
Returns status 200 with application/json
object as follows:
error_code
: Integer error code (see below)error_message
: Message string
GET /pool/info
Returns pool information as application/json
object:
name
description
fee
: Pool fee (0 to 1, 1 = 100%)logo_path
: Relative path for logo image, starting with/
.protocol_version
:1
pool_target
: Plot NFT target addressmin_difficulty
: Lowest partial difficulty that is supported
GET /pool/stats
Returns pool statistics as application/json
object:
estimated_space
: Estimated pool size in TBpartial_rate
: Partials / hourfarmers
: Number of active farmers
GET /account/info
Query parameters:
id
: Farmer account address (payout address)
Returns account info as application/json
object:
balance
: Current unpaid balance [MMX]total_paid
: Total amount paid out so far [MMX]difficulty
: Partial difficultypool_share
: Relative farm size to pool (0 to 1)partial_rate
: Partials / hourblocks_found
: Number of blocks farmedestimated_space
: Estimated farm size in TB
Node API
POST /wapi/node/verify_partial
Endpoint to verify a partial, optionally with plot NFT verification.
Note: Partials should be verfied after a certain delay, for example once the height of the partial has been reached on-chain. Partials are computed 6 blocks in advance, so waiting until the partial’s height has been reached will give 6 blocks security. Even in case of a re-org larger than 6 blocks, the chance a partial won’t be valid anymore is only ~5%.
Content-Type: application/json
Payload: Object
partial
: The same object as was received by the pool via POST/partial
.pool_target
: Expected plot NFT target address (optional)- When specified will verify plot NFT is locked to given target address at current blockchain height.
Returns status 200 with application/json
object as follows:
error_code
: Integer error code (see below)error_message
: Message string
When the node is not synced will return status 500 with error text.
POST /wapi/node/verify_plot_nft_target
Endpoint to verify that a plot NFT is locked and pointed to the given target address at the current blockchain height.
Content-Type: application/json
Payload: Object
address
: Plot NFT addresspool_target
: Expected plot NFT target address
Returns status 200 with application/json
object as follows:
error_code
: Integer error code (see below)error_message
: Message string
When the node is not synced will return status 500 with error text.
Message hash algorithm
A string is generated for JSON objects as follows:
- First the
__type
field is added, followed with/
- Then for each field in the specified order:
- The field name is added, followed with a
:
- The field value is added (floating point values are floored first)
- The field name is added, followed with a
- For any nested objects, the same scheme is followed.
The final string is hashed via SHA2-256
.
Error Codes
Error codes are transferred as strings in JSON:
NONE
: No errorINVALID_PARTIAL
DUPLICATE_PARTIAL
PARTIAL_TOO_LATE
PARTIAL_NOT_GOOD_ENOUGH
CHALLENGE_REVERTED
CHALLENGE_NOT_FOUND
INVALID_PROOF
INVALID_DIFFICULTY
INVALID_SIGNATURE
INVALID_CONTRACT
INVALID_AUTH_KEY
INVALID_ACCOUNT
INVALID_TIMESTAMP
POOL_LOST_SYNC
SERVER_ERROR