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 |
接口说明:
用户在注册之前,发送注册验证码。如果您输入邮箱,验证码就发送到您的邮箱。如果您输入是手机号,验证码就通过短信发送到您手机上。
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
注册(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 | 成功或失败 |
接口说明:
用户注册接口
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
发送登录验证码(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 | 布尔值,成功或失败 |
接口说明:
在登录之前,调用发送登录验证码。如果您输入的是邮箱,验证码就发达到您的邮箱。如果您输入的是手机号,验证码通过短信发送到您的手机上。
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
登录接口(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>”
}
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
登出接口(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 | 布尔值,成功或失败 |
接口说明:
在设定支付密码时,需要发送支付密码的验证码。如果您输入的是邮箱,验证码就发给到您的邮箱里,如果您输入的是手机号,验证码通过短信发送到您的手机上。
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
设定支付密码(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. |
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
status | Integer | required | 200 - success, others failure |
message | String | required | the message |
data | Boolean | optional | success or failure |
接口说明:
user set pay password.
是否设定支付密码(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. |
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
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 |
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
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 |
String | optional | user email | |
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 |
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
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 |
String | optional | user email | |
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 |
接口说明:
获取用户信息接口。
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
添加联系方式(addContacts)
路径:/user/v1/node/add-contacts
Method: POST
请求头: { AuthorizationV2: "<sessionKey>" }
请求对象:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
name | String | required | user name |
*phone | String | optional | user phone |
String | optional | user email | |
sex | Byte | optional | 1: man 0 woman |
icon | String | optional | user icon |
address | String | required | user address |
description | String | optional | description |
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
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 | Optional | user phone |
String | Optional | user email | |
sex | Byte | optional | 1: man 0 woman |
icon | String | optional | user icon |
address | String | required | user address |
description | String | optional | description |
接口说明:
查询用户联系方式接口。
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
钱包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. |
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email),所以在国际环境下调用这个接口,不要传入参数
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
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 |
接口说明:
从地址中获取对应的公钥Hash。
发送资产接口(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 |
注意:国际环境下目前不支持手机号(phone),只支持邮箱(email)
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
地址属于此用户。国际环境下目前不支持手机号(phone),只支持邮箱(email)
返回结果:
属性 | 类型 | 是否必选 | 说明 |
---|---|---|---|
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,这些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 |
接口说明:
公网接口,不需要用户登录。
根据起始的区块高度,批量查询之后的区块hash列表。
获取区块数据(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 |
接口说明:
公网接口,不需要用户登录。
根据区块Hash获取对应的区块数据。
获取区块头信息列表(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,获取对应的区块内部数据。
获取区块尾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 |
接口说明:
公网接口,不需要用户登录。
根据起始高度,批量获取区块尾hash列表。
获取区块尾数据(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 |
接口说明:
公网接口,不需要用户登录。
根据区块hash,获取对应的区块尾数据。
获取交易(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
字段
接口说明:
公网接口,不需要用户登录。
根据地址和最小输出key,批量查询相应的交易数据列表。
获取所有未花费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();
接口说明:
公网接口,不需要用户登录。
根据地址和最小输出key,批量查询相应的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 |
接口说明:
根据起始区块高度和远程地址,从远程服务中,批量获取区块hash列表,一次拉取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. |
接口说明:
根据区块hash和远程的地址,从远程服务中获取对应的区块数据。
获取区块头列表(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 |
接口说明:
batch get block header list by the current block height, each in 100 items.
获取区块内部数据(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 |
接口说明:
根据区块hash,从远程服务获取对应的区块内部数据。
广播新区块(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 |
接口说明:
根据起始高度,向远程地址批量获取区块头hash列表,一次拉取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 |
接口说明:
根据区块尾hash,向远程地址获取对应的区块尾数据。
矿工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路径
- 区块链配置:初始化区块实例
- 同步区块服务配置:配置同步区块后台服务,比如是否立即启动同步任务,配置时间间隔等
- 区块存储配置:实例化区块存储器
- 钱包存储配置:实例化钱包存储器
- 矿工后台任务配置:根据结点配置,是否启动矿工后台任务
- 钱包配置:钱包实例化
- 云结点配置:结点配置,例如:配置结点角色,手机号,密码等
存储层
存储层包括以下几个:
- 区块存储服务
- 区块存储服务,目前支持大数据存储
- 区块复制服务
- 区块复制服务,提供copy服务
- 钱包存储服务
- 钱包存储服务,目前支持大数据存储
服务层与事件处理详细方案
云结点服务
结点服务,内部服务。为ClouderController类,提供功能实现。它的类结构图如下:
交易广播机制
轮询周围结点信息算法如下:
- 在表circle_node_info表中,按id从大到小的顺序,批量查询合法的结点信息列表。初始id是Long的最大值
- 根据查出来的批量列表,逐个给这些结点广播交易信息
- 每批次处理完成之后,再更新初始id为最后一个结点对应的id值,继续查询下一个批次
- 如果批次不空,继续2的步骤,如果批次为空,则结束广播交易信息
区块广播机制
轮询周围结点信息算法如下:
- 在表circle_node_info表中,按id从大到小的顺序,批量查询合法的结点信息列表。初始id是Long的最大值
- 根据查出来的批量列表,逐个给这些结点广播区块信息
- 每批次处理完成之后,再更新初始id为最后一个结点对应的id值,继续查询下一个批次
- 如果批次不空,继续2的步骤,如果批次为空,则结束广播区块信息
矿工结点服务
矿工结点服务,内部服务,主要是为矿工api提供功能实现。它的类结构如下:
钱包结点服务
钱包结点服务,内部服务,主要是钱包api提供功能实现。它的类结构如下:
区块链公共库
区块链公共库提供以下基础功能:
交易功能
区块链公共库的交易功能,主要是构建四大类型交易:
1)coinBase交易
2)积分交易
3)电子资产交易
4)身份认证交易
其中coinBase交易中,包括三个小类:积分coinbase, 资产coinbase和身份认证coinbase。
区块功能
区块功能,主要包括区块功能和区块链功能。其中区块功能包括以下:
- 区块构建(创世纪区块和普通区块构建)
- 区块查询
- 区块拷贝
- 区块序列和序列化
区块链功能包括以下:
- 初始化区块链
- 创建创世纪区块
- 添加新区块
- 区块遍历
- 查询所有未花费输出
- 查询所有已花费输出
- 根据交易id,查询链上交易
- 区块查询(区块hash、交易id等)
- 交易加签
加密功能
区块链模块加密功能,表现在如下几个方面:
- 用户地址是匿名的,一个钱包生成一个唯一的地址,但是一个用户可以拥有多个钱包。钱包生成地址是利用钱包的公钥,获取其ripeMD160Hash,添加版本和校验码之后,执行Base58转换之后得到。
- 区块和交易的id都是其内容的double哈希值(两次sha256哈希)。
- 每次交易输出,都通过锁定脚本将交易输出锁定。而锁定脚本一般采用P2PKH协议生成,这个协议必须通过这个锁定脚本公钥对应的私钥的签名进行解锁。
- 每次交易输入,在交易签名的时候,将针对这个输入的key值进行私钥签名,并跟对应的公钥生成解锁脚本。这个解锁脚本跟这个输入对应的输出(交易id和输出序号决定)中锁定脚本,构成一个锁定解锁脚本,将每次交易输入执行解锁并执行相应的支付操作。
- 针对资产的流转和身份的认证,这块除了基本的交易加密之外,还针对资产进行了加密处理:
- 上传资产时,会针对资产进行签名和RSA非对称加密。只能签名通过,并且解密成功之后才能查看原来内容。
挖矿功能
区块链模块含有矿工的挖矿功能,挖矿的算法,其实比较简单,就通过Long的循环变量,从0开始,不断赋值给区块的nonce字段,同时计算这个区块的hash有没有满足相应的难度,一旦满足就结束轮询。
挖矿功能支持单线程和多线程两个方式挖矿。
单线程方式就是上面我说的算法,通过单一线程进行挖矿,速度比较慢。
多线程方式,线程数取内核cpu个数+1,通过将循环变量的取值范围分成线程总数段之后 ,每一个线程在自己的范围内进行轮询计算。一旦得到满足一定难度的hash之后,通知所有正在计算的线程立即停止计算。准备一个高度的区块挖矿操作。
钱包功能
钱包功能包括钱包套件,钱包和地址三个基本概念和功能。
钱包套件:一个用户手机号(加密存储)对应一个钱包套件。
钱包:一个钱包套件可以创建多个钱包。一个钱包有公钥和私钥。公钥用来生成地址,私钥用来解锁脚本。
地址:一个钱包只能创建一个地址,这个地址通过这个钱包的公钥通过一定算法计算得来,并且不可逆。
钱包服务主要是提供用户以下功能:
- 钱包资产查询功能
- 用户交易功能
- 用户资产管理
链表分叉服务
链表分叉服务主要是解决,同一秒之内在同一个高度产生了两个或多个以上的区块。结点服务会把这些区块分别存储在区块表里,同时链表分叉服务,会将这些区块信息存储起来分叉信息表里,随着后续区块不断更新,链表分叉服务会自动判定那个区块是最新、最有效的顶层区块。
设计原理
分叉服务判定最新、最有效的顶层区块算法:在分叉表里,按高度,id从大到小搜索,有效的主链的区块信息。第一条就是最新、最有效的顶层区块。
分叉表设计
字段 | 类型 | 说明 |
---|---|---|
height | Long | 区块所在的高度 |
hash | String | 区块的hash值 |
hash_crc32 | Integer | 区块的hash的crc检验码 |
prev_hash | String | 当区块的前一个区块的hash值 |
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是否合法,非法的话,不进行同步
- 设定当前的状态是区块同步状态,防止系统并发
- 调用批量接口,从最大区块高度的结点中,拉取区块列表,调用blockCopyResitory接口coyBlock进行无脑拷贝。
- 区块同步完成之后,准备同步分叉信息列表
- 取当前结点分叉信息表最新高度为查询分叉信息最初高度,调用批量查询分叉信息列表接口
- 调用blockCopyResitory接口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或数据盘等。本地钱包服务,安全性由自己控制,如果私钥不小心被弄丢之后,你在链上的所有资产将无人能够为您找回。