CircleChain总体技术方案
CircleChain是基于区块链技术构建的资产管理平台。其技术基础来源于比特币底层的区块链技术,但与比特币技术有所区别。比特币是基于P2P的客户端应用程序,将数字货币存储在本地数据库中。而CircleChain是基于云端分布式解决方案,利用区块链加密技术构建的大数据资产管理平台。其应用范围比比特币更广泛,具有更强的扩展性。
总体技术架构
整个框架分为以下几个主要部分:
- API层 - 对外提供接口服务
- 后台服务与事件处理 - 核心业务逻辑和事件处理
- 后台任务 - 定时任务和后台处理
- 配置中心 - 系统配置管理
- 存储层 - 数据持久化存储
API层
API分为以下几类:
- 账户API - 对外网用户提供账户管理服务
- 钱包API - 对外网用户提供钱包管理服务
- 区块API - 对外网用户提供区块链数据查询服务
- 云节点API - 对CircleChain内网提供云节点相关功能接口
- 矿工节点API - 对CircleChain内网提供矿工相关接口
API说明
CircleChain采用RESTful接口设计,数据格式为JSON,请求头Content-Type
为"application/json"。
账户APIs
账户API是公网API,部分接口需要用户登录后才能调用,具体可参考以下文档说明。
发送注册验证码(sendRegisterVerifyCode)
路径:/user/v1/node/register/send-verify-code
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
phone | String | optional | Phone和email不能同时为空 |
String | optional | Phone和email不能同时为空 |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | Boolean | optional | success or failure |
接口说明:
用户在注册前需要发送注册验证码。如果输入邮箱,验证码将发送到您的邮箱;如果输入手机号,验证码将通过短信发送到您的手机上。
注册(register)
路径:/user/v1/node/register
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
phone | String | optional | Phone和email不能同时为空 |
String | optional | Phone和email不能同时为空 | |
passwordInput1 | String | required | 第一次输入的密码 |
passwordInput2 | String | required | 第二次输入的密码 |
verifyCode | String | required | 验证码,通过接口sendRegisterVerifyCode 发送。 |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - 成功, 其他失败 |
message | String | required | 消息 |
data | Boolean | optional | 成功或失败 |
接口说明:
用户注册接口,用于创建新用户账户。
发送登录验证码(sendVerifyCode)
路径:/user/v1/node/send-verify-code
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
phone | String | optional | Phone和email不能同时为空 |
String | optional | Phone和email不能同时为空 |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - 成功,其他值为失败 |
message | String | required | 结果消息 |
data | Boolean | optional | 布尔值,成功或失败 |
接口说明:
在登录前需要调用发送登录验证码接口。如果输入邮箱,验证码将发送到您的邮箱;如果输入手机号,验证码将通过短信发送到您的手机上。
登录接口(login)
路径:/user/v1/node/login
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
phone | String | optional | Phone和email不能同时为空 |
String | optional | Phone和email不能同时为空 | |
verifyCode | String | optional | 验证码登录,由接口 sendVerifyCode 发出。verifyCode 和password ,您选择一个输入就可以了 |
password | String | optional | 密码登录,verifyCode 和password ,您选择一个输入就可以了 |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - 成功,其他值均表示失败。 |
message | String | required | 接口返回消息 |
data | UserLoginResult | optional | 用户登录结果数据 |
UserLoginResult:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
userId | String | required | 用户 id |
sessionKey | String | required | 登录的session key |
sex | byte | optional | 用户性别 |
success | Boolean | required | 布尔值,成功或失败 |
接口说明:
用户登录接口,登录成功之后,您将得到一个 sessionKey
值,小心保管这个数据,这个值确保您是登录用户。在调用需要登录情况下的接口里,需要将 sessionKey
设置到您调用接口的header中:
{
"AuthorizationV2": “<sessionKey>”
}
登出接口(logout)
路径:/user/v1/node/logout
Method: POST
请求对象:
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - 成功,其他值均表示失败。 |
message | String | required | 接口返回消息 |
data | Boolean | optional | 布尔值,成功或失败 |
接口说明:
用户登出接口,用于终止当前会话。
发送设置支付密码验证码接口(sendPayVerifyCode)
路径:/user/v1/node/pay/send-verify-code
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
phone | String | optional | Phone和email不能同时为空 |
String | optional | Phone和email不能同时为空 |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - 成功,其他值均表示失败 |
message | String | required | 接口返回消息 |
data | Boolean | optional | 布尔值,成功或失败 |
接口说明:
在设置支付密码时需要发送验证码。如果输入邮箱,验证码将发送到您的邮箱;如果输入手机号,验证码将通过短信发送到您的手机上。
设定支付密码(setPayPassword)
路径:/user/v1/node/pay/set-password
Method: POST
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
account | AccountPO | required | account |
verifyCode | String | required | the verify code sent by sendPayVerifyCode |
password | String | required | the new pay password. |
AccountPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
phone | String | optional | Phone and email should not be empty either. |
String | optional | Phone and email should not be empty either. | |
encryptedPassword | String | Optional | the password encrypted by user public key, it can be empty here. |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | Boolean | optional | success or failure |
接口说明:
设置用户支付密码。
是否设定支付密码(havePayPassword)
路径:/user/v1/node/have-pay-password
Method: GET
请求对象:
请求头: { AuthorizationV2: "<sessionKey>" }
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | Boolean | optional | have or not set. |
接口说明:
检查用户是否已设置支付密码。
发送重置密码验证码(sendResetPasswordVerifyCode)
路径:/user/v1/node/reset-password/send-verify-code
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
phone | String | optional | Phone and email should not be empty either. |
String | optional | Phone and email should not be empty either. |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | Boolean | optional | success or failure |
接口说明:
用户在重置密码前需要发送重置密码验证码。如果输入邮箱,验证码将发送到您的邮箱;如果输入手机号,验证码将通过短信发送到您的手机上。
重置登录密码(resetPassword)
路径:/user/v1/node/reset-password
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
account | AccountPO | required | account |
verifyCode | String | required | the verify code sent by sendResetPasswordVerifyCode |
password1 | String | required | new login password |
password2 | String | required | password confirmed |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | Boolean | optional | success or failure |
接口说明:
用户重置登录密码接口。
保存用户信息(saveOrUpdateUserInfo)
路径:/user/v1/node/save-or-update-userinfo
Method: POST
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
userId | String | required | user id |
name | String | required | user name |
phone | String | optional | user phone |
sex | Byte | optional | 1: man 0 woman |
icon | String | optional | user icon |
address | String | optional | user address |
motherLang | Integer | required | 0 English 1 Chinese 2 Japanese 3 French 4 German 5 Italian 6 Korea 7 Thai |
String | optional | wechat account | |
entWechat | String | optional | enterprise WeChat account |
dingtalk | String | optional | dingtalk account |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | Boolean | optional | success or failure |
接口说明:
保存或更新用户信息接口。
获取用户信息(getUserInfoPO)
路径:/user/v1/node/get-user-info
Method: GET
请求对象:
请求头: { AuthorizationV2: "<sessionKey>" }
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | UserInfoPO | optional | user info data |
UserInfoPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
userId | String | required | user id |
name | String | required | user name |
phone | String | optional | user phone |
sex | Byte | optional | 1: man 0 woman |
icon | String | optional | user icon |
address | String | optional | user address |
motherLang | Integer | required | 0 English 1 Chinese 2 Japanese 3 French 4 German 5 Italian 6 Korea 7 Thai |
String | optional | wechat account | |
entWechat | String | optional | enterprise WeChat account |
dingtalk | String | optional | dingtalk account |
接口说明:
获取当前登录用户信息接口。
添加联系方式(addContacts)
路径:/user/v1/node/add-contacts
Method: POST
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
name | String | required | user name |
phone | String | required | user phone |
sex | Byte | optional | 1: man 0 woman |
icon | String | optional | user icon |
address | String | required | user address |
description | String | optional | description |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | Boolean | optional | success or failure |
接口说明:
添加联系人信息到用户通讯录。
查询用户联系方式(listContacts)
路径:/user/v1/node/list-contacts
Method: GET
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | contact data list |
ContactPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
name | String | required | user name |
phone | String | required | user phone |
sex | Byte | optional | 1: man 0 woman |
icon | String | optional | user icon |
address | String | required | user address |
description | String | optional | description |
接口说明:
查询用户通讯录中的联系人列表。
钱包APIs
以下是钱包服务的API,大部分接口需要用户登录后才能调用。
创建钱包(createWallet)
路径:/wallet/v1/node/createWallet
Method: POST
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | String | optional | address of the wallet |
接口说明:
创建钱包接口,需要用户登录后才能调用。每个用户最多可创建3个钱包。
查询钱包(listWallet)
路径:/wallet/v1/node/listWallet
Method: GET
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
phone | String | optional | list the phone's address. If not set, list his own address. |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | address of the wallet |
接口说明:
此接口仅限登录用户访问。根据手机号查询该手机号下的钱包地址数量。手机号可以是自己的,也可以是其他人的。如果不填写手机号,则查询当前登录用户名下的地址列表。
查询地址余额(getBalanceOfAddress)
路径:/wallet/v1/node/getBalanceOfAddress
Method: GET
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
address | String | required | the address |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | Long | optional | The balance value for the address |
接口说明:
查询指定地址的余额。仅限登录用户调用此接口。
批量查询地址余额(getBalanceByAddressList)
路径:/wallet/v1/node/getBalanceByAddressList
Method: GET
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
addressList | String | required | the address list join by "," |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | The balance value for the address |
BalanceVO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
confirmed | Long | required | confirmed balance |
unconfirmed | Long | required | unconfirmed balance |
接口说明:
批量查询地址余额接口。仅限登录用户调用此接口。
查询钱包余额(getBalanceOfWallet)
路径:/wallet/v1/node/getBalanceOfWallet
Method: GET
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | The balance value for the address |
WalletSpentInfo:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
address | String | required | address |
balance | Long | required | the balance |
spent | Long | required | the spent balance |
接口说明:
查询登录用户的所有钱包余额信息。
查询钱包资产信息(getAssetsOfWallet)
路径:/wallet/v1/node/getBalanceOfWallet
Method: GET
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | AssetsInfo | optional | The balance value for the address |
AssetsInfo:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
balance | Long | required | the total balance of the user |
IdentityNum | Integer | required | the count of identity assets |
ownershipNum | Integer | required | the count of ownership assets |
walletNum | Integer | required | the count of wallets |
接口说明:
查询登录用户钱包的资产汇总信息。
查询地址的资产信息(getAssetsOfAddress)
路径:/wallet/v1/node/getAssetsOfAddress
Method: GET
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
address | String | required | the address |
type | Integer | required | the asset type: 1 ownership, 2 identity |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | The balance value for the address |
AddressAssetsInfo:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
address | String | required | the address |
type | Integer | required | asset type: 1 ownership, 2 identity |
txId | String | required | the transaction id |
idx | Integer | required | the output index of the transaction |
value | String | required | the asset value, encoding with hex |
doubleHashHex | String | optional | the asset data double hash hex data |
接口说明:
查询指定地址下的所有资产信息。仅限登录用户调用此接口。
获取公钥Hash(getPubKeyHashFromAddress)
路径:/wallet/v1/node/getPubKeyHashFromAddress
Method: GET
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
name | type | requred | description |
---|---|---|---|
address | String | required | the address |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | String | optional | public key hash encoding hex string |
接口说明:
从指定地址中获取对应的公钥哈希值。
发送资产接口(sendTo)
路径:/wallet/v1/node/sendTo
Method: POST
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
from | String | required | the from address |
address | String | required | the to address |
receivePhone | String | optional | received phone |
String | optional | received email | |
transContent | TransactionContentPO | required | the transfer content data |
payPassword | String | required | the payment password |
TransactionContentPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
type | Integer | required | 交易类型: 1 ownership, 2 identity |
valueHex | String | optional | Hex值字串, deprecated. |
uuid | String | optional | 资产的UUID值 |
hash | String | optinal | 资产数据HASH数据 |
注:如果邮箱或手机号非空,请确保
address
属于此用户。
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | Boolean | optional | success or failure |
接口说明:
向指定地址发送数字资产。
支付(pay)
路径:/wallet/v1/node/pay
Method: POST
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
from | String | required | the from address |
to | String | required | the to address |
receivePhone | String | optional | received phone |
String | optional | received email | |
value | Long | required | the balance value |
payPassword | String | required | the payment password |
注:如果填写了邮箱或手机号,请确保
to
地址属于此用户。
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | Boolean | optional | success or failure |
接口说明:
向指定地址支付CC币。
根据类型查询交易(searchTxByType)
路径:/wallet/v1/node/searchTxByType
Method: GET
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
type | Integer | required | 0 balance 1 ownership 2 identity |
pageNo | Integer | optional | default 1 |
pageSize | Integer | optional | default 10 |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | transaction info list. |
TransactionInfo:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
fromAddress | String | required | the from address |
toAddress | String | required | the to address |
txId | String | required | the transaction id |
idx | Integer | required | the output index of the transaction |
txType | Integer | required | the transactfion type: 0 balance, 1 ownership, 2 identity |
inOut | String | required | IN: input, OUT: output |
value | String | required | the balance/asset value |
timestamp | String | required | the transaction create timestamp in the 'YYYY-mm-dd HH:MM:SS' date format |
接口说明:
根据交易类型查询交易列表。
根据时间查询交易(searchTxByTime)
路径:/wallet/v1/node/searchTxByTime
Method: GET
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
startTime | Long | required | the stat time in milliseconds |
endTime | Long | required | the end time in milliseconds. |
pageNo | Integer | optional | default 1 |
pageSize | Integer | optional | default 10 |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | transaction info list. |
TransactionInfo 定义请见之前说明。
接口说明:
根据时间范围查询交易列表。
区块APIs
以下是区块服务的API,这些API不需要用户登录,匿名用户可直接访问。
获取区块Hash列表(getBlockHashList)
路径:/block/v1/node/get-block-hashList
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
baseHeight | Long | required | The start height |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | block hash list |
接口说明:
公网接口,无需用户登录。
根据起始区块高度,批量查询后续区块哈希列表。
获取区块数据(getBlock)
路径:/block/v1/node/get-block
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
hash | String | required | the block hash |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | BlockPO | optional | block hash list |
BlockPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
header | BlockHeaderPO | required | block header |
dataHexStr | String | required | block data hex string |
接口说明:
公网接口,无需用户登录。
根据区块哈希获取对应的区块数据。
获取区块头信息列表(getBlockHeaderList)
路径:/block/v1/node/get-block-header-list
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
baseHeight | Long | required | The start height |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | block header list |
BlockHeaderPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
hash | String | required | block hash |
minedTimestamp | Long | required | the mined timestamp |
version | String | required | the version |
height | Long | required | the height of the block |
prevBlockHash | String | required | the previous block hash |
merkleTreeRoot | String | required | the merkle tree root |
minerIpPort | String | optional | the miner ipPort |
minerInfo | String | optional | the miner info |
timeStamp | Long | required | the block create timestamp |
difficulty | Long | required | the difficulty of the block |
nonce | Long | required | the nonce. |
接口说明:
公网接口,无需用户登录。
根据起始高度,批量查询区块头信息列表。
获取区块内部数据(getBlockData)
路径:/block/v1/node/get-block-data
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
hash | String | required | the block hash |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | String | optional | the block data encoding in hex string |
接口说明:
公网接口,无需用户登录。
根据区块哈希,获取对应的区块内部数据。
获取区块尾hash列表(getBlockTailsHashList)
路径:/block/v1/node/get-blocktails-hashList
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
baseHeight | Long | required | the start height to get |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | block tails hash list |
接口说明:
公网接口,无需用户登录。
根据起始高度,批量获取区块尾哈希列表。
获取区块尾数据(getBlockTailsPO)
路径:/block/v1/node/get-blocktails-po
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
hash | Long | required | the block hash |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | BlockTailsPO | optional | block tails data |
BlockTailsPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
height | Long | required | the block height |
hash | String | required | the block hash |
hashCrc32 | Integer | required | the block hash crc32 value |
prevHash | String | required | the previous block hash |
isMaster | Byte | required | 0 slave 1 master |
接口说明:
公网接口,无需用户登录。
根据区块哈希,获取对应的区块尾数据。
获取交易(getTxByTxId)
路径:/block/v1/node/gettx-by-txid
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
txIdStr | String | required | tx id hex string |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | TransactionDetail | optional | transaction detail. |
TransactionDetail:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
blockHash | String | required | block hash |
height | Long | required | the block height |
txIdHexStr | String | required | the transaction id |
type | Integer | required | the transaction type: 0 balance, 1 ownership, 2 identity |
inputs | List |
required | inputs of transaction |
outputs | List |
required | outputs of transaction |
createTime | Long | required | the create time for the transaction |
minedTimestamp | Long | required | the block mined timestamp |
sendersPubKeyHash | List |
required | the sender public key hash list |
receiversPubKeyHash | List |
required | the receiver public key hash list |
confirmations | Long | required | the confirmation of the block. |
TXInputPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
txIdStr | String | required | tx id hex string |
txOutputIndex | Integer | required | the output index for the transaction |
unlockScript | String | required | the unlock script encoding hex string |
value | String | required | the value |
serialNO | Integer | required | the serial NO. |
addressList | List |
required | the inputs' address list. |
TXOutputPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
txIdStr | String | required | tx id hex string |
idx | Integer | required | the output index for the transaction |
status | Integer | required | Status: 0 unspent, 1 spent |
value | String | required | the value |
lockScript | String | required | the lock script encoding hex string |
addressList | List |
required | the outputs' address list. |
接口说明:
公网接口,无需用户登录。
根据交易ID,获取其对应的唯一交易数据。
批量获取交易(getTransactionsByTxIdList)
路径:/block/v1/node/gettx-by-txid-list
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
txIdList | List |
required | tx id list |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | transaction details |
TransactionDetail: more detail see above.
接口说明:
公网接口,无需用户登录。
根据交易ID列表,批量获取其对应的交易数据列表。
查询交易数据(searchTxByTxId)
路径:/block/v1/node/search-tx-by-txid
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
txIdStr | String | required | tx id hex string |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | transaction details |
接口说明:
公网接口,无需用户登录。
根据交易ID,查询与其相关的所有交易数据。
获取地址相关交易(searchTxByAddress)
路径:/block/v1/node/search-tx-by-address
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
address | String | required | the address |
minOutputKey | String | optional | Default "" |
limit | Integer | optional | Default 100 |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | AddressTxInfo | optional | address transaction info data |
AddressTxInfo:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
address | String | required | the address |
pubKeyHash | String | required | public key hash |
txDetailList | List |
required | Transaction detail list |
minOutputKey | String | required | the minOutputKey for the next query |
TransactionDetail: more details see above.
注:在第一次查询之后,我们需要设定
minOutputKey
值。第一次查询时,我们可以获取到AddressTxInfo
数据, 它有一个minOutputKey
字段
接口说明:
公网接口,无需用户登录。
根据地址和最小输出键,批量查询相应的交易数据列表。
获取所有未花费UTXO(searchUtxos)
路径:/block/v1/node/search-utxos
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
address | String | required | the address |
minOutputKey | String | optional | Default "" |
limit | Integer | optional | Default 100 |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | AddressUTXOInfo | optional | address transaction info data |
AddressUTXOInfo:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
address | String | required | the address |
pubKeyHash | String | required | public key hash |
outputs | List |
required | the uxto outputs. |
TxOutputPO: more detail see above
注: 在第一次查询之后,我们需要设定
minOutputKey
值。第一次查询时,我们可以获取AddressUTXOInfo
数据, 这个字段有一个outputs
,它的类型是TXOutputPO
. 这个列表是按数据库id从小到大排充的。所以我们可以通过以下代码获取minOutputKey
:
TXOutputPO lastItem = outputs.get(outputs.size() - 1);
String minOutputKey = lastItem.getTxIdStr() + ":" + lastItem.getTxOutputIndex();
接口说明:
公网接口,无需用户登录。
根据地址和最小输出键,批量查询相应的UTXO数据列表。
云节点APIs
以下接口均为内网接口,仅限符合内网标准的用户访问。普通用户无法调用这些接口。
All the request and response content type is "application/json"
心跳(heartbeat)
路径:/coulder/v1/node/heartbeat
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
requestId | String | optional | |
version | String | required | such as '1.0.0' |
role | String | required | CLOUDER, MINER |
protolVersion | String | required | such as '1.0.0' |
publicIP | String | required | |
localIP | String | required | |
port | Integer | required | such as 80 |
ipPort | String | required | such as '123.23.45.23:80' |
heartBeatPO | HeartBeatPO | required |
HeartBeatPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
baseHeight | Long | required | the base height of the node |
ipPortList | List |
required | the neighbors ipPort list of the node |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the mesage |
data | HeartBeatInfo | optional | the heartbeat info data |
HeartBeatInfo:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
heartBeatPO | HeartBeatPO | required | heartbeat po |
publicIP | String | required | public ip |
localIP | String | required | local ip |
port | Integer | required | such as 80 |
publicKey | String | required | public key hex string |
heartBeanSign | String | required | the sign data for the hearbeatPO |
接口说明:
节点心跳接口,用于维护节点间的连接状态。
获取区块Hash列表(getBlockHashList)
路径: /coulder/v1/node/getBlockHashList
Mthod: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
baseHeight | Integer | required | the start height |
ipPort | String | required | the remote node ipPort, such as '123.23.45.23:80' |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | the block hash list |
接口说明:
根据起始区块高度和远程地址,从远程服务中批量获取区块哈希列表,每次拉取100个。
获取区块数据(getBlock)
路径:/coulder/v1/node/getBlock
Mthod: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
hash | String | required | the block hash |
ipPort | String | required | the remote node ipPort |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | BlockPO | optional | the block data. |
BlockPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
header | BlockHeaderPO | required | block header |
dataHexStr | String | required | block data hex string |
BlockHeaderPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
hash | String | required | block hash |
minedTimestamp | Long | required | the mined timestamp |
version | String | required | the version |
height | Long | required | the height of the block |
prevBlockHash | String | required | the previous block hash |
merkleTreeRoot | String | required | the merkle tree root |
minerIpPort | String | optional | the miner ipPort |
minerInfo | String | optional | the miner info |
timeStamp | Long | required | the block create timestamp |
difficulty | Long | required | the difficulty of the block |
nonce | Long | required | the nonce. |
接口说明:
根据区块哈希和远程地址,从远程服务中获取对应的区块数据。
获取区块头列表(getBlockHeaderList)
路径:/coulder/v1/node/getBlockHeaderList
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
baseHeight | Long | required | the start height to get block header list |
ipPort | String | required | the remote node ipPort |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | the list of block headers |
接口说明:
根据当前区块高度批量获取区块头列表,每次获取100个。
获取区块内部数据(getBlockData)
路径:/coulder/v1/node/getBlockData
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
hash | String | required | the block hash |
ipPort | String | required | the remote node ipPort |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | String | optional | the block data encoding in hex string |
接口说明:
根据区块哈希,从远程服务获取对应的区块内部数据。
广播新区块(broadcastMinedBlock)
路径:/coulder/v1/node/broadcastMinedBlock
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
Block | BlockPO | required | the block data |
minerPublicKey | String | required | the miner public key |
minerPublicIP | String | required | the miner public ip |
blockSign | String | required | the block hash signed by the miner private key |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | String | optional | the result string |
接口说明:
向邻居节点广播新区块数据。
广播交易数据(brandcastTransaction)
路径:/coulder/v1/node/broadcastTransaction
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
transaction | TransactionPO | required | Transaction data |
TransactionPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
txIdHexStr | String | required | the transaction id hex string |
type | Integer | required | the transaction type: 0 balance, 1 ownership, 2 identity |
inputsHexStr | String | required | the inputs hex string |
outputsHexStr | String | required | the outputs hex string |
createTime | Long | required | the create time of the transaction |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | String | optional | transaction id hex string |
接口说明:
向邻居节点广播交易数据。
批量广播交易数据(broadcastTransactionList)
路径:/coulder/v1/node/broadcastTransactionList
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
transactionList | List |
required | Transaction list data |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | transaction id hex string list |
接口说明:
向邻居节点批量广播交易数据。
获取区块尾hash列表(getBlockTailsHashList)
路径:/coulder/v1/node/getBlockTailsHashList
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
baseHeight | Long | required | the start height to get |
ipPort | String | required | the remote node's ipPort |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | block tails hash list |
接口说明:
根据起始高度,向远程地址批量获取区块头哈希列表,每次拉取100个。
获取区块尾数据(getBlockTailsPO)
路径:/coulder/v1/node/getBlockTailsPO
Method: GET
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
hash | Long | required | the block hash |
ipPort | String | required | the remote node's ipPort |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | BlockTailsPO | optional | block tails data |
BlockTailsPO:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
height | Long | required | the block height |
hash | String | required | the block hash |
hashCrc32 | Integer | required | the block hash crc32 value |
prevHash | String | required | the previous block hash |
isMaster | Byte | required | 0 slave 1 master |
接口说明:
根据区块尾哈希,向远程地址获取对应的区块尾数据。
矿工APIs
以下是矿工内网接口。仅限符合内网标准的用户访问。普通用户无法调用这些接口。
获取矿工列表(retrieveMinerIpPortList)
路径:/miner/v1/node/retrieveMinerIpPortList
Method: POST
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
version | String | required | 0.0.1 |
role | String | required | CLOUDER, MINER etc |
protolVersion | String | required | 1.0.0 |
publicIP | String | required | public ip |
localIP | String | required | local ip |
port | Integer | required | the port |
publicKey | String | optional | the node's public key |
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | List |
optional | the ipPort list |
接口说明:
发送本节点信息,以获取相应的矿工地址列表。
服务层与事件处理
服务层和公共库包括:
- 云节点服务
- 提供云节点相关服务,主要提供内网API服务,包括但不限于区块查询、心跳、广播交易、广播区块等服务
- 矿工节点服务
- 提供云端矿工节点服务,主要提供内网API服务,包括但不限于矿工节点列表查询等服务
- 钱包节点服务
- 提供云端钱包相关服务,主要对外部C端用户提供钱包服务,包括但不限于初始化钱包、创建钱包、查询资产、交易资产等方面服务
- 区块链分叉服务
- 区块链分叉服务,内部服务,提供分叉处理功能,对外目前只提供内网的查询分叉信息服务
- 节点信息服务
- 节点信息服务,内部服务,提供内网各节点信息查询服务,信息存储在云端数据库
- 区块链公共库
- 公共库以JAR形式提供,提供核心的区块链功能。详细说明见详细说明方案部分
事件包括:
- 区块事件
- 节点接收到合法区块时,或矿工节点成功挖矿时,会对外广播区块事件
- 交易事件
- 节点接收到合法交易时,会对外广播交易事件
- 交易池事件
- 交易池事件,仅矿工节点拥有。当交易池满或时间到期时,会触发挖矿操作
后台任务
后台任务包括:
- 心跳任务
- 后台每隔10秒与周围节点同步心跳信息
- 挖矿任务
- 矿工节点任务,每隔10分钟(默认值,可配置)检查是否能启动挖矿任务,如果可以则启动挖矿
- 区块同步任务
- 后台每隔5分钟(默认值,可配置)定时与周围节点同步最新的区块信息
配置中心
配置中心包括:
- 异步线程池配置 - 配置默认线程池
- 对外路径配置 - 配置对外API路径
- 区块链配置 - 初始化区块链实例
- 同步区块服务配置 - 配置同步区块后台服务,如是否立即启动同步任务、配置时间间隔等
- 区块存储配置 - 实例化区块存储器
- 钱包存储配置 - 实例化钱包存储器
- 矿工后台任务配置 - 根据节点配置,决定是否启动矿工后台任务
- 钱包配置 - 钱包实例化
- 云节点配置 - 节点配置,如配置节点角色、手机号、密码等
存储层
存储层包括以下几个部分:
- 区块存储服务
- 区块存储服务,目前支持大数据存储
- 区块复制服务
- 区块复制服务,提供复制功能
- 钱包存储服务
- 钱包存储服务,目前支持大数据存储
服务层与事件处理详细方案
云节点服务
节点服务,内部服务。为ClouderController类提供功能实现。其类结构图如下:
交易广播机制
轮询周围节点信息算法如下:
- 在表circle_node_info中,按id从大到小的顺序,批量查询合法的节点信息列表。初始id为Long的最大值
- 根据查询出的批量列表,逐个向这些节点广播交易信息
- 每批次处理完成后,更新初始id为最后一个节点对应的id值,继续查询下一个批次
- 如果批次不为空,继续步骤2;如果批次为空,则结束广播交易信息
区块广播机制
轮询周围节点信息算法如下:
- 在表circle_node_info中,按id从大到小的顺序,批量查询合法的节点信息列表。初始id为Long的最大值
- 根据查询出的批量列表,逐个向这些节点广播区块信息
- 每批次处理完成后,更新初始id为最后一个节点对应的id值,继续查询下一个批次
- 如果批次不为空,继续步骤2;如果批次为空,则结束广播区块信息
矿工节点服务
矿工节点服务,内部服务,主要为矿工API提供功能实现。其类结构如下:
钱包节点服务
钱包节点服务,内部服务,主要为钱包API提供功能实现。其类结构如下:
区块链公共库
区块链公共库提供以下基础功能:
交易功能
区块链公共库的交易功能,主要构建四大类型交易:
- Coinbase交易 - 挖矿奖励交易
- 积分交易 - 代币转账交易
- 电子资产交易 - 数字资产交易
- 身份认证交易 - 身份验证交易
其中Coinbase交易包括三个子类:积分Coinbase、资产Coinbase和身份认证Coinbase。
区块功能
区块功能主要包括区块功能和区块链功能。其中区块功能包括:
- 区块构建 - 创世区块和普通区块构建
- 区块查询 - 区块数据检索
- 区块拷贝 - 区块数据复制
- 区块序列化 - 区块数据序列化和反序列化
区块链功能包括:
- 初始化区块链 - 区块链系统初始化
- 创建创世区块 - 创建第一个区块
- 添加新区块 - 向区块链添加新区块
- 区块遍历 - 遍历区块链数据
- 查询未花费输出 - 查询UTXO(未花费交易输出)
- 查询已花费输出 - 查询已使用的交易输出
- 查询链上交易 - 根据交易ID查询链上交易
- 区块查询 - 根据区块哈希、交易ID等查询区块
- 交易签名 - 交易数字签名
加密功能
区块链模块加密功能体现在以下几个方面:
- 用户地址生成 - 用户地址是匿名的,一个钱包生成一个唯一地址,但一个用户可以拥有多个钱包。钱包地址通过钱包公钥生成RIPEMD160哈希,添加版本号和校验码后,执行Base58编码转换得到
- 区块和交易ID - 区块和交易的ID都是其内容的双重哈希值(两次SHA256哈希)
- 交易输出锁定 - 每次交易输出都通过锁定脚本锁定。锁定脚本一般采用P2PKH(Pay-to-Public-Key-Hash)协议生成,必须通过对应私钥的签名进行解锁
- 交易输入解锁 - 每次交易输入在签名时,针对输入的密钥值进行私钥签名,并与对应公钥生成解锁脚本。解锁脚本与输入对应输出(由交易ID和输出序号决定)中的锁定脚本构成锁定-解锁脚本对,执行交易输入的解锁和支付操作
- 资产加密处理 - 针对资产流转和身份认证,除基本交易加密外,还对资产进行额外加密处理:
- 上传资产时,对资产进行签名和RSA非对称加密。只有签名验证通过且解密成功后才能查看原始内容
挖矿功能
区块链模块包含矿工挖矿功能。挖矿算法相对简单,通过Long类型循环变量从0开始,不断将值赋给区块的nonce字段,同时计算区块哈希是否满足相应难度要求,一旦满足则结束循环。
挖矿功能支持单线程和多线程两种方式:
单线程挖矿 - 采用上述算法,通过单一线程进行挖矿,速度较慢
多线程挖矿 - 线程数取CPU核心数+1,将循环变量取值范围分成线程总数段,每个线程在自己的范围内进行循环计算。一旦得到满足难度要求的哈希,通知所有正在计算的线程立即停止,准备下一个高度的区块挖矿操作
钱包功能
钱包功能包括钱包套件、钱包和地址三个基本概念和功能。
钱包套件 - 一个用户手机号(加密存储)对应一个钱包套件
钱包 - 一个钱包套件可以创建多个钱包。每个钱包包含公钥和私钥。公钥用于生成地址,私钥用于解锁脚本
地址 - 一个钱包只能创建一个地址,该地址通过钱包公钥按特定算法计算得出,且不可逆
钱包服务主要提供以下功能:
- 钱包资产查询 - 查询钱包中的数字资产
- 用户交易功能 - 执行各种交易操作
- 用户资产管理 - 管理用户的数字资产
区块链分叉服务
区块链分叉服务主要用于解决在同一秒内同一高度产生两个或多个区块的情况。节点服务会将这些区块分别存储在区块表中,同时区块链分叉服务会将这些区块信息存储到分叉信息表中。随着后续区块不断更新,区块链分叉服务会自动判定哪个区块是最新、最有效的顶层区块。
设计原理
分叉服务判定最新、最有效的顶层区块算法:在分叉表中,按高度和ID从大到小搜索有效的主链区块信息。第一条记录就是最新、最有效的顶层区块。
分叉表设计
字段 | 类型 | 说明 |
---|---|---|
height | Long | 区块所在的高度 |
hash | String | 区块的哈希值 |
hash_crc32 | Integer | 区块哈希的CRC校验码 |
prev_hash | String | 当前区块的前一个区块哈希值 |
is_master | Boolean | 此区块是否是主链区块 |
在存储区块时,根据当前区块与区块链中顶层区块的高度进行比较,如果当前区块高度大于链中顶层区块的高度,则当前区块是主链中的区块,否则不是。
处理分叉机制
存在一种场景:当前区块与区块链中顶层区块的高度相同,且当前区块的出块时间与链中顶层区块的出块时间在1秒之内,甚至比链中顶层区块的时间更早。按上述逻辑,当前区块仍是从链区块,并非主链上的区块。此时无法判定哪个是真正准确的顶层区块,区块发生了分叉。分叉中的两个区块里的交易都处于待确定状态,需要等到下一个区块到来且没有发生分叉时,才能确定哪个是真正有效的顶层区块。
因此,区块稳定期规定为:区块入链后,深度达到6个区块才算是稳定期,永远不可更改。在深度未达到6之前,由于区块分叉等因素影响,此时的区块可能是从链上的区块。
节点信息服务
节点信息服务主要用于存储周边云节点、挖矿节点相关基本信息,这些信息主要通过心跳或内网API收集。
节点信息表设计
节点信息表结构如下:
字段 | 类型 | 说明 |
---|---|---|
public_ip | String | 公网IP地址 |
local_ip | String | 内网IP地址 |
version | String | 服务版本 |
role | String | 角色:CLOUDER 云节点 MINER 矿工节点 仅支持这两个角色 |
protol_version | String | 协议版本 |
port | Integer | 端口号 |
base_height | Integer | 节点中区块最大高度值 |
create_time | Long | 创建时间 |
update_time | Long | 更新时间 |
节点信息表存储周围云节点、矿工节点的信息,便于自身广播心跳、交易、区块等功能。同时,针对新的节点服务,提供种子节点信息,方便新节点同步区块数据。
后台服务详解
心跳任务
后台每隔10秒与周围节点同步心跳信息。
心跳广播机制
轮询周围节点信息算法如下:
- 在表circle_node_info中,按ID从大到小的顺序,批量查询合法的节点信息列表。初始ID为Long的最大值
- 根据查询出的批量列表,逐个向这些节点发送本节点的心跳信息
- 每批次处理完成后,更新初始ID为最后一个节点对应的ID值,继续查询下一个批次
- 如果批次不为空,继续步骤2;如果批次为空,则结束发送心跳信息
挖矿任务
矿工节点任务,每隔10分钟(默认值,可配置)检查是否能启动挖矿任务,如果可以则启动挖矿。
挖矿设计
具体的挖矿逻辑在区块链公共库中。详细说明请参考:区块链公共库下的挖矿功能。
广播机制
广播区块的机制与云节点提供的广播区块机制相同。
区块同步任务
后台每隔5分钟(默认值,可配置)定时与周围节点同步最新的区块信息。
区块同步轮询机制
区块同步任务会定时扫描自身的节点信息表中,比自己区块高度要高的节点信息,找到最大高度的节点。如果找到高度相同的节点,则取创建时间最大的节点信息。从找到的节点中同步区块信息,开始的高度是本节点中区块链顶层区块的高度。
配置中心
异步线程池配置
配置默认线程池:
core_pool_size: 5
max_pool_size: 10
queue_capacity: 100
对外路径配置
配置对外API路径
目前路径配置
## clouder apis
path.blockHashListPath=/clouder/v1/node/getBlockHashList
path.blockPath=/clouder/v1/node/getBlock
path.blockHeaderListPath=/clouder/v1/node/getBlockHeaderList
path.blockDataPath=/clouder/v1/node/getBlockData
path.blockTailsHashListPath=/clouder/v1/node/getBlockTailsHashList
path.blockTailsPOPath=/clouder/v1/node/getBlockTailsPO
path.heartbeatPath=/clouder/v1/node/heartbeat
path.broadcastMinedBlock=/clouder/v1/node/broadcastMinedBlock
path.broadcastTransaction=/clouder/v1/node/broadcastTransaction
## miner apis
path.minerIpPortList=/miner/v1/node/retrieveMinerIpPortList
## wallet apis
path.initWalletPackage=/wallet/v1/node/initWalletPackage
path.createWallet=/wallet/v1/node/createWallet
path.listWallet=/wallet/v1/node/listWallet
path.listPubkey=/wallet/v1/node/listPubkey
path.balanceOfAddress=/wallet/v1/node/getBalanceOfAddress
path.balanceOfWallet=/wallet/v1/node/getBalanceOfWallet
path.pubKeyHashFromAddress=/wallet/v1/node/getPubKeyHashFromAddress
path.sendTo=/wallet/v1/node/sendTo
path.requestCharge=/wallet/v1/node/requestCharge
## block apis
path.blockchainHashListPath=/block/v1/node/get-block-hashlist
path.blockchainPath=/block/v1/node/get-block
path.blockchainHeaderListPath=/block/v1/node/get-block-header-list
path.blockchainDataPath=/block/v1/node/get-block-data
path.blockchainTailsHashListPath=/block/v1/node/get-blocktails-hashlist
path.blockchainTailsPOPath=/block/v1/node/get-blocktails-po
区块链配置
初始化区块链实例:
public class BlockchainConfig {
@Bean(name = "blockchain")
@DependsOn("blockCloudRepository")
public Blockchain getBlockchain() {
Blockchain blockchain = null;
try {
blockchain = Blockchain.initBlockchain(RepoType.CLOUD_STORE);
} catch (Exception e) {
log.error("initBlockchain error!", e);
blockchain = Blockchain.createGenesisBlockchain(RepoType.CLOUD_STORE);
}
return blockchain;
}
}
同步区块服务配置
配置同步区块后台服务,如是否立即启动同步任务、配置时间间隔等。
如果环境是dev环境,则不启动同步区块服务;否则配置后台任务的线程池,查询自己顶层区块高度和周围节点顶层区块高度。如果自己高度小于周围节点顶层区块的最大高度,则立即启动同步区块服务;否则在下一个间隔(默认300秒)启动同步区块服务。
周边节点选择机制
查询周边节点中,最大高度的节点进行区块信息同步。周边节点区块高度信息通过各自的心跳服务进行更新。
同步机制
- 判定节点状态是否是同步状态,如果是同步状态,则直接返回。因为只有在非同步状态下,才能进行区块信息同步服务
- 查询周边节点最大区块高度
- 查询自己最大区块高度
- 判定自己的高度是否小于周边节点的高度,如果相等或不小于,则不进行同步
- 检查最大区块高度的节点公网IP是否合法,非法则不进行同步
- 设定当前状态为区块同步状态,防止系统并发
- 调用批量接口,从最大区块高度的节点中拉取区块列表,调用blockCopyRepository接口copyBlock进行数据拷贝
- 区块同步完成后,准备同步分叉信息列表
- 取当前节点分叉信息表最新高度为查询分叉信息初始高度,调用批量查询分叉信息列表接口
- 调用blockCopyRepository接口copyBlockTail进行数据拷贝,直至完全同步为止
- 将节点状态设定为正常状态
区块存储配置
实例化区块存储器
钱包存储配置
实例化钱包存储器
矿工后台任务配置
根据节点配置,决定是否启动矿工后台任务
钱包配置
钱包实例化
云节点配置
节点配置,如:配置节点角色、手机号、密码等
存储层
区块存储服务
区块存储服务,目前支持大数据存储。
接口设计
主要提供区块相关接口功能,包括以下几个部分:
资源初始化和关闭
- void init(): 初始化接口
- void close(): 资源关闭接口
区块查询
- String getFirstBlockHash()
- String getLastBlockHash()
- Block getBlock()
- String getPrevBlockHash(String blockHash)
- boolean blockExists(String blockHash)
- Long getHeight(String blockHash)
- Long getBlockHeightByTxId(byte[] txId)
- Block getBlockByTxId(byte[] txId)
区块上链
- boolean addBlock(Block block)
UTXO功能
- Map
getChainstateBucket(): 获取本地缓存UXTO映射表 - void cleanChainStateBucket(): 清除UTXO本地缓存
- void putUTXOs(String txIdHexStr, TXOutput[] utxos): 保存交易输出
- TXOutput[] getUserUTXOs(byte[] pubKeyHash): 根据公钥查询未花费输出(UTXO)
- TXOutput[] getUTXOs(String txIdHexStr): 根据交易id的hex string查询UTXO
- int deleteUTXOs(String txIdHexStr): 根据交易Id的hex string删除相关的UTXO
交易查询
- Transaction findTransaction(byte[] txId)
- List
transactionFilterByTypeSet(List txIdList, Set typeSet): 根据交易id,检查此交易类型是否在typeSet里
区块复制服务
区块复制服务,提供copy服务
应用场景
当一个新的节点服务(云节点或矿工节点)部署时,由于内部数据都为空,其数据必须通过周围的节点提供。此时节点的同步区块任务就会启动,自动同步周边节点的数据到此节点数据中。同步区块数据需要使用区块复制服务。
接口设计
boolean copyBlock(Block block)
- 将区块数据存储到区块表中boolean copyBlockTail(CircleBlockTails circleBlockTails)
- 将分叉信息存储到分叉表中
钱包存储服务
钱包存储服务,目前支持大数据存储。目前钱包支持云端钱包服务和本地钱包服务。
接口设计
无论是云端钱包,还是本地钱包,都支持统一的接口:
资源初始化和关闭
- void init(): 初始化接口
- void close(): 资源关闭接口
钱包套件相关
- void initWalletPackage(WalletPackage walletPackage): 初始化钱包套件
- void updateWalletPackage(WalletPackage walletPackage):更新钱包套件
钱包套件配置相关
- WalletPackageConfig getWalletPackageConfigByAddress(String address):通过addres获取钱包套件配置
- WalletPackageConfig getWalletPackageConfigByPhone(String phone):通过手机号获取钱包套件配置
- WalletPackageConfig getWalletPackageConfigByUid(String uid):通过uid获取钱包套件配置
- boolean saveOrUpdatePhone(String phone, WalletPackageConfig config):根据手机号和配置,更新原有的钱包套件配置
- boolean saveOrUpdateAddress(String address, WalletPackageConfig config):根据address和配置,更新原有钱包套件配置
- boolean saveOrUpdateUid(WalletPackageConfig config):根据uid更新钱包套件配置
- boolean updateWalletPackageConfig(WalletPackageConfig config):更新钱包套件配置
云端钱包服务
用户通过手机号和验证码登录云端钱包H5页面,即可开通云端钱包服务。用户手机号经加密后存储在云端,钱包所有数据均通过SHA256加密处理(不可逆)。加密后的数据即使被他人获取,信息也不会被破解,安全性极高。
用户生成的钱包数据加密后存储在云服务上,我们有多个节点服务分布在全球各地,非常安全和快捷。在手机不被盗用的情况下,信息绝对安全。
本地钱包服务
本地钱包服务是在本地运行的钱包程序。私钥和公钥经加密后存储在本地文件中。您必须对这些文件进行安全处理,如备份到USB或数据盘等。本地钱包服务的安全性由自己控制,如果私钥不慎丢失,您在链上的所有资产将无法找回。