Skip to content

Latest commit

 

History

History
311 lines (221 loc) · 12.3 KB

nip-0004.md

File metadata and controls

311 lines (221 loc) · 12.3 KB

NIP 4 - Apostille Improvement Protocol

    NIP: 4
    Layer: Library
    Title: Apostille Improvement Protocol
    Author: Jonathan Tey <[email protected]>
    Discussions-To: #wg-apostille
    Comments-URI: https://github.com/nemtech/NIP/issues/11
    Status: Draft
    Type: Standards Track
    Created: 2019-04-02
    License: Apache-2.0
    License-Code: ASL v2

Table of contents

Introduction

This proposal intends to improve the apostille creation standard to utilize the newer features of Catapult as well as to consolidate private and public apostille into a single standard. Any wallet or explorer that is compatible with this NIP will be able to parse and display accounts that are created according to this standard.

Future work should be done to define standards for handling transfer of ownership, scaling, verifying, and the use case for metadata.

Specification

Creating an apostille account

The steps below describe using private apostille standard to generate an asset account (Section 3.3 in the Apostille whitepaper). The point of deviation from the whitepaper will be indicated as below and is part of the improvement proposal.

X0 - Private key of owner

X1 - Private key of document to apostille

PA - Public address of apostille sink account

To generate X1, hash the filename and sign with X0. The resulting signature is truncated and will be X0

The file hash, Fh is generated as follows:

0xFE 'N' 'T' 'Y' 0x81 + sign(md5(data)
0xFE 'N' 'T' 'Y' 0x82 + sign(sha-1(data)
0xFE 'N' 'T' 'Y' 0x83 + sign(sha-256(data)
0xFE 'N' 'T' 'Y' 0x88 + sign(keccak-256(data)
0xFE 'N' 'T' 'Y' 0x89 + sign(keccak-512(data))
0xFE 'N' 'T' 'Y' 0x90 + sign(sha3-256(data)
0xFE 'N' 'T' 'Y' 0x91 + sign(sha3-512(data))

As @daoka pointed out, the SHA3 used in NIS1 differs from Catapult. Hence we will distinguish the two to ensure compatibility.

with the magic header 0xFE4E5459 and sign() is the signing function using the owner's private key, for X0.

Important!

Note that the non-signed version of apostille is not included here.

The section that follows will now deviate from the previous apostille standard

Announcing apostille

The announcing of apostille will now use aggregate transactions that will contain at least one inner transaction.

aggregateTx = AggregateCompleteTransaction[
    innerTransaction1, // Required
    innerTransaction2, // Optional
    innerTransaction3, // Optional
    innerTransaction4 // Optional
]

First inner transaction

The first inner transaction will contain the file hash and is the core of the apostille system.

apostilleTx = TransferTransaction.create(
    Deadline.create(),
    <address of apostille account>,
    [],
    PlainMessage.create(<File hash>),
    NetworkType.MIJIN_TEST);

innerTransaction1 = apostilleTx.toAggregate(<owner public account>);

Second inner transaction

The second inner transaction will announce the creation of the apostille to a public sink address.

sinkTx = TransferTransaction.create(
    Deadline.create(),
    <address of public sink account>,
    [],
    PlainMessage.create(<File hash>),
    NetworkType.MIJIN_TEST);

innerTransaction2 = sinkTx.toAggregate(<apostille public account>);

Third inner transaction

The third inner transaction will assign ownership of the apostille. Solving the private key leakage issue (https://github.com/daoka/asset-apostille).

multisigTx = ModifyMultisigAccountTransaction.create(
    Deadline.create(),
    1,
    1,
    [
        new MultisigCosignatoryModification(
            MultisigCosignatoryModificationType.Add,
            cosignatory,
        )
    ],
    NetworkType.MIJIN_TEST);

innerTransaction3 = multisigTx.toAggregate(<apostille public account>);

cosignatory will be the PublicAccount of X0 or any other public account to assign first ownership to.

Fourth inner transaction

A fourth optional inner transaction can be added to contain certain apostille metadata.

metadataTx = TransferTransaction.create(
    Deadline.create(),
    <address of apostille account>
    [],
    PlainMessage.create(<metadata>),
    NetworkType.MIJIN_TEST
);

innerTransaction4 = metadataTx.toAggregate(<apostille public accout>);

where metadata is a JSON string.

Metadata JSON example
{
    "filename": "sample.pdf",
    "tags": ["sample", "apostille"],
    "description": "apostille sample file",
    "originFileURL": "http://example.com/sample_file.pdf"
}

Note

  • The size of the JSON payload is limited to the transaction message size.
  • When Metadata Key/Value Association (#8) specification is decided and implemented, this section might use that feature. Future implementations should always check for a transfer transaction with a JSON payload to ensure backwards compatibility.

Sign and announce

signedTx = aggregateTx
    .signTransactionWithCosignatories(
        <owner account>,
        [apostille account]
    )

transactionHttp
    .announce(signedTransaction)
    .subscribe(x => console.log(x), err => console.error(err));

This concludes the first section on how to create an apostille account.

Tokenization of apostille asset

After the creation of the apostille account, we can tokenize it by issuing mosaics from the apostille account.

To do this, we will designate certain nonces to represent different categories of tokens, eg. initial offering, STO compatibility list, etc.

const nonce = <as defined below>;

const mosaicDefinitionTransaction = MosaicDefinitionTransaction.create(
    Deadline.create(),
    nonce,
    MosaicId.createFromNonce(nonce, account.publicAccount),
    MosaicProperties.create({
        supplyMutable: true,
        transferable: true,
        levyMutable: false,
        divisibility: 0,
        duration: UInt64.fromUint(1000)
    }),
    NetworkType.MIJIN_TEST);

with account.publicAccount being the apostille public account.

Table of nonces

Below is a set of recommendations, subject to change.

Nonce Description
0x544F4B00 Generic token
0x53544F01 Global STO token
0x53544F02 Region locked STO token
0x53544F03 Vesting token

Nonces in Catapult are 32 bit long binary string. The above is the nonce encoded in HEX.

Hex values 54, 4F, 4B represents T, O, K respectively while53, 54, 4F represents S, T, O, in UTF-8.

Motivation

There have been discussions in https://github.com/daoka/asset-apostille regarding the possibility of using mosaics to represent private apostille .

While representing assets as mosaics can give certain benefits, eg. tokenization, it does not give enough flexibility as being represented as an account. For example, with multisig it is easy to enforce a 2 of 3 contract where no transfer of ownership happens without a minimum of a combination of 2 signatures of the three owners. Using mosaics to enforce such a contract is difficult and control of ownership of mosaics is more complicated (not impossible).

Private apostille is already proven to be very useful in representing non-fungible assets on the NEM blockchain, but lacks the tokenization property as the number of multisig owners of an account is limited and much smaller than the possible divisibility of mosaics.

Design Decisions

There has been confusion regarding private vs public apostille, and the ability to switch between the two. In actual fact, the implementation for private apostille is almost not compatible with public apostille.

Private vs Public Apostille

Naming both methods as apostille does not provide a good developer experience. For example, someone implements a public apostille application because it is simple in concept and works well as a first Proof of Concept (PoC). Later on, they would add a new feature on their road map to have a transferable apostille as they read it is possible with apostille, not knowing that it would entail rewriting their PoC from scratch to support the more "complicated" private apostille.

Hence in this proposal, we would like to consolidate both private and public apostille into a single standard; combining the feature sets of private and public apostille into one apostille standard.

Storing of XEMs/currency in private apostille account

Right now, in order for private apostille to be functional, eg. transfer of ownership, the apostille account needs to be funded with XEMs. This raises an issue where by a small amount of XEMs need to be kept in these accounts which can be spent by anyone who currently controls the multisig contract.

Using aggregate transactions, it is possible to have a third party pay the transaction fee of the transfer, etc. without needing to preload the apostille account with XEMs. How this is done will be detailed in the #Specification section.

Future of tokenization

Another trend that is happening in the blockchain world is the move towards tokenization, eg. STOs. This NIP will also set forth a recommendation on how to support different tokens that are compatible with certain regulations, etc.

Implementation

https://github.com/luxtagofficial/Apostille-library/tree/NIP0004

Backwards compatibility

This standard will deprecate the public apostille standard. As for how we can transition current public apostille to the new standard is not determined and is outside the scope of this NIP.

This standard is NOT backwards compatible with NIS1, as it relies on certain Catapult only features.

Drawbacks

A separate verifier class needs to be maintained to support verification of older .nty files (NanoWallet generated apostille certificate). This is subject to the details of the migration plans.

On the blockchain, the maximum number multisig accounts that a single account can cosign for is limited to 5 (for NIS1) and 25 (for Catapult, but configurable for each chain). The point being that NEM accounts are not designed to "own" (cosign for) a large number of asset/apostille accounts, as opposed to mosaics, which theoretically an account can hold significantly more of.

The scalability issues of this NIP will be addressed in a separate issue as it is outside the scope of this NIP.

Alternatives

References

History

Date Version
2019-04-02 Initial draft
2019-04-08 Add apostille metadata transaction
2019-04-15 Split SHA 3 from KECCAK
2019-04-16 Add implementation source