-
Couldn't load subscription status.
- Fork 0
Operations
The most critical parts to backup are of course :
-
ipns key
-
signing keys
If you use a cloud hsm, make sure to activate some deletion protections, to avoid any accidental removal.
Beside that, since a signer can always rebuild its state, if it still has control of its keys (signing + ipns), backing up its local state or its ipfs repository is not mandatory. It’s just a matter of rebooting faster in case of data loss on a server.
Of course, if you lose your ipfs repository, users won’t be able to retrieve your signatures if no node on the network has a copy. That’s why BenderLabs runs a instance of wrap-indexer, that amongs other thing, will pin all events produced by the quorum.
By default, fees will be distributed to the implicit account associated with the signer signing key. It’s possible to instruct the contract to dispatch fees to another payment address.
Quorum contract exposes an entrypoint set_signer_payment_address for this purpose:
(pair %set_signer_payment_address
(address %minter_contract) (1)
(pair
(string %signer_id) (2)
(signature %signature) (3)
)
)
-
Address of the minter contract
-
Signer’s IPFS key (as returned by the
keysendpoint) -
A signature, described below
The signature will be checked againt the public key associated with this signer_id.
If the signature is valid, the sender address will be used as the new payment address.
That way, we check that the caller is both in control of the signer public key, and obviously, the sender private key.
To prevent replay attack, each signer is associated with a counter that will increment with every call.
The payload to sign is as follow:
(
chain_id (1)
*
address (2)
) *
(
nat (3)
*
(
address (4)
* address (5)
)
)
-
Chain id the contract is running on
-
Quorum contract address
-
Current counter for this signer. Starts at 0. Can be retrieve later on in the quorum contract storage
-
Minter contract address
-
Sender address
Admin api exposes an enpoint to produce this signature.
-
Build the signature
PAYLOAD=`cat <<EOF { "address":"tz…",(1) "counter":0 (2) } EOF`; curl -X POST -H "Content-Type: application/json" -d "${PAYLOAD}" http://signer.node:5000/signatures/payment_address;-
New payment address
-
Current counter. can be left to 0 the first time around
You’ll get an answer looking like:
{ "signature" = "<signature in base58>", "quorum":{ "quorumContract": "<targeted quorum contract>, "chainId": "<targeted chain id>", "minterContract": "<targeted minter contract>" }, "parameters":{ "counter": <counter used>, "address": "<new payment address>" } }Extracts the information you need for next step (quorum contract, minter contract, signature)
-
-
Call the quorum contract, using the proper sender
tezos-client call <Quorum contract address> \ from <Your new payment address> \ --entrypoint 'set_signer_payment_address' --arg 'Pair "<Minter contract address>" (Pair "<ipfs key>" "<signature>")'
Minter contract is technically, the owner of all fees generated. It keeps an internal ledger to know who is entitled to what. This ledger is updated in different ways:
-
each time a wrap/unwrap occurs, the minter contract increases it own balance
-
each time
distribute_tokensordistribute_xtzis called, minter contract dispatches it balance along signers, dev pool and staking contract -
each time anyone who owns a balance withdraw its funds
So in a nutshell, only withdraw_all_tokens, withdraw_all_xtz, withdraw_token generate an actual transfer.
An offchain view exists to extract the token amount owned to a given address : get_token_reward
To know how many tokens are pending distributon, the same view can used, just passing minter contract address as parameter.
Minter contract, when one of the distribution endpoint is called, will update to the appropriate amount the balance of each signer.
To do so, it needs to know the current quorum members. That’s why these entrypoints are permissioned to a role called oracle, in charge of relaying quorum members.
For now, this role is held by the quorum contract itself, and will just forward what it has in storage. Later on more sofisticated rules could be introduced.
Since the token list can grow unbounded, tokens to be distributed must be specified as parameter.
So, to trigger a distribution, one must call distribute_tokens_with_quorum from the quorum contract. It’s permissionless, and accept this parameter:
(pair %distribute_tokens_with_quorum
(address %minter_contract)
(list %tokens (pair address nat)))
One such invocation could look like:
tezos-client transfer 0 from %YOUR_ADDRESS% \
to KT1DLif2x9BtK6pUq9ZfFVVyW5wN2kau9rkW \
--entrypoint 'distribute_tokens_with_quorum' \
--arg 'Pair "KT1MTnKjFSN2u4myPRBqnFuCYCPX8kTdUEnv" { Pair "KT18fp5rcTW7mbWDmzFwjLDUhs5MeJmagDSZ" 0 ; Pair "KT18fp5rcTW7mbWDmzFwjLDUhs5MeJmagDSZ" 1 }'
The withdrawal logic is very straighforward : the minter contract will send any amount associated with the sender address to the sender itself.
|
❗
|
keep in mind that unless you change it, all fees will be associated with the implicit account deduced from the signer public key, so you would need to call withdraw with your signing key. |
For instance, the withdraw all initial 21 tokens out of the contract:
transfer 0 from %YOUR_ADDRESS% \
to KT1MTnKjFSN2u4myPRBqnFuCYCPX8kTdUEnv \
--entrypoint 'withdraw_all_tokens' \
--arg 'Pair "KT18fp5rcTW7mbWDmzFwjLDUhs5MeJmagDSZ" { 0 ; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; 19; 20 }'
And to withdraw fees collected in WRAP, if any :
transfer 0 from %YOUR_ADDRESS% \
to KT1MTnKjFSN2u4myPRBqnFuCYCPX8kTdUEnv \
--entrypoint 'withdraw_all_tokens' \
--arg 'Pair "KT1LRboPna9yQY9BrjtQYDS1DVxhKESK4VVd" { 0 }'
Signer node exposes a minimal admin api. It is not protected, so make sure not to expose it on the internet:
returns keys in use by this signer instance. Usefull to be onboarded as a quorum member, since it contains everything required.
{
"tezosKey":"<tezos public key, in base58>",
"ethereumKey": "<ethereum signing address>",
"ipnsKey": "<ipfs public key used to publish events>"
}
returns the signer current status. Can serve as a healtcheck endpoint.
{
"head": "<CID of last event published>",
"tezosLevel": <last tezos level observed>,
"ethereumLevel": <lest ethereum level observed>
}
used to signed a change payment address request. By default, minter contract will collect fees for a specific signer under the implicit account associated with its public key. This could prove to be unpractical, and as a mater of fact, we discourage storing assets under this address.
It is possible to change its payment address, calling the proper endpoint on quorum contract, but it will require a signature coming from its public signing key.
Also, the quorum contract expects the new payment address to be the SENDER address
To protect against replay attack, quorum contract expect the signed to payload to include a counter, specific to each signer, and incremented with each successfull call.
This process is described in more details in the contract documentation.
Payload, Content-Type=application/json:
{
"address":"<new payment address. Should be the `SENDER` that quorum contract will observe> ",
"counter": <current signer counter in quorum contract>
}
Response:
{
"signature" = "<signature in base58>",
"quorum":{
"quorumContract": "<targeted quorum contract>,
"chainId": "<targeted chain id>",
"minterContract": "<targeted minter contract>"
},
"parameters":{
"counter": <counter used>,
"address": "<new payment address>"
}
}
This response can be used then to actually call the quorum contract