(and with respect to work done in Cordite)
Corda
- the open source version of Corda, including thefinance
andcore
modulesCordite
- a collection of cordapps for decentralised businessesCordite DGL
- the distributed general ledger for accounts and tokens as defined in CorditeCordite DAO
- see Cordite DAO
-
Several of the changes in Corda are good and very welcome:
FungibleState
andLinearPointer
. We note that the use of the latter with Tokens, in the way suggested in the document, will carry a performance cost. -
There are other design concerns - most of these are either functionally minimal or related to performance. These are covered in the Design Review section.
-
Apart from these, there is an almost one-to-one correspondence between the Cordite implementation and this proposal such that, with a minimal set of renames / refactorings, would match the specification.
-
The Cordite project welcomes contributions to refactor the existing implementation towards the intended design.
-
The Cordite project welcomes any roadmap that hollows out Cordite DGL into Corda
finance
without creating two competing implementations. -
The Cordite DGL codebase is expected to continue to advance with new features layered on top of Corda
finance
.
- Wide spread adoption of Corda
- Build awareness and understanding of the benefits of Corda
- Encourage use of Corda by demonstrating how it will help improve your business
- Support thought leaders in using Corda
- Don't fork Corda. Stronger together
- Minimal core system with flexibility to extend
- Support widest functionality and be least prescriptive
- Provide exemplar CorDapps using Cordite
- Minimise CorDapp knowledge of Cordite
- Code is not law. Cordite will re-use existing legal frameworks to make law is code
- Don't be opinionated. You lose people for every opinion
- Don't implement anything more than the minimum required. Let others extend
- Don't wait. WYSIWYG. Raise feature requests on Corda and work round
- Be Open Source (Presently 24 contributors, multiple maintainers from disparate orgs)
- No manual test. Aggressive use of automated testing from unit to full scale environments
- Sustain code quality and test coverage with code reviews and commit gates
- Maintain a bi-weekly cadence. Have the ability to release at any moment in time from a "green" build
In the slack conversations some asked for the requirements for Tokens in Cordite. This a precis of a large number of requirements captured as project tickets.
Built for: NatWest CurrencyPay and RBS Rewards, but with an eye on new use-cases being discovered via Chorum.
- Define a unit level instrument (Token type) that can represent fiat, crypto currencies, reward tokens, audio credits or units of basic tokenised assets - equities, bonds, mortgages
- Should be able to support aliasing - it multiple ‘instrument’ codes - for example XBT, BTC
- Aliasing should also support validity date ranges (for example ISINs)
- Must be able to support micro units and hence exponent should be part of definitiion
- Corda Parties should be able to create Token types with ‘strong’ issuance such that Tokens are unique by Issuer and Token Name and be universally unique
- Tokens should be referenced by their unique identifier across nodes without the need for copying the whole token definition
- Corda Parties must be able to create accounts to store tokens
- Accounts must be able to support multiple token types
- Accounts should be uniquely identifiable across all nodes - using node identity plus account name
- Accounts must support aliases so that they can be identified by existing methods, such as IBAN, Sortcode and Account Number
- Accounts must support multiple financial structures such as trading book hierarchies and accounting hierarchies so that aggregation of positions and financial position can be calculated
- Accounts should support multiple owners (e.g. joint accounts, business accounts) and only allow transfers when a quorum of signatures is achieved
- Accounts should be able to span multiple nodes for resilience and decentralisation
- Accounts should be able to be owned by non node (i.e. user) parties
- Tokens must only be issued to accounts
- Tokens must be able to be transferred between accounts on the same node or between nodes using primary or aliased account identifiers
- All Token transactions must produce a summary of debits and credits
- Tokens and Accounts should be searchable by primary and secondary (alias) identifiers
- We must be able to listen to account changes by specifying single or groups of primary identifiers or tags.
- Tokens may be issued back-to-back from existing off-ledger assets, in which case it should be possible to immobilise the off-ledger asset thereby ensuring that the underlying assets cannot be 'spent' independantly from the issued token. The Token should be a specialised form a PromissoryNote with immediate or future maturity and partial redemption.
It would be helpful if the static class diagram was done to show all dependencies and inheritance relationships, ideally using a standard like UML. It would also be helpful to show example assets and their representation in this hiearchy, to give futher context and a useful reference for the written narrative.
-
It is debatable whether a Commodity does not have an issuer. Logically it would be the miner, farmer, a quality assurance gate provisioned by a buyer or distributor etc.
-
Likewise for freehold real-estate with the issuer being either a sovereign or proxy; and for chattels being the manufacturer.
-
Cryptocurrencies - the nature of the issuer depends on the coin. Some that are issued by a foundation or group of "master" nodes (e.g see Dash), which could be identified natively as a DAO
-
Typically, cryptocurrencies being tokenised on the Corda Ledger will need to have an issuer that holds the required keys to settle the respective tokens, when called upon by an owner. Without an issuer, how does one exchange
XBTC
(Bitcoin on Corda) for it's underlying 'BTC'?
The separation of Fungible
from Ownable
is a good step. Notably because the notion of Ownable
in Corda is somewhat constrained to a single party. In the real-world, joint ownership is not unheard of. Furthermore, for digital mutuals, joint ownership will be a central concept.
We also suggest for consideration the dropping of the withNewOwner
method as being mandatory. This limits transfers of state to simple semantics. The case in point is on metering invoices (and it could be said invoices in general) where one will only want to be able to transfer state if certain contract conditions are met - i.e. when paying and invoice, transfer back to the payee can only be done under the condition that there is payment in some kind of token.
Suggest we reconsider semantics of Ownable
to be broader. Or introduce an alternative type to represent joint ownership.
These are very close to Cordite's TokenType,State
, TokenType.Descriptor
with minimal refactoring. The changes proposed open up potential new use-cases, which is good, but they may also possibly hamper performance for tokens at scale. Notably, to resolve LinearPointer
s to TokenType
s will be a very common operation incurring per transaction overheads of unbounded size because TokenType
is effectively open to carry any payload. See the next section for more detail.
As a general construct, this is a useful addition to Core Corda. The issue is how to resolve
a pointer to its LinearState
. The Pointer
doesn't contain the source party. The design document suggests transferring the TokenType
with each transaction as reference data, but notes:
embedding the pointed-to state may not always be preferable, especially if it is quite large
Indeed this is the case with tokens at large - transferring the definition adds an unnecessary duplication of reference state per transaction (O(N) space), obviating the need for LinearPointer
, and causing inflation of network and disk representation. This is particularly a concern because as a node operator, one cannot estimate the potential size of network messages and disk storage of TokenTypes
because it is an open type. Furthermore, there is a performance cost for functions such as getBalance
, where a join is required between the FungibleState
table and the TokenType
table, degrading from O(N) to O(N.log(N)) in the worst case.
In lieu of an efficient pointer type in Corda, Cordite DGL reviewed the above concerns and concluded:
-
tokens need to carry a descriptor that can be serialisable to a well-formed string that is human and machine readable, meaningful enough for database queries, and without implying the need for additional states and joins. This string carries the issuer name so that the string is globally referentially unique.
-
as a result,
TokenType
s are sealed. Any ancillary information about the token type has to be encoded in a seperate and distinct state type.
-
make the transfer of reference data a one-time operation that does not incur per transaction cost overheads; or make the pointer type carry the originator party so that it may be recovered on a lazy basis from the source node using a core API call.
-
enforce the naming of the
externalId
for theLinearState
used byTokenType.Description
to be a well-formed string representing a unique 'symbol' for the token, it's number of decimal places, and its issuer / creator. That way, generalised queries for amounts by type, can be served with no joins, and no additional states (reference or otherwise). -
Suggest keeping ancilliary data regarding the TokenType (e.g. bond default status) as being out-of-band data that is (a) optional; (b) can use data-distribution groups or other techniques for sharing (some of these may wish to monetised); (c) is completely decoupled from the core Token design.
-
Is there a reason to limit this pointer to only
LinearState
?