Skip to content

Commit

Permalink
Rewrite RGB20 spec using Contractum & concept of interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Dec 18, 2022
1 parent f6d642e commit 1a05b8c
Showing 1 changed file with 105 additions and 227 deletions.
332 changes: 105 additions & 227 deletions lnpbp-0020.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
```
LNPBP: 0020
Vertical: Smart contracts
Title: RGB fungible assets schema (RGB-20)
Title: RGB fungible assets interface (RGB-20)
Authors: Dr Maxim Orlovsky <[email protected]>,
Giacomo Zucco,
Marco Amadori,
Expand All @@ -10,244 +10,122 @@ Authors: Dr Maxim Orlovsky <[email protected]>,
Sabina Sachtachtinskagia,
Martino Salvetti
Comments-URI: <https://github.com/LNP-BP/LNPBPs/issues/70>
Status: Final
Status: Proposal
Type: Standards Track
Created: 2019-09-23
Finalized: 2020-10-10
Finalized: 2022-12-18
License: CC0-1.0
```

Schema ID: `sch19s8js2gyxvtyzztp82l4tt4gr3x8m28yrgks93exsfuwc5u4fqlqf46ah5`

Encoded schema data: `schema1qxx4qkgjsgcqcl2atrzgmugynnpuk7q5c7dcplkppl9jr0ywx75xnk3zyvup3p3ke99auju22h9734efqs6gfppkg6qcyy69a8uhnw7czt37ckszd950xwwn9mjr59payf3sd2yuezjdy5vu5jdkew7mr78prvvnjkg0x34qyf6fdfsxyd4fk6guzrpuuxp7exgkyhlntx8ruw9j2s2e7dt8sgjhczjkk5e2a3np886u86mq5ge92r5ckde9gr4htt2td66gkzvypm2hwpsr8gdm6vqzmgca3ltn8j0qqkd0rl5s6f3nllngjfldlt7kz7uarne8w0zkhwpr90k0smcxk48dx`

Schema source:
```rust
Schema {
rgb_features: none!(),
root_id: none!(),
genesis: GenesisSchema {
metadata: type_map! {
FieldType::Ticker => Once,
FieldType::Name => Once,
FieldType::ContractText => NoneOrOnce,
FieldType::Precision => Once,
FieldType::Timestamp => Once,
FieldType::IssuedSupply => Once
},
owned_rights: type_map! {
OwnedRightsType::Inflation => NoneOrMore,
OwnedRightsType::Epoch => NoneOrOnce,
OwnedRightsType::Assets => NoneOrMore,
OwnedRightsType::Renomination => NoneOrOnce
},
public_rights: none!(),
abi: none!(),
},
extensions: none!(),
transitions: type_map! {
TransitionType::Issue => TransitionSchema {
metadata: type_map! {
FieldType::IssuedSupply => Once
},
closes: type_map! {
OwnedRightsType::Inflation => Once
},
owned_rights: type_map! {
OwnedRightsType::Inflation => NoneOrMore,
OwnedRightsType::Epoch => NoneOrOnce,
OwnedRightsType::Assets => NoneOrMore
},
public_rights: none!(),
abi: bmap! {
// sum(in(inflation)) >= sum(out(inflation), out(assets))
TransitionAction::Validate => Procedure::Embedded(StandardProcedure::FungibleInflation)
}
},
TransitionType::Transfer => TransitionSchema {
metadata: type_map! {},
closes: type_map! {
OwnedRightsType::Assets => NoneOrMore
},
owned_rights: type_map! {
OwnedRightsType::Assets => NoneOrMore
},
public_rights: none!(),
abi: none!()
},
TransitionType::Epoch => TransitionSchema {
metadata: none!(),
closes: type_map! {
OwnedRightsType::Epoch => Once
},
owned_rights: type_map! {
OwnedRightsType::Epoch => NoneOrOnce,
OwnedRightsType::BurnReplace => NoneOrOnce
},
public_rights: none!(),
abi: none!()
},
TransitionType::Burn => TransitionSchema {
metadata: type_map! {
FieldType::BurnedSupply => Once,
// Normally issuer should aggregate burned assets into a
// single UTXO; however if burn happens as a result of
// mistake this will be impossible, so we allow to have
// multiple burned UTXOs as a part of a single operation
FieldType::BurnUtxo => OnceOrUpTo(None),
FieldType::HistoryProofFormat => Once,
FieldType::HistoryProof => NoneOrMore,
},
closes: type_map! {
OwnedRightsType::BurnReplace => Once
},
owned_rights: type_map! {
OwnedRightsType::BurnReplace => NoneOrOnce
},
public_rights: none!(),
abi: bmap! {
TransitionAction::Validate => Procedure::Embedded(StandardProcedure::ProofOfBurn)
}
},
TransitionType::BurnAndReplace => TransitionSchema {
metadata: type_map! {
FieldType::BurnedSupply => Once,
// Normally issuer should aggregate burned assets into a
// single UTXO; however if burn happens as a result of
// mistake this will be impossible, so we allow to have
// multiple burned UTXOs as a part of a single operation
FieldType::BurnUtxo => OnceOrMore,
FieldType::HistoryProofFormat => Once,
FieldType::HistoryProof => NoneOrMore
},
closes: type_map! {
OwnedRightsType::BurnReplace => Once
},
owned_rights: type_map! {
OwnedRightsType::BurnReplace => NoneOrOnce,
OwnedRightsType::Assets => OnceOrMore
},
public_rights: none!(),
abi: bmap! {
TransitionAction::Validate => Procedure::Embedded(StandardProcedure::ProofOfBurn)
}
},
TransitionType::Renomination => TransitionSchema {
metadata: type_map! {
FieldType::Ticker => NoneOrOnce,
FieldType::Name => NoneOrOnce,
FieldType::ContractText => NoneOrOnce,
FieldType::Precision => NoneOrOnce
},
closes: type_map! {
OwnedRightsType::Renomination => Once
},
owned_rights: type_map! {
OwnedRightsType::Renomination => NoneOrOnce
},
public_rights: none!(),
abi: none!()
},
// Allows split of rights if they were occasionally allocated to the
// same UTXO, for instance both assets and issuance right. Without
// this type of transition either assets or inflation rights will be
// lost.
TransitionType::RightsSplit => TransitionSchema {
metadata: none!(),
closes: type_map! {
OwnedRightsType::Inflation => NoneOrMore,
OwnedRightsType::Assets => NoneOrMore,
OwnedRightsType::Epoch => NoneOrOnce,
OwnedRightsType::BurnReplace => NoneOrOnce,
OwnedRightsType::Renomination => NoneOrOnce
},
owned_rights: type_map! {
OwnedRightsType::Inflation => NoneOrMore,
OwnedRightsType::Assets => NoneOrMore,
OwnedRightsType::Epoch => NoneOrOnce,
OwnedRightsType::BurnReplace => NoneOrOnce,
OwnedRightsType::Renomination => NoneOrOnce
},
public_rights: none!(),
abi: bmap! {
// We must allocate exactly one or none rights per each
// right used as input (i.e. closed seal); plus we need to
// control that sum of inputs is equal to the sum of outputs
// for each of state types having assigned confidential
// amounts
TransitionAction::Validate => Procedure::Embedded(StandardProcedure::RightsSplit)
}
}
},
field_types: type_map! {
// Rational: if we will use just 26 letters of English alphabet (and
// we are not limited by them), we will have 26^8 possible tickers,
// i.e. > 208 trillions, which is sufficient amount
FieldType::Ticker => DataFormat::String(8),
FieldType::Name => DataFormat::String(256),
// Contract text may contain URL, text or text representation of
// Ricardian contract, up to 64kb. If the contract doesn't fit, a
// double SHA256 hash and URL should be used instead, pointing to
// the full contract text, where hash must be represented by a
// hexadecimal string, optionally followed by `\n` and text URL
FieldType::ContractText => DataFormat::String(core::u16::MAX),
FieldType::Precision => DataFormat::Unsigned(Bits::Bit8, 0, 18u128),
// We need this b/c allocated amounts are hidden behind Pedersen
// commitments
FieldType::IssuedSupply => DataFormat::Unsigned(Bits::Bit64, 0, core::u64::MAX as u128),
// Supply in either burn or burn-and-replace procedure
FieldType::BurnedSupply => DataFormat::Unsigned(Bits::Bit64, 0, core::u64::MAX as u128),
// While UNIX timestamps allow negative numbers; in context of RGB
// Schema, assets can't be issued in the past before RGB or Bitcoin
// even existed; so we prohibit all the dates before RGB release
// This timestamp is equal to 10/10/2020 @ 2:37pm (UTC)
FieldType::Timestamp => DataFormat::Integer(Bits::Bit64, 1602340666, core::i64::MAX as i128),
FieldType::HistoryProof => DataFormat::Bytes(core::u16::MAX),
FieldType::HistoryProofFormat => DataFormat::Enum(HistoryProofFormat::all()),
FieldType::BurnUtxo => DataFormat::TxOutPoint
},
owned_right_types: type_map! {
OwnedRightsType::Inflation => StateSchema {
// How much issuer can issue tokens on this path. If there is no
// limit, than `core::u64::MAX` / sum(inflation_assignments)
// must be used, as this will be a de-facto limit to the
// issuance
format: StateFormat::CustomData(DataFormat::Unsigned(Bits::Bit64, 0, core::u64::MAX as u128)),
// Validation involves other state data, so it is performed
// at the level of `issue` state transition
abi: none!()
},
OwnedRightsType::Assets => StateSchema {
format: StateFormat::DiscreteFiniteField(DiscreteFiniteFieldFormat::Unsigned64bit),
abi: bmap! {
// sum(inputs) == sum(outputs)
AssignmentAction::Validate => Procedure::Embedded(StandardProcedure::NoInflationBySum)
}
},
OwnedRightsType::Epoch => StateSchema {
format: StateFormat::Declarative,
abi: none!()
},
OwnedRightsType::BurnReplace => StateSchema {
format: StateFormat::Declarative,
abi: none!()
},
OwnedRightsType::Renomination => StateSchema {
format: StateFormat::Declarative,
abi: none!()
}
},
public_right_types: none!(),
}
- [Abstract](#abstract)
- [Background](#background)
- [Motivation](#motivation)
- [Design](#design)
- [Specification](#specification)
- [Compatibility](#compatibility)
- [Rationale](#rationale)
- [Reference implementation](#reference-implementation)
- [Acknowledgements](#acknowledgements)
- [References](#references)
- [Copyright](#copyright)


## Abstract


## Background


## Motivation


## Design



## Specification

Interface specification is the following Contractum code:

```haskell
-- # Defining main data structures

-- number of decimal fractions (decimal numbers after floating point)
data DecFractions :: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18

data TxOut :: txid [Byte ^ 32], vout U16

data Amount :: U64 -- asset amount

-- allocation of assets to some transactou output
data Allocation :: TxOut, Amount

-- right over certain amount of assets; right owner may be unknown
data AssetControl :: TxOut?, Amount

data Nomination ::
ticker [Ascii ^ 1..8],
name [Ascii ^ 1..40],
details [Unicode ^ 40..256]?,
contract [Unicode]??,
precision DecFractions

data RGB20Info ::
knownInfo Nomination,
origInfo Nomination,
isFinalInfo Bool,
renominationRight TxOut?,

isSupplyKnown Bool, -- indicates that all issues, burn and reissues are known
supplyKnown Amount, -- returns information about known cirtulating supply
supplyLimit Amount, -- maximum possible asset inflation
pastIssues [AssetControl], -- known past issue operations
futureIssues [AssetControl], -- known future issue operations
knownBurns [AssetControl], -- known past burn operations
knownReissues [AssetControl], -- known future burn operations

knownAllocations [Allocation] -- known asset amounts allocated to known UTXOs

interface RGB20 :: RGB20Info
op transfer :: inputs [TxOut ^ 1..]
-> beneficiaries [Allocation]

-- question mark denotes optional operation, which may not be supported by
-- some of schemata implementing the intrface

op? issue :: usingRight TxOut, amount Amount
-> nextRight TxOut?, beneficiaries [Allocation]

op? burn :: usingRight TxOut, assets Allocation
-> nextRight TxOut?

op? reissue :: usingRight TxOut, assets Allocation
-> nextRight TxOut?, beneficiaries [Allocation]

op? renominate :: usingRight TxOut
-> nextRight TxOut?, newNomination AssetInfo
```

## Subschemata
## Compatibility

- https://github.com/LNP-BP/LNPBPs/issues/44

## Rationale

Include from
- https://github.com/LNP-BP/LNPBPs/issues/27
- https://github.com/LNP-BP/LNPBPs/issues/28
- https://github.com/LNP-BP/LNPBPs/issues/50

## Reference implementation


## Acknowledgements


## References


## Copyright

This document is licensed under the Creative Commons CC0 1.0 Universal license.

0 comments on commit 1a05b8c

Please sign in to comment.