2021SC@SDUSC
目錄
- 一、資料賬本的設計核心
- 1.資料賬本模型
- 二、資料賬本的介紹
- 三、合約樣例一覽
- 1.設定KV
- 2.注冊用戶、資料賬戶、事件賬戶
- 4.發布事件
- 四、支持資料型別
一、資料賬本的設計核心
1.資料賬本模型
資料賬本的核心任務是對資料進行有效地組織和管理,因此,需要定義資料的結構和資料處理的操作模型,
JD Chain的資料賬本模型以“鍵值”結構來組織業務資料,定義標準的讀寫操作,記錄資料變更歷史,維護資料完整性與不可否認性,管理資料的存在性證明,
二、資料賬本的介紹
資料賬本為各參與方提供區塊鏈底層服務功能,包括區塊、賬戶、配置和存盤等,
區塊是JD Chain賬本主要組成部分,包含交易資訊和交易執行狀態的資料快照哈希值,但不存盤具體的交易操作和狀態資料,JD Chain將賬本狀態和合約進行分離,并約束合約對賬本狀態的訪問,來實作資料與邏輯分離,提供無狀態邏輯抽象,
JD Chain通過細化賬戶分類、分級分類授權的方式,對區塊鏈系統中的賬戶進行管理,達到邏輯清晰化、隔離業務和保護相關資料內容的目的,
組態檔包括密鑰資訊,存盤資訊以及共享的參與者身份資訊等內容,使JD Chain系統中各節點能夠執行諸如連接其他節點、驗證資訊、存盤并更新賬本等操作,
存盤格式采用簡潔的KV資料型別, 使用較為成熟的NoSQL資料庫來實作賬本的持久化存盤,使區塊鏈系統能夠支持海量交易,
三、合約樣例一覽
提供通過合約創建用戶/資料賬戶/事件賬戶,寫入KV,發布事件等功能
1.設定KV
/**
* 設定KV
*
* @param address 資料賬戶地址
* @param key 鍵
* @param value 值
* @param version 版本
*/
@ContractEvent(name = "setKVWithVersion")
void setKVWithVersion(String address, String key, String value, long version);
/**
* 設定KV,基于最新資料版本
*
* @param address 資料賬戶地址
* @param key 鍵
* @param value 值
*/
@ContractEvent(name = "setKV")
void setKV(String address, String key, String value);
如上代碼,我們可以看到,第一段代碼呼叫了setKVWithVersion的方法,該方法可以幫助初始資料賬戶、鍵、值、以及版本的資訊,
@Override
public void setKVWithVersion(String address, String key, String value, long version) {
eventContext.getLedger().dataAccount(Bytes.fromBase58(address)).setText(key, value, version);
}
第二段代碼的setKV可以基于最新版本的KV進行設定,if陳述句用于判別該版本是否為最新版本,若不為最新版本則version = entries[0].getVersion();該陳述句可以更新到最新版本,
@Override
public void setKV(String address, String key, String value) {
// 查詢最新版本,初始為-1
// 查詢已提交區塊資料,不包括此操作所在未提交區塊的所有資料
// TypedKVEntry[] entries = eventContext.getLedger().getDataEntries(eventContext.getCurrentLedgerHash(), address, key);
// 可查詢包括此操作所在未提交區塊的所有資料
TypedKVEntry[] entries = eventContext.getUncommittedLedger().getDataEntries(address, key);
long version = -1;
if (null != entries && entries.length > 0) {
version = entries[0].getVersion();
}
eventContext.getLedger().dataAccount(Bytes.fromBase58(address)).setText(key, value, version);
}
2.注冊用戶、資料賬戶、事件賬戶
/**
* 注冊用戶
*
* @param seed 種子,不小于32個字符
*/
@ContractEvent(name = "registerUser")
String registerUser(String seed);
/**
* 注冊資料賬戶
*
* @param seed 種子,不小于32個字符
*/
@ContractEvent(name = "registerDataAccount")
String registerDataAccount(String seed);
/**
* 注冊事件賬戶
*
* @param seed 種子,不小于32個字符
*/
@ContractEvent(name = "registerEventAccount")
String registerEventAccount(String seed);
如上代碼分別使用了三個方法
1.這一段代碼使用了registerUser(String seed)、getAlgorithm(“ed25519”)、getSignatureFunction(algorithm)、generateKeypair(seed.getBytes())、getPrivKey()、getPubKey()的方法用于獲取用戶輸入的密碼賬號名等資訊
return keypair.getAddress().toBase58();最侄訓回傳一個郵箱的資訊,該資訊的格式是Base58,
@Override
public String registerUser(String seed) {
CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519");
SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm);
AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes());
BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());
eventContext.getLedger().users().register(keypair.getIdentity());
return keypair.getAddress().toBase58();
}
2.下面兩段代碼與上面一段代碼可以當作類似來處理,
@Override
public String registerDataAccount(String seed) {
CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519");
SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm);
AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes());
BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());
eventContext.getLedger().dataAccounts().register(keypair.getIdentity());
return keypair.getAddress().toBase58();
}
@Override
public String registerEventAccount(String seed) {
CryptoAlgorithm algorithm = Crypto.getAlgorithm("ed25519");
SignatureFunction signFunc = Crypto.getSignatureFunction(algorithm);
AsymmetricKeypair cryptoKeyPair = signFunc.generateKeypair(seed.getBytes());
BlockchainKeypair keypair = new BlockchainKeypair(cryptoKeyPair.getPubKey(), cryptoKeyPair.getPrivKey());
eventContext.getLedger().eventAccounts().register(keypair.getIdentity());
return keypair.getAddress().toBase58();
}
4.發布事件
/**
* 發布事件
*
* @param address 事件賬戶地址
* @param topic 訊息名稱
* @param content 內容
* @param sequence 當前訊息名稱下最大序號(初始為-1)
*/
@ContractEvent(name = "publishEventWithSequence")
void publishEventWithSequence(String address, String topic, String content, long sequence);
/**
* 發布事件,基于最新時間序號
*
* @param address 事件賬戶地址
* @param topic 訊息名稱
* @param content 內容
*/
@ContractEvent(name = "publishEvent")
void publishEvent(String address, String topic, String content);
上面的代碼使用了如下的方法
1.呼叫這個方法可以調取事件的各項資訊進行發布
@Override
public void publishEventWithSequence(String address, String topic, String content, long sequence) {
eventContext.getLedger().eventAccount(Bytes.fromBase58(address)).publish(topic, content, sequence);
}
2.下面這段代碼用if陳述句判斷事件是否為空,若不為空則可以獲取用getSequence()方法來獲取event的時間序列,以達成案最新時間序列輸出的功能,
@Override
public void publishEvent(String address, String topic, String content) {
// 查詢最新序號,初始為-1
// 查詢已提交區塊資料,不包括此操作所在未提交區塊的所有資料
// Event event = eventContext.getLedger().getRuntimeLedger().getLatestEvent(address, topic);
// 可查詢包括此操作所在未提交區塊的所有資料
Event event = eventContext.getUncommittedLedger().getLatestEvent(address, topic);
long sequence = -1;
if (null != event) {
sequence = event.getSequence();
}
eventContext.getLedger().eventAccount(Bytes.fromBase58(address)).publish(topic, content, sequence);
}
四、支持資料型別
setText,字符型別
setInt64,長整型
setJSON,JSON串
setBytes,位元組陣列
setTimestamp,時間戳,長整型
setXML,XML文本
setImage,圖片位元組資料
本質上僅支持String/Long/[]byte這三種資料型別,JSON/XML/Image/Timestamp等起標識作用,用于擴展差異化資料展示等場景需求
setText(“key1”, “value1”, -1)中第三個引數即為資料版本,需要傳入JD Chain網路中當前key1的最高資料版本,首次寫入時傳入-1,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/307376.html
標籤:區塊鏈
