As part of delegation program, nodes are to upload some proof of their activity. These proofs are to be accumulated and utilized for scoring. This service provides the nodes with a way to siubmit their data for score calculation.
MAX_SUBMIT_PAYLOAD_SIZE
: max size (in bytes) of thePOST /submit
payloadREQUESTS_PER_IP_HOURLY
: max amount of requests per hour per IP addressREQUESTS_PER_PK_HOURLY
: max amount of requests per hour per public keysubmitter
- Node submits a payload to the Service using
POST /submit
- Server saves the request
- Server replies with status
ok
and HTTP 200 if payload is correct and some other HTTP code otherwise
Backend Service is a web server that exposes the following entrypoints:
-
POST /submit
to submit a JSON payload containing the following data:{ "data": { "peer_id": "<base58-encoded peer id of the node from libp2p library>", "block": "<base64-encoded bytes of the latest known block>", "created_at": "<current time>", // Optional argument "snark_work": "<base64-encoded snark work blob>" }, "submitter": "<base58check-encoded public key of the submitter>", "sig": "<base64-encoded signature of `data` contents made with public key submitter above>" }
- Mina's signature scheme (as described in https://github.com/MinaProtocol/c-reference-signer) is to be used
- Time is represented according to
RFC-3339
with mandatoryZ
suffix (i.e. in UTC), like:1985-04-12T23:20:50.52Z
- Payload for signing is to be made as the following JSON (it's important that its fields are in lexicographical order and if no
snark_work
is provided, field is omitted):block
: Base64 representation of ablock
field from payloadcreated_at
: same as indata
peer_id
: same as indata
snark_work
: same as indata
(omitted ifnull
or""
)
- There are three possible responses:
400 Bad Request
with{"error": "<machine-readable description of an error>"}
payload when the input is considered malformed401 Unauthorized
when public keysubmitter
is not on the list of allowed keys or the signature is invalid411 Length Required
when no length header is provided413 Payload Too Large
when payload exceedsMAX_SUBMIT_PAYLOAD_SIZE
constant429 Too Many Requests
when submission from public keysubmitter
is rejected due to rate-limiting policy500 Internal Server Error
with{"error": "<machine-readable description of an error>"}
payload for any other server error503 Service Unavailable
when IP-based rate-limiting prohibits the request200
with{"status": "ok"}
Cloud storage has the following structure:
submissions
<submitted_at_date>/<submitted_at>-<submitter>.json
- Path contents:
submitted_at_date
with server's date (of the time of submission) in formatYYYY-MM-DD
submitted_at
with server's timestamp (of the time of submission) in RFC-3339submitter
is base58check-encoded submitter's public key
- File contents:
remote_addr
with theip:port
address from which request has comepeer_id
(as in user's JSON submission)snark_work
(optional, as in user's JSON submission)submitter
is base58check-encoded submitter's public keycreated_at
is UTC-basedRFC-3339
-encodedblock_hash
is base58check-encoded hash of a block
- Path contents:
blocks
<block-hash>.dat
- Contains raw block
All endpoints are guarded with Nginx which acts as a:
- HTTPS proxy
- Rate-limiter (by IP address) configured with
REQUESTS_PER_IP_HOURLY
On receiving payload on /submit
, we perform the following validation:
- Content size doesn't exceed the limit (before reading the data)
- Payload is a JSON of valid format (also check the sizes and formats of
create_at
andblock_hash
) |NOW() - created_at| < 1 min
submitter
is on the listallowed
of whitelisted public keyssig
is a valid signature ofdata
w.r.t.submitter
public key- Amount of requests by
submitter
in the last hour is not exceedingREQUESTS_PER_PK_HOURLY
After receiving payload on /submit
, we update in-memory public key rate-limiting state and save the contents of block
field as blocks/<block_hash>.dat
.