Grid sporks
After 0.0.8. The storage spork, type 1030, with its REST resource and
gridspork-getandgridspork-setsupport, is on themasterbranch and not in release 0.0.8. So are theblock,cliffandpercentfields of a vesting schedule, the ledger blacklist and ledger fee sporks, and the mint storage entries that name a ledger account. Release 0.0.8 has the mint storage, mint supply, vesting storage and statistics key sporks, and all of the co-signing described below.
A grid spork is a small, signed settings record that every node on the Unigrid network holds and passes on to its peers. Sporks let the network’s key holders change shared parameters, such as the maximum coin supply or the rules for network storage, on every node at once, without a software release and without a consensus round. A node accepts a change only if two different trusted keys signed it, so no single key can alter the network on its own.
What a spork holds
Each spork has a type, a current value, the previous value, a timestamp for each and the signatures that authorise it. The previous value is always a full copy of the value it replaced, never a difference. A node keeps at most one spork of each type. A mint storage spork holds at most 16,384 entries, a vesting storage spork at most 4,096 schedules, and a signature history at most 4,096 entries.
| Type | Id | What it carries | A change is |
|---|---|---|---|
| Mint storage | 1000 | Amounts credited to an address at a chain height | A grow: adds or replaces entries |
| Mint supply | 1010 | The network’s maximum supply | A set: replaces the value |
| Vesting storage | 1020 | Vesting schedules per address | A grow: adds or replaces an address |
| Storage | 1030 | The parameters of Network storage | A set: replaces the value |
| Statistics public key | 2001 | A public key held as text | Cannot be changed from Hedgehog |
The Ledger adds two more, the ledger blacklist (1040) and the ledger fee (1050), and gives the
mint sporks a use, see Ledger sporks. The upcoming socks-proxy branch uses the
id 1040 for the communication spork instead, which switches on the SOCKS proxy.
A set replaces the whole value. A grow starts from the value already stored, or from the value of a proposal still waiting for its second signature, so several changes can go into one co-signature. No change can remove an entry.
Mint storage (1000)
Holds amounts to be credited later: a map from an address and a block height of the legacy chain to an
amount of coins. One entry credits that amount to the address at that height. The legacy chain does not
mint these amounts, so Hedgehog adds those whose height lies above the current chain height to the
balance that /bootstrap/address reports, see Legacy chain snapshot.
The Ledger has no block heights, so it turns each height into a time: the time of the last block of the snapshot plus one minute for every height after it. It mints the amount when that time comes. Entries at or below the snapshot’s last height are already in the snapshot balances and are never minted again. An entry may also name a ledger account, with a time in seconds in place of the height, see Ledger sporks.
An entry with the same address and height as an existing one replaces its amount.
Read it with gridspork-get mint-storage. Propose an entry with
gridspork-grow mint-storage --address <address> --height <height> -D <amount>, with a board key in -k,
--key-file or $HEDGEHOG_BOARD_KEY; the command signs the next version on the machine and hands it to
the node in wire form. GET /gridspork/mint-storage/{address}/{height} reads one entry back. No JSON
request changes a spork.
Mint supply (1010)
Holds one number, the maximum coin supply, which is zero until a value is set. Hedgehog stores and
distributes it and shows it in GET /gridspork, and the Ledger mints nothing beyond it. Release
0.0.8 enforces nothing of it. It is the only spork of a release with the governed flag, which is meant to
send a change to a vote of the network. Nothing checks that flag yet.
Read it with gridspork-get mint-supply. Propose a value with
gridspork-set mint-supply -D <number> and a board key; the command signs it on the machine and hands it to
the node in wire form. No JSON request changes a spork.
Vesting storage (1020)
Holds one vesting schedule per address. A schedule has these fields:
| Field | Meaning |
|---|---|
amount |
The amount that vests; can be empty |
start |
When the schedule starts |
duration |
How long it runs |
parts |
The number of parts it is divided into |
cliff, percent, block |
Stored with the schedule; Hedgehog gives them no meaning (after 0.0.8) |
Hedgehog stores and distributes the schedules and calculates no releases from them. Proposing a schedule
for an address replaces the schedule that address already has. No command sets this spork: it can be
submitted only in wire form, by a program that builds and signs the spork itself. Read it with
GET /gridspork/vesting-storage or GET /gridspork/vesting-storage/{address}.
Storage (1030)
Holds the parameters of Network storage and Erasure coding. Storage stays switched off on a node until a valid storage spork has been accepted. The values below are the defaults of a new proposal.
| Parameter | Default | Allowed | What it sets |
|---|---|---|---|
maxBytesPerNode |
10 GiB | 0 or more | Disk quota of a gridnode |
chunkSize |
1 MiB | A multiple of fragmentSize, large enough for its tag and manifest |
Size of an encrypted chunk |
fragmentSize |
64 KiB | Above 0 | Size of a fragment |
maxOuterDataChunks |
32 | 1 to 255 | Data chunks in a stripe |
outerParityPercent |
50 | 0 to 200 | Parity chunks of a stripe, as a percentage of its data chunks |
innerParityPercent |
50 | 0 to 200 | Parity fragments of a chunk; 16 data and 8 parity make the 24 guaranteed fragments |
maxParityPercent |
100 | innerParityPercent to 25500 |
Upper bound on the fragments of a chunk |
repairIntervalMinutes |
60 | 1 or more | Length of a repair epoch |
repairThresholdPercent |
50 | 1 to 100 | Share of the parity fragments that must be missing before repair starts |
tombstoneDays |
30 | 1 to 65535 | How long a delete is remembered |
manifestCopies |
3 | 1 to 16 | Copies of the manifest written per upload |
placementSlack |
8 | 0 to 255 | Extra gridnodes ranked beyond the fragments of a chunk |
extraPoolPercent |
20 | 0 to 90 | Share of the quota that the non-guaranteed fragments may use |
The stripe and chunk limits also require that data and parity together stay within 255 chunks, and the fragments of a chunk within 255 fragments. The REST interface answers 400 with the reason when a proposal breaks a rule. A node does not validate a value that arrives from a peer, but it keeps storage switched off while its stored value is invalid.
Read it with gridspork-get storage. Propose a value with gridspork-set storage -D '<json>' and a board
key; the command prints the stored and proposed data, signs on the machine and prints the answer, such as
202 Accepted and the proposal with its digest. No JSON request changes a spork.
Statistics public key (2001)
Holds a public key as text, empty by default, with no format defined. Nothing in Hedgehog reads it. It has
no REST resource or CLI command, and Hedgehog never creates a new version of it, so it exists on a node
only when it arrives from a peer or is already in spork.db. It is left out of the periodic publish
described below.
Who may change a spork
Trust comes from a short list of public keys, the network keys. The default of the --network-keys
option is the four board keys of Stiftelsen The Unigrid Foundation, and an operator can override it on
the command line. Three older foundation keys are kept as retired keys: they approve nothing, but they
let a spork’s history name who signed earlier versions. The signing commands read the
same lists: --network-keys tells them which public keys are the board’s, and --retired-network-keys
which older keys count in a signature history. A private network passes its own lists to its nodes and to
every signing command.
Signatures use ECDSA with SHA-512 on the P-521 curve. A change needs two of them, from different network keys, and both cover exactly the same bytes: the type, flags, both timestamps, the current and previous values and the signature history described below. Those bytes are the spork’s own wire encoding, so a node that receives a spork from a peer checks exactly what the signer signed. A change to the governed mint supply spork may instead be put to a vote of the network; that path is not in Hedgehog yet.
An incoming spork is compared with the stored one first, so a spork that is not newer costs no signature check. One peer may have one spork of a type checked a second, and all peers together at most 32 a second for that type. A spork that is accepted gives its check back, so a peer that sends several genuine sporks in a row has each of them checked.
Co-signing a change
A change takes two board members. The first signs a proposal. The second, using a different board key, co-signs it by its digest, and only then does the change become an accepted spork. The digest is the SHA-512 of the bytes both signatures cover, written as 128 lower-case hex characters, so it names exactly one version of one change. When a later version replaces the accepted spork, its signature history records both signers.
The board member signs on their own machine. gridspork-set, gridspork-grow, gridspork-cosign and
gridspork-renew read what the node holds in the wire form peers exchange, check it, show what the
change sets, sign on this machine and hand the signed spork back in the same form. The board key never
leaves the machine, and no message repeats it. The node checks the signatures as it checks those of a
spork from a peer. The key comes from exactly one of three sources:
| Source | How |
|---|---|
-k <hex>, --key <hex> |
The private board key on the command line, where other users of the machine can read it in the list of processes |
--key-file <path> |
A regular file that holds the board key in hex and that only its owner can read; on a file system with POSIX permissions a file that a group or others hold any permission on is refused, with chmod 600 named as the remedy |
$HEDGEHOG_BOARD_KEY |
The environment |
A missing key, two sources at once, a file that cannot be read as a key, or a key that is not a current board
key ends the command with exit code 2 and the usage, before the node is contacted. A retired key signs
nothing. On a network with keys of its own, --network-keys and --retired-network-keys tell the command
which public keys are the board’s.
sequenceDiagram
participant A as Board member A
participant NA as Node of A
participant P as Other nodes
participant NB as Node of B
participant B as Board member B
A->>NA: read the stored spork and the pending proposal
A->>A: check, show, sign with key A
A->>NA: hand back the signed spork
NA-->>A: held as a proposal, with its digest
NA->>P: publish the proposal
P->>NB: pass on the proposal
Note over NA,NB: every node holds it for up to 60 minutes
A-->>B: send the digest
B->>NB: read the proposal in wire form
B->>B: check, show, co-sign with key B
B->>NB: hand back the co-signed spork
NB->>NB: check both signatures and the history, store
NB->>P: publish the accepted spork
P->>P: check, store and pass on
The steps
- Member A proposes the change on A’s node, with the command for the spork type, for example
hedgehog cli gridspork-set mint-supply -D 1000000000 -k <key of A>. The command reads what the node holds, prints the stored head and the stored and proposed data in full, signs, and hands the spork back. The answer is202 Acceptedand the proposal, with itsdigestandexpires. - A sends B the digest and the value they agreed, over a channel they trust.
- B runs
hedgehog cli gridspork-pendingon B’s node and comparestypeanddatawith what was agreed, andsignerwith A’s public key. Nothing else checks the value: the node checks the keys and that the data can be acted on, not what was agreed. If the list is empty, the proposal has not reached B’s node yet. Nodes publish their proposals every three minutes. - B co-signs within 60 minutes of A’s proposal:
hedgehog cli gridspork-cosign -k <key of B> <digest>. A digest is 128 lower-case hex characters; anything else ends the command with exit code 2 and the usage, before the node is asked. The command prints the proposal, the stored head and both data sets, signs here and hands the result back. It takes several digests and tries each one, even after an error. - Both check the result with
hedgehog cli gridspork-get <type>andhedgehog cli gridspork-log.
What the command checks before it signs
A node hands out what it holds, and anything between the node and this machine can have changed it, so the command checks it first and sends nothing when it fails:
| Check | Message |
|---|---|
| The stored spork is signed and co-signed by two known keys, retired ones among them, or carries the single signature of a release 0.0.7 build, with a valid history | The <TYPE> spork that the node holds is not one that board keys signed, so nothing is signed on top of it |
| The stored spork is not stamped more than 2 minutes ahead | The <TYPE> spork that the node holds is stamped ahead of the clock of this machine, made at <time>, so nothing is signed on top of it |
| The proposal is signed by a current board key and made over the stored spork as its next version or its renewal | The <TYPE> proposal that the node waits on is not one that a current board key made from the spork it holds, so nothing is signed on top of it |
| The proposal is at most 60 minutes old and not more than 2 minutes ahead | The <TYPE> proposal that the node waits on was made at <time>, longer ago than a proposal waits, so nothing is signed on top of it, or the same with stamped ahead of the clock of this machine in place of longer ago than a proposal waits |
The command prints the stored head, the stored data and the proposed data in full before it signs.
gridspork-set and gridspork-grow print a failed check as Nothing was signed: <message> and other
failures as The spork was not proposed: <message>; gridspork-cosign prints
Co-signing <digest> refused: <message>, and gridspork-renew prints
Renewing refused, nothing was proposed: <message>.
When co-signing fails
| Message | Cause | What to do |
|---|---|---|
The board key is not one of the current board keys of the network (see --network-keys) |
The key is not a current board key, or is malformed | Use a current board key; a retired key signs nothing |
No spork awaits a co-signature under <digest> |
The digest is unknown, the proposal expired, or it was already co-signed | Check gridspork-pending and gridspork-get <type>; ask A to propose again |
Co-signing <digest> refused: A second, different network key has to co-sign the spork |
B used A’s key | A different board member must co-sign |
The node answered <digest> with another spork, which was not co-signed |
The node holds no proposal under the digest, or hands out another one | Read gridspork-pending again; the proposal may have been replaced |
Co-signing <digest> refused: The spork does not follow on the stored spork and the proposal held |
The stored spork moved on, for example because a newer one was stored | Read the stored spork, then ask A to propose again |
A refused co-signature leaves the proposal pending.
Good to know
- A node holds one proposal per type. A newer proposal replaces the older one on every node. A grow started while one is pending carries the pending entries forward, while a set replaces the pending value. Either way the digest changes, so take it from the newest answer.
- A proposal lives 60 minutes from its own timestamp, in memory only. It is dropped without notice when that time passes, and a node that restarts loses it. A proposal stamped more than two minutes ahead of a node’s clock is refused.
- Any node can hold the proposal, so B does not need A’s node. Each member works on their own node.
util key-signandutil key-validatesign and check arbitrary data with a key. They are not part of this flow.
Peers pass on only what they have not seen before, so a spork spreads through the network and then stops. Nodes also publish their stored sporks, except the statistics key, to each peer every three minutes and whenever a connection comes up, which is how a node that was offline, or is new, catches up. The transport is described in Peer-to-peer network protocol.
One background thread saves spork.db every three minutes. A spork.db that cannot be read is moved
aside as spork.db.unreadable-<epoch seconds> and the node starts without it.
When two changes race
Two board members may propose different changes over the same stored version, and each proposal may be
co-signed on a node that has not yet seen the other. Both versions are then valid, made over the same
version with logs of the same length, so nodes hold one or the other for a moment. A proposal waits at
most 60 minutes for its co-signature, so both fall within the change window below, and every node ends up
with the newer one; the older change is lost and has to be proposed again over the newer version.
Members avoid a race by checking gridspork-pending before they propose and by changing one spork type
at a time.
The 60-minute window in the acceptance rules below exists because a node that shows a member an older version than the network holds could otherwise get a new version signed that drops the newest change. With the window, that works only within the hour after a change, and only when both members who sign use such a node.
Before signing, the signing commands print one line about the stored version:
Stored <TYPE> made at <time>, digest <16 hex>, signed by <16 hex> and <16 hex>, with (retired key)
after the key of a retired signer. gridspork-log on a second node shows the same time, digest and
signers, so a member can compare the two before signing.
Examples
The keys, address, digests and times below are made up, and output that repeats data is abbreviated. Both members work on their own node.
Mint storage. Member A wants 500 coins credited to a ledger account at 00:00 UTC on 1 December 2026. The account is 64 lower-case hex characters, and its entry names the time in epoch seconds. The command takes an ISO-8601 instant and turns it into 1796083200. An entry for an old-style Unigrid address names a height of the legacy chain instead, see Ledger sporks.
$ hedgehog cli gridspork-grow mint-storage --address 3f2a5b7c9d1e4f6081a2b3c4d5e6f708192a3b4c5d6e7f8091a2b3c4d5e6f708 \
--time 2026-12-01T00:00:00Z -D 500 -k <key of A>
Stored MINT_STORAGE data:
none
Proposed MINT_STORAGE data, signed now:
{
"mints" : {
"3f2a…f708/1796083200" : 500
}
}
202 Accepted
{
"type" : "MINT_STORAGE",
"timeStamp" : "2026-10-16T10:00:00Z",
"expires" : "2026-10-16T11:00:00Z",
"signer" : "<public key of A>",
"digest" : "9c41d7e00123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234567",
"data" : {
"mints" : {
"3f2a…f708/1796083200" : 500
}
}
}
A sends B the digest together with the account, the amount and the time. B checks that the pending time is the same and co-signs:
$ hedgehog cli gridspork-pending
$ hedgehog cli gridspork-cosign -k <key of B> \
9c41d7e00123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234567
Proposal 9c41d7e0…01234567 of MINT_STORAGE, made at 2026-10-16T10:00:00Z and signed by <public key of A>
Stored data:
none
Proposed data:
{
"mints" : {
"3f2a…f708/1796083200" : 500
}
}
Co-signed 9c41d7e0…01234567
Storage. Member A raises the quota of a gridnode from 10 GiB to 20 GiB. A set replaces the whole value, so the JSON carries every parameter:
$ hedgehog cli gridspork-set storage -k <key of A> -D '{
"maxBytesPerNode": 21474836480, "chunkSize": 1048576, "fragmentSize": 65536,
"outerParityPercent": 50, "maxOuterDataChunks": 32, "innerParityPercent": 50,
"maxParityPercent": 100, "repairIntervalMinutes": 60, "tombstoneDays": 30,
"manifestCopies": 3, "placementSlack": 8, "repairThresholdPercent": 50,
"extraPoolPercent": 20 }'
Stored STORAGE made at 2026-10-01T09:00:00Z, digest 7b1e04aa9d2c8f31, signed by 44f21a0c9b7e6d18 and 7c0e35b9a1d24f68
Stored STORAGE data:
{
"maxBytesPerNode" : 10737418240,
…
}
Proposed STORAGE data, signed now:
{
"maxBytesPerNode" : 21474836480,
…
}
202 Accepted
{
"type" : "STORAGE",
"timeStamp" : "2026-10-16T10:00:00Z",
"expires" : "2026-10-16T11:00:00Z",
"signer" : "<public key of A>",
"digest" : "e208ab550123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234567",
"data" : {
"maxBytesPerNode" : 21474836480,
…
}
}
B compares the proposed data with the agreed values before co-signing:
$ hedgehog cli gridspork-cosign -k <key of B> \
e208ab550123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01234567
Proposal e208ab55…01234567 of STORAGE, made at 2026-10-16T10:00:00Z and signed by <public key of A>
Stored STORAGE made at 2026-10-01T09:00:00Z, digest 7b1e04aa9d2c8f31, signed by 44f21a0c9b7e6d18 and 7c0e35b9a1d24f68
Stored data:
{
"maxBytesPerNode" : 10737418240,
…
}
Proposed data:
{
"maxBytesPerNode" : 21474836480,
…
}
Co-signed e208ab55…01234567
If B had co-signed with A’s key, the command would have printed
Co-signing <digest> refused: A second, different network key has to co-sign the spork.
When a replacement is accepted
Every version carries a signature history (log). When a node makes a new version over its stored one,
the stored version’s own signatures and digest become the next entry of the log. The entries are
chained, so removing or rewriting an earlier entry breaks the current signatures. The history can be
read with gridspork-log.
A node replaces the spork it holds only when the incoming version is signed by two different current network keys, its log begins with the stored log unchanged, every new history entry is validly signed by a known key, and one of these holds:
- the log is longer and goes on from the stored version: the entry right after the stored log is the stored version itself, with the same signatures and a digest equal to the SHA-512 of its signed bytes;
- the log is the same length and the version is a sibling, made over the same previous version with the same previous value and previous timestamp, and it is newer than the stored one.
A node that missed several versions still takes the newest, since its log goes on from the node’s version. A version built on another version than the one the node holds is refused, however long its log.
A sibling that keeps the data, a renewal, replaces the stored version at any time. A sibling that changes the data replaces it only while its timestamp is at most 60 minutes after the stored version’s.
Renewing after a key change
When the network keys change, sporks signed with the old keys stop verifying on upgraded nodes. A
one-off renewal re-signs everything a node holds with the new keys and keeps the history and the values.
The command takes its board key from -k, --key-file or $HEDGEHOG_BOARD_KEY, as the other signing
commands do, and signs on the machine. It follows the same two steps as any change:
- Member A runs
hedgehog cli gridspork-renew -k <key of A>. The command reads every spork the node holds, checks each stored head and prints all their data before it signs anything. It then signs every spork with its data unchanged and hands each one back; every answer is202 Acceptedand the proposal, with itsdigestandexpires. If any stored spork cannot be signed, nothing is proposed. If the node holds no spork, the command printsNo sporks to renew. - Member B runs
hedgehog cli gridspork-cosign -k <key of B> <digest> <digest> …with those digests, each 128 lower-case hex characters.
A mint storage spork signed by a 0.0.7 build cannot be renewed from the command line: the command refuses it before signing, as a stored spork that board keys did not sign.
Do not renew while a proposal for a value is pending: the renewal is newer and replaces it.
Key facts
| Item | Value |
|---|---|
| Signatures needed | Two, from different network keys |
| Default network keys | Four board keys, plus three retired keys used for history only |
| Algorithm | ECDSA, SHA-512, P-521 (secp521r1) |
| Board key | From exactly one of -k <hex>, --key-file <path> or $HEDGEHOG_BOARD_KEY; it never leaves the machine |
| Signed spork submission | POST /gridspork/wire with application/octet-stream, at most 16,777,216 bytes |
| Proposal digest | SHA-512 of the signed bytes, 128 lower-case hex characters |
| Proposals held | One per spork type, in memory only |
| Proposal lifetime | 60 minutes from its timestamp; a stamp more than 2 minutes ahead is refused |
| Change window | A data-changing sibling’s timestamp is at most 60 minutes after the stored version’s |
| Mint storage size | At most 16,384 entries |
| Vesting storage size | At most 4,096 schedules |
| Signature history | At most 4,096 entries |
| Signature checks | At most 1 a second per type and sending peer, 32 a second per type |
| Publish interval | Every 3 minutes; all but the statistics key are published |
| Save interval | Every 3 minutes, on one background thread; every type is saved |
Unreadable spork.db |
Moved aside as spork.db.unreadable-<epoch seconds>; the node starts without it |
| Stored in | spork.db in the user data directory |
| Default network port | 52883 (--netport) |
In the source
application/src/main/java/org/unigrid/hedgehog/model/spork/GridSpork.java: the base type and the acceptance rulesapplication/src/main/java/org/unigrid/hedgehog/model/spork/MintStorage.java,MintSupply.java,VestingStorage.java,StorageSpork.java,StatisticsPubKey.java,LedgerBlacklist.javaandLedgerFee.java: the spork typesapplication/src/main/java/org/unigrid/hedgehog/model/spork/PendingSporks.java: proposals waiting for a second keyapplication/src/main/java/org/unigrid/hedgehog/model/spork/VerifySlots.javaandSporkLag.java: when an incoming spork’s signatures are checkedapplication/src/main/java/org/unigrid/hedgehog/model/spork/PendingSporkInfo.java: how a proposal is listed, with its digestapplication/src/main/java/org/unigrid/hedgehog/model/spork/SignatureLog.java: the signature historyapplication/src/main/java/org/unigrid/hedgehog/model/crypto/NetworkKey.java: which keys are trustedapplication/src/main/java/org/unigrid/hedgehog/model/network/handler/PublishSporkChannelHandler.java: receiving sporksapplication/src/main/java/org/unigrid/hedgehog/model/network/schedule/PublishSporkSchedule.java: the periodic publishapplication/src/main/java/org/unigrid/hedgehog/model/producer/SporkDatabaseProducer.java: loads and savesspork.dbapplication/src/main/java/org/unigrid/hedgehog/model/network/codec/SporkWire.java: the wire form that the commands and the node’s wire endpoints read and writeapplication/src/main/java/org/unigrid/hedgehog/server/rest/GridSporkWireResource.java: handing out a stored spork or a proposal in wire form, and taking a signed spork backapplication/src/main/java/org/unigrid/hedgehog/server/rest/GridSporkResource.javaand the other spork resources: reading sporks and proposals as JSON, for displayapplication/src/main/java/org/unigrid/hedgehog/client/rest/SporkClient.java: the checks a command makes on what the node hands outapplication/src/main/java/org/unigrid/hedgehog/command/option/BoardKeyOptions.java: the three sources of the board key and their messagesapplication/src/main/java/org/unigrid/hedgehog/command/cli/GridSporkCosign.java: the co-sign command;GridSporkPending.java,GridSporkRenew.javaandGridSporkLog.javasit beside itapplication/src/main/java/org/unigrid/hedgehog/command/cli/spork/SporkProposal.java: fetching, checking, showing, signing and submitting a change;gridspork-get,gridspork-setandgridspork-growsit beside it