I recently discovered a very nice tool that makes the protocol makers life easier. It behaves as protocol descriptor system as well as compiler to generate the needed protocol data structures to many languages such C++, Java, Python, Javascript, etc. In addition it generates accessors functions in order to ease the access to the structure data and raise exception when a wrong data is passed on.
Since I will work on integrating the uCoin server using Python and C++ later on, I was looking for a solution that can help every contributors to connect easily the protocol to any applications coded around the project including contributions.
Protocol Buffers is maintained by Google and used by thousand of their projects, it helps them to guarantee backward and forward compatibility when updates are necessary.
I have ported the uCoin protocol into the protocol buffers format (.proto file), you can find it here:
package uc.protocol;
// uCoin data structures mapped from descriptions found at
// https://github.com/ucoin-io/ucoin/blob/master/doc/Protocol.md
//
// Certification
//
// The generic word certification is to be used for describing
// certification from others, i.e. non-self certifications.
//
message Certification {
// certification public key
required bytes pubkey_from = 1;
// public key whose identity is being certified
required bytes pubkey_to = 2;
// certification date
required uint32 timestamp = 3;
// certification signature
required bytes signature = 4;
}
//
// Membership
//
// A member is represented by a public key he is supposed to be the
// owner. To be integrated in a community, the newcomer owner of the
// key has to express its will to integrate the Community.
//
message Membership {
// current structure version
required uint32 version = 1;
// name of the currency
required string currency = 2;
// public key of the issuer
required bytes issuer = 3;
// create date of this message, timestamp, this date may be
// different from signature's date
required uint32 date = 4;
// state used by membership field
enum State {
IN = 0;
OUT = 1;
}
// membership message, value is either IN or OUT to express
// whether a member wishes to opt-in or opt-out the community
required State membership = 5;
// identity to use for this public key
required string userid = 6;
// certification of identity date
required uint32 certts = 7;
extensions 100 to 199;
}
//
// Transaction
//
// Transaction is the support of money, it allows to materialize
// coins' ownership.
//
message Transaction {
// current structure version
required uint32 version = 1;
// name of the currency
required string currency = 2;
message Issuer {
// issuer public key
required bytes pubkey = 1;
// sequential inter
required uint32 index = 2;
}
// list of public key, followed by a sequential integer
repeated Issuer issuers = 3;
message Input {
// index
required uint32 index = 1;
enum Source {
T = 0;
D = 1;
F = 2;
}
// source of coin
required Source source = 2;
// a sha-1 hash fingerprint
required bytes fingerprint = 3;
// amount
required uint32 amount = 4;
}
// list of linking issuers (via index) to coin sources
repeated Input inputs = 4;
message Output {
// a sha-1 hash fingerprint
required bytes fingerprint = 1;
// amount
required uint32 amount = 2;
}
// list of public keys and amounts allowed to them
repeated Output outputs = 5;
// signatures of issuers
repeated bytes signatures = 6;
extensions 100 to 199;
}
//
// Block
//
// A Block is a document gathering both:
// * Public key data in order to build a Web Of Trust (WoT) representation
// * Transaction data to identify money units & ownership
//
message Block {
// document version
required uint32 version = 1;
// document type
optional string type = 2 [default = "Block"];
// currency name
required string currency = 3;
// arbitrary nonce value
required uint32 nonce = 4;
// keyblock number
required uint32 number = 5;
// generation date
required uint32 date = 6;
// last confirmed date
required uint32 confirmed_date = 7;
// universal dividend amount
optional uint32 universal_dividend = 8;
// fees amount
required uint32 fees = 9;
// public key of the block issuer
required bytes issuer = 10;
// previous keyblock fingerprint (sha-1)
optional bytes previous_hash = 11;
// previous keyblock issuer public key
optional bytes previous_issuer = 12;
// number of members in the WoT, this block included
required uint32 members_count = 13;
message Identity {
required bytes pubkey = 1;
required bytes signature = 2;
required uint32 timestamp = 3;
required string user_id = 5;
}
// new identities in the WoT
repeated Identity identities = 14;
message Joiner {
required bytes pubkey = 1;
required bytes signature = 2;
required uint32 timestamp = 3;
required uint32 certts = 4;
required string user_id = 5;
}
// IN memberships
repeated Joiner joiners = 15;
message Leaver {
required bytes pubkey = 1;
required bytes signature = 2;
required uint32 timestamp = 3;
}
// OUT memberships
repeated Leaver leavers = 16;
// Excluded members public key
repeated bytes excluded = 17;
// Certifications
repeated Certification certifications = 18;
// List of compact transactions
repeated Transaction transactions = 19;
extensions 100 to 199;
}
//
// Blockchain
//
// A Blockchain is a chaining of Blocks. Such a structure describes a
// WoT + Transactions over the time.
//
message Blockchain {
// list of blocks
repeated Block blocks = 1;
}
//
// Peer
//
// UCP uses P2P networks to manage community & money data. Since only
// members can write to the Blockchain, it is important to have
// authenticated peers so newly validated blocks can be efficiently
// sent to them, without any ambiguity.
//
message Peer {
// current structure version
required uint32 version = 1;
// currency name
required string currency = 2;
// public key of the node
required bytes public_key = 3;
message Endpoint {
// protocol name
optional string protocol_name = 1 [default = "BASIC_MERKLED_API"];
// dns name
optional string dns = 2;
// ipv4
optional string ipv4 = 3;
// ipv6
optional string ipv6 = 4;
// port number
optional uint32 port = 5;
}
// a list of endpoints to interact with the node
repeated Endpoint endpoints = 4;
extensions 100 to 199;
}
message Status {
// current structure version
required uint32 version = 1;
// currency name
required string currency = 2;
enum StatusChoice {
ASK = 0;
NEW = 1;
NEW_BACK = 2;
UP = 3;
UP_BACK = 4;
DOWN = 5;
}
// status type
required StatusChoice status = 3;
// currrent nodes timestamp
required uint32 time = 4;
// public key of the issuer for this message
required bytes issuer = 5;
// public key of the recipient for this message
required bytes recipient = 6;
extensions 100 to 199;
}
For instance, you can build for Python using the following command line:
protoc --python_out=. ucoin.proto