Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Table of Contents
maxLevel4

Motivation

The purpose of the protocol is to transfer value between independent shards.

...

The cross-shard value transfer protocol provides a way for each of the clients to move value from their own wallets to a parent shard or back.

Outstanding issues

  1. how to do weighted multi-signature 
  2. notification on block finalization (check with Michael Birch (Unlicensed) & Former user (Deleted))
  3. Should we have a shard DAG in a future version?
  4. how to roll-back cross-shard transfers when something goes wrong during the transfer?
  5. how to mount an existing shard?
  6. How to unmount a shard without destroying it?
  7. Why not register all the wallets in a public WalletRegistry?
  8. Do we sign the "approved" contracts used for REV?
  9. How to avoid the situation when the validators move their stakes out of the child shard while still holding their validator status?
  10. How does interaction with PoS contract happens at bonding/unbonding
  11. how to update K in order to keep the K/N ratio the same as validators bond/unbond. Should we keep the ratio in the config and re-compute K each time?

Architecture

The shards are organised in a tree structure. 

...

The parent shard validators are not involved in the child shards.

Components

Common data structures

KonsensusConfig

  • genesis_hash
  • validators : [ ValidatorConfig ]
  • k : Int

ValidatorConfig

  • ip_address
  • public_key
  • expected_bond : Int

K-of-N consensus

KonsensusFactory

Creates the Konsensus contract. This extra layer is needed because the create call has to be confirmed by all the validators.

KonsensusFactory API

createKonsensusConfig→ KonsensusFactoryInstantiates the K-of-N contract given the public keys of the validators and a given K value
createKonsensusSignature → KonsensusCreates the consensus after all the signatures are accumulated. The expected signature is the name of Konsensus process, signed with the caller's private key. The call returns only when all the required signatures are accumulated.

KonsensusProxy

This is used to control messages sent to a name. The notation KonsensusProxy[X] used further means that, after a message with K signatures is received the call will be forwarded to X. 

...

KonsensusProxy

sendMessage → Signature → UnitAccumulates K signatures on a message. After all the K messages are received the message is forwarded to the underlying address. The expected signature is the message signed with the callers' private key.

KoNsensus

A smart contract running in the parent shard which supervises the consensus in the child shard by running a K-of-N algorithm.

...

Konsensus API

getConfigUnit → KonsensusConfigreturns the configuration of the Konsensus contract

getUpdater

Unit → KonsensusProxy[KonsensusUpdater]Creates an updater for this Konsensus instance, wrapped in a KonsensusProxy that requires signatures equal to the number of public-keys 
makeProxyName → KonsensusProxy[_]Creates a proxy on top of an existing name

KonsensusUpdater

Processes that require k-of-n consensus are wrapped in a KonsensusProxy by calling makeProxy

KonsensusUpdater API

updateConfig

KonsensusConfig → UnitUpdates the Konsensus contract configuration with a new set of validators and a new K value. 

Child-validator management

ValidatorManager

Holds the stakes placed by the stakeholders.

...

ValidatorManager API

create[ValidatorConfig] → (KonsensusProxy[ValidatorManager], [StakeAdder] )Given a list of public keys of the child shard validators and their expected deposits returns a ValidatorManager, wrapped in a KonsensusProxy and a list of StakeAdderS
addValidatorPublicKey → StakeAdderstarts the operation of adding a new validator. The operation is finished when the new validator places his stake by calling StakeAdder.placeStake
removeValidatorPublicKey → Unitstarts the operation of removing an existing stakeholder from the depository

StakeAdder

This contract has the authority to place a new stake in the ValidatorManager. This has to be a separate capability and cannot be put in ValidatorManager because it doesn't have to be wrapped in the KonsensusProxy and placeStake has to be called independently by the new validator.

StakeAdder API

placeStakeSignature → Purse → Validator

used by child-shard validators to place their initial deposits. 

The expected signature is the purse name signed with a private key registered with the ValidatorManager during its creation.

Validator

The owner of the Validator instance has the right to withdraw his stake from the Depository, to the child-shard purse containing his tokens and can make a withdraw request.

...

Validator API
withdrawUnit → Pursereturns a purse with the deposit placed by the validator. This call completes after  removeValidator is called in the stake storage
getChildPurseUnit → Namereturns the name of the purse residing in the child shard and holding the equivalent of the placed stake in child shard tokens

Depository

The Depository (aka "Fort Knox") is a pair of public smart contracts running in a parent shard.

...

Depository.Withdrawer API

withdrawAmount → Purse

destroys the content of the purse and returns the name of a new purse located in the parent shard, minus fees. The new purse is sprouted from the Depository and its value + fees is removed from the Depository.

The returned name is a wallet registered in the parent shard

The Mint

The Mint is a pair of public smart contracts running in a child shard. 

...

Purse API
splitAmount → Pursecreates a new purse containing the given amount. This amount is subtracted from the current purse. Empty purses are destroyed

Wallets

A wallet is an address identified by a public key.

...

Wallet API

create(Purse,PublicKey) → WalletCreates a wallet given a purse with the initial value and a public key. The purse is destroyed and the returned wallet will contain the value of the Purse minus fees
depositPurse → UnitDeposits a purse into this wallet. The purse is destroyed
withdraw Amount → Purse

Withdraws an amount from this wallet. A new purse is returned.

getValueUnit → Amountreturns the value stored in the wallet

Shard tree setup

Sprout

Sprouting is the process of creating a child shard with an empty value stored inside.

...

See each of these steps described in details below

K-of-N Konsensus setup

In the parent-shard the Konsensus contract is instantiated through the following steps in order to avoid a MITM attack by the validator who initiates the process:

...

In the child shard a Konsensus contract also has to be instantiated and registered under a public name. The Konsensus in the client-shard to control the access to the Mint contract.

Mint & Depository setup

The Mint and Depository contracts are created and their names registered in their respective shard.

Stake placement

Removing a stakeholder

TODO. Interaction with Pos needs to be clarified

Adding a stakeholder

TODO. Interaction with Pos needs to be clarified

Child-shard absorption

Absorbing is the process of destroying a child shard while transferring all its value in the parent shard.

...

Unregistered child-shard wallets are also lost in the absorption process.

Mount

Through mounting, an existing shard is attached as a child of another existing shard.

TODO. We need to clarify how the mounting affects the clients of the shard

Umount

Through unmounting, a shard is detached from a shard tree and continues to live independently

TODO. We need to clarify how the unmounting affects the clients of the shard and the grandchild shards.

Atomic cross-shard value transfer

Each client only trusts his shard and the parents of his shard.

...

  1. Alice moves it's tokens to the root shard, which is the least common ancestor in this situation
  2. Alice transfers to a new wallet created with Bob's public-key in root shard
  3. Bob transfers his amount to "/d" shard

Parent-to-child transfer

TODO: Add diagrams and explain the steps

...

```rholang
//session id creation
contract newId(return) =
{ new id in {
return!(*id.toByteArray)
}
} ```

Child-to-parent transfer

TODO: Add diagrams and explain the steps

...

  1.  User in parent invokes the `transfer` function of the mint args: (purse, public key, return channel); returns session id over return channel
  2. Block containing 1. finalized
  3. Child Validators send messages to parent k-of-n contract
  4. Depository splits out a purse with the right number of tokens and wraps it in a wallet with the right public key, placing the result at `rho:uuid:<session id>`
  5. Blocks containing 3., 4. are finalized
  6. Child validators see 5. and each deploys a message to the k-of-n mint contract
  7. Confirmation sent to user over same return channel as 1.
  8. Blocks containing 6., 7. finalized

Useful links

https://blockstream.com/sidechains.pdf

...