Skip to content

1 Client SDK

Senthilnathan Natarajan edited this page May 27, 2020 · 3 revisions

Go API for client

Client SDK expose multiple APIs

Connection to Blockchain DB done by using Open() API, exposed by Client SDK as well.

// Open opens an existing db associated with the dbName
// DBOptions may specify:
// 1. Required transaction isolation level
// 2. Number of servers used to read data
// 2. Number of responses should be collected by Client SDK during Commit() call
//    to return success to Client
func Open(dbName string, options DBOptions) (DB, error)

Part of DBOptions are client Certificate and Private key, that will be used to sign transactions, authenticate communication with server and so on. The idea to provide private key during db connection is to store it as part of SDK connect data and this way SDK will hide all cryptography from user application.

Query APIs mentioned above are part of DB interface. In addition to queries, DB interface contains method to initialize transactions - Begin()

// DB provides APIs to begin a transaction context, to perform provenance queries, and close the db connection.
type DB interface {
    // Begin initializes a transaction context
    // TxOptions may override DBOptions:
    // 1. Required transaction isolation level
    // 2. Number of servers used to read data during Tx creation/execution
    // 3. Number of responses should be collected by Client SDK during Commit() call
    //    to return success to Client
    Begin(options TxOptions) (TxContext, error)
    // Close closes the connection to DB
    Close() error
    // DataQuerier provides APIs to query states from the database
    DataQueries
    // Provenance provides APIs to access historical data
    Provenance
    // UserQuerier provides APIs to query existing users
    UserQuerier
}

In addition to queries, transaction context API provided as well. It covers both standard KV Store - Get(), Put(), Delete() and user management API - GetUser(), Adduser(), UpdateUser() and DeleteUser()

Invocation of transaction statements between Begin() and Commit() calls inside TxContex, results in Transaction envelope created and sent to server. During Tx creation, all RWSets and Statements packed inside transaction envelope payload, client identity added to envelope payload header, payload signed and signature added to envelope. For full envelope structure, see Transaction document.

Commit() call returns only after required number of tx responses collected from db nodes. To understand how responses collected and what response structure, see Server APIs. Please note that Commit() returns Digest structure, contains root of merkle tree and ledger height.

To make user management methods calls part of regular transaction, during transaction execution phase in SDK, we add to each transaction RSet the user who submitted it, including version. This way we will discover conflicts between transactions that update the user and transactions submitted by the user.

// TxContext provides APIs to both query and modify states
type TxContext interface {
    DataQuerier
    // Put stores the given key and value
    Put(key string, value []byte) error
    // Delete deletes the given key
    Delete(key string) error
    // Users provides APIs for user management
    Users
    // Commit commits the transaction and return the
    // block merkel tree root and the block number at which
    // the transaction got added
    Commit() (*Digest, error)
    // Cancel transaction context, discard all transaction
    // data
    Abort() error
}


// API to manage BlockchainDB users, accessible only to users with Admin role
type User interface {
    UserQueries
    // AddUsers adds a new user to the DB
    AddUser(user User) error
    // UpdateUser updates an existing user in the DB
    UpdateUser(user User) error
    // DeleteUser deletes an existing user in the DB
    DeleteUser(user User) error
}

Client SDK exposes multiple query APIs: data queries, provenance and integrity data queries and db user queries.

// DataQuerier provides API to query states from the DB
type DataQuerier interface {
    Get(key string) ([]byte, error)
}

// Provide access to historical data and dat integrity proofs
type Provenance interface {
    // GetValueAtTime returns the value of a key at a given time
    GetValueAtTime(key string, date time.Time) (*HistoricalValue, error)
    // GetHistoryIterator returns an iterator to iter over the historical
    // value of a given key.
    GetHistoryIterator(key string, opt QueryOption) (HistoryIterator, error)
    // GetTxProof return a proof for a given txId so that the caller can
    // validate the authenticity of the transaction.
    GetTxProof(txId string) (*Proof, error)
    // GetMerkleRoot returns the current block merkle root hash and the last committed
    // block number
    GetMerkleRoot() (*Digest, error)
}

type Digest struct {
    rootHash []byte
    blockNum uint64
}
type Proof struct {
    // Path to tx inside block
    blockpath []Hash
    // Path to block inside dynamic ledger merkle tree combined with ledger merkle list
    ledgerpath []Hash
    // tx signatures
    txsignature []Signature
    // block signature
    blocksignature []Signature
}

type HistoryIterator interface {
    Next() (*HistoricalValue, error)
    Close()
}

// Access db user data 
type UserQuerier interface {
    // GetUsers returns all users in the DB
    GetUsers() []User
    // GetUsersForRole returns all users in the DB with a given role
    GetUsersForRole(role Role) []User
}

Collecting transaction responses not exposed to Client and there is no API for that. Policy how many responses to collect defined during Open() or Begin() calls and Tx response structure described in Server APIs

Clone this wiki locally