Noto - Notarized Tokens¶
The Noto domain provides confidential UTXO tokens which are managed by a single party, referred to as the notary. Each UTXO state (sometimes referred to as a "coin") encodes an owning address, an amount, and a randomly-chosen salt. The states are identified on the base ledger only by a hash of the state data, while the private state data is only exchanged via private channels.
The base ledger provides deterministic ordering, double-spend protection, and provable linkage of state data to transactions. The private state data provides a record of ownership and value transfer.
Private ABI¶
The private ABI of Noto is implemented in Go,
and can be accessed by calling ptx_sendTransaction
with "type": "private"
.
constructor¶
Creates a new Noto token, with a new address on the base ledger.
{
"name": "",
"type": "constructor",
"inputs": [
{"name": "notary", "type": "string"},
{"name": "implementation", "type": "string"},
{"name": "restrictMinting", "type": "boolean"},
{"name": "hooks", "type": "tuple", "components": [
{"name": "privateGroup", "type": "tuple", "components": [
{"name": "salt", "type": "bytes32"},
{"name": "members", "type": "string[]"}
]},
{"name": "publicAddress", "type": "address"},
{"name": "privateAddress", "type": "address"}
]}
]
}
Inputs:
- notary - lookup string for the identity that will serve as the notary for this token instance. May be located at this node or another node
- implementation - (optional) the name of a non-default Noto implementation that has previously been registered
- restrictMinting - (optional - default true) only allow the notary to request mint
- hooks - (optional) specify a Pente private smart contract that will be called for each Noto transaction, to provide custom logic and policies
mint¶
Mint new value. New UTXO state(s) will automatically be created to fulfill the requested mint.
{
"name": "mint",
"type": "function",
"inputs": [
{"name": "to", "type": "string"},
{"name": "amount", "type": "uint256"},
{"name": "data", "type": "bytes"}
]
}
Inputs:
- to - lookup string for the identity that will receive minted value
- amount - amount of new value to create
- data - user/application data to include with the transaction (will be accessible from an "info" state in the state receipt)
transfer¶
Transfer value from the sender to another recipient. Available UTXO states will be selected for spending, and new UTXO states will be created, in order to facilitate the requested transfer of value.
{
"name": "transfer",
"type": "function",
"inputs": [
{"name": "to", "type": "string"},
{"name": "amount", "type": "uint256"},
{"name": "data", "type": "bytes"}
]
}
Inputs:
- to - lookup string for the identity that will receive transferred value
- amount - amount of value to transfer
- data - user/application data to include with the transaction (will be accessible from an "info" state in the state receipt)
approveTransfer¶
Approve a transfer to be executed by another party.
When calling ptx_prepareTransaction()
to prepare a private transfer
, the metadata
of the prepared transaction
will include information on how to build a proper approveTransfer
call. This allows preparing a transfer and then
delegating it to another party for execution.
{
"name": "approveTransfer",
"type": "function",
"inputs": [
{"name": "inputs", "type": "tuple[]", "components": [
{"name": "id", "type": "bytes"},
{"name": "schema", "type": "bytes32"},
{"name": "data", "type": "bytes"}
]},
{"name": "outputs", "type": "tuple[]", "components": [
{"name": "id", "type": "bytes"},
{"name": "schema", "type": "bytes32"},
{"name": "data", "type": "bytes"}
]},
{"name": "data", "type": "bytes"},
{"name": "delegate", "type": "address"}
]
}
Inputs:
- inputs - input states that will be spent
- outputs - output states that will be created
- data - encoded Paladin and/or user data
- delegate - address of the delegate party that will be able to execute this transaction once approved
Public ABI¶
The public ABI of Noto is implemented in Solidity by Noto.sol,
and can be accessed by calling ptx_sendTransaction
with "type": "public"
. However, it is not often required
to invoke the public ABI directly.
mint¶
Mint new UTXO states. Generally should not be called directly.
May only be invoked by the notary address.
{
"name": "mint",
"type": "function",
"inputs": [
{"name": "outputs", "type": "bytes32[]"},
{"name": "signature", "type": "bytes"},
{"name": "data", "type": "bytes"}
]
}
Inputs:
- outputs - output states that will be created
- signature - sender's signature (not verified on-chain, but can be verified by anyone with the private state data)
- data - encoded Paladin and/or user data
transfer¶
Spend some UTXO states and create new ones. Generally should not be called directly.
May only be invoked by the notary address.
{
"name": "transfer",
"type": "function",
"inputs": [
{"name": "inputs", "type": "bytes32[]"},
{"name": "outputs", "type": "bytes32[]"},
{"name": "signature", "type": "bytes"},
{"name": "data", "type": "bytes"}
]
}
Inputs:
- inputs - input states that will be spent
- outputs - output states that will be created
- signature - sender's signature (not verified on-chain, but can be verified by anyone with the private state data)
- data - encoded Paladin and/or user data
approveTransfer¶
Approve a specific transfer
transaction to be executed by a specific delegate
address.
Generally should not be called directly.
The txhash
should be computed as the EIP-712 hash of the intended transfer, using type:
Transfer(bytes32[] inputs,bytes32[] outputs,bytes data)
.
May only be invoked by the notary address.
{
"name": "approveTransfer",
"type": "function",
"inputs": [
{"name": "delegate", "type": "address"},
{"name": "txhash", "type": "bytes32"},
{"name": "signature", "type": "bytes"},
{"name": "data", "type": "bytes"}
]
}
Inputs:
- delegate - address of the delegate party that will be able to execute this transaction once approved
- txhash - EIP-712 hash of the intended transfer, using type
Transfer(bytes32[] inputs,bytes32[] outputs,bytes data)
- signature - sender's signature (not verified on-chain, but can be verified by anyone with the private state data)
- data - encoded Paladin and/or user data
transferWithApproval¶
Execute a transfer that was previously approved.
The values of inputs
, outputs
, and data
will be used to (re-)compute a txhash
, which must exactly
match a txhash
that was previously delegated to the sender via approveTransfer
.
{
"name": "transferWithApproval",
"type": "function",
"inputs": [
{"name": "inputs", "type": "bytes32[]"},
{"name": "outputs", "type": "bytes32[]"},
{"name": "signature", "type": "bytes"},
{"name": "data", "type": "bytes"}
]
}
Inputs:
- inputs - input states that will be spent
- outputs - output states that will be created
- signature - sender's signature (not verified on-chain, but can be verified by anyone with the private state data)
- data - encoded Paladin and/or user data
Transaction walkthrough¶
Walking through a simple token transfer scenario, where Party A has some fungible tokens, transfers some to Party B, who then transfers some to Party C.
No information is leaked to Party C, that allows them to infer that Party A and Party B previously transacted.
Party A
has three existing private states in their wallet and proposes to the notary:- Spend states
S1
,S2
&S3
- Create new state
S4
to retain some of the fungible value for themselves - Create new state
S5
to transfer some of the fungible value toParty B
- Spend states
Notary
receives the signed proposal fromParty A
- Validates that the rules of the token ecosystem are fully adhered to
- Example:
sum(S1,S2,S3) == sum(S4,S5)
- Example:
Party B
is authorized to receive funds - Example: The total balance of
Party A
will be above a threshold after the transaction - Uses the notary account to submit
TX1
to the blockchain recording signature + hashes
Party B
processes the two parts of the transaction- a) Receives the private data for
#5
to allow it to storeS5
in its wallet - b) Receives the confirmation from the blockchain that
TX1
created#5
- Now
Party B
hasS5
confirmed in its wallet and ready to spend
- a) Receives the private data for
Party B
proposes to the notary:- Spend state
S5
- Create new state
S6
to retain some of the fungible value for themselves - Create new state
S7
to transfer some of the fungible value toParty C
- Spend state
Notary
receives the signed proposal fromParty B
- Validates that the rules of the token ecosystem are fully adhered to
- Uses the notary account to submit
TX2
to the blockchain recording signature + hashes
Party C
processes the two parts of the transaction- a) Receives the private data for
#7
to allow it to storeS7
in its wallet - b) Receives the confirmation from the blockchain that
TX2
created#7
- Now
Party C
hasS7
confirmed in its wallet and ready to spend
- a) Receives the private data for
TODO: Fill in significantly more detail on how Noto operates (Lead: Andrew Richardson)