PlatONE is a blockchain bottom-level consortium chain built by Wanxiang Blockchain and its partners to support privacy computing. This article introduces in detail how to set up the rights management of PlatONE. PlatONE source code acquisition address: https://github.com/PlatONEnterprise
1. Brief description of the system contract
In the PlatONE alliance chain, the authority control is maintained by the system contract. The following seven system contracts are deployed on the system at the beginning of the chain for authority management.
System contract name | identifier | effect |
---|---|---|
contract management contract | cnsManager | Record name-to-address mappings |
Parameter management contract | __sys_ParamManager | System-level parameters for maintenance chains |
User management contract | __sys_UserManager | User Management |
User registration contract | __sys_UserRegister | User registration |
role management contract | __sys_RoleManager | role management contract |
role registration contract | __sys_RoleRegister | role registration contract |
Node management contract | __sys_NodeManager | Node management contract |
- For the interfaces supported by the system contract, please refer to the appendix
ctool is there ~/PlatONE-Go/cmd/SysContracts/build
, and the system contract is ~/PlatONE-Go/cmd/SysContracts/build/systemContract/cnsManager
stored under
For example, you can query the address of each system contract by calling the cnsManager contract
cd ~/PlatONE-Go/cmd/SysContracts/build
./ctool invoke --addr 0x0000000000000000000000000000000000000011 --abi ./systemContract/cnsManager/cnsManager.cpp.abi.json --config ./config.json --func getRegisteredContracts --param 0 --param 10
The contract call result is as follows:
{"code":0,
"msg":"ok",
"data":{
"total":7,
"contract":[
{"name":"__sys_NodeManager","version":"1.0.0.0","address":"0xee62fbc0b45f594465738fb5c794c60f9827f59e","origin":"0x9d41fe3b45f3cacb1bebbb4e5670f88ff74ef1c4","create_time":1561359510,"enabled":true},
{"name":"__sys_NodeRegister","version":"1.0.0.0","address":"0x6d26ea822241d1baf1c774dd46947616cd0f3d40","origin":"0x9d41fe3b45f3cacb1bebbb4e5670f88ff74ef1c4","create_time":1561359511,"enabled":true},
{"name":"__sys_ParamManager","version":"1.0.0.0","address":"0x2f0956a40cdb7f64ecc532a9c3d7171ed193ed03","origin":"0x9d41fe3b45f3cacb1bebbb4e5670f88ff74ef1c4","create_time":1561359505,"enabled":true},
{"name":"__sys_RoleManager","version":"1.0.0.0","address":"0xfd82ff83bbfcfc0dea1fb48f015393f4218d61a7","origin":"0x9d41fe3b45f3cacb1bebbb4e5670f88ff74ef1c4","create_time":1561359508,"enabled":true},{"name":"__sys_RoleRegister","version":"1.0.0.0","address":"0x53ba35b8b8f4b7ab63094a5e9e7bc3485a0b7bd4","origin":"0x9d41fe3b45f3cacb1bebbb4e5670f88ff74ef1c4","create_time":1561359509,"enabled":true},
{"name":"__sys_UserManager","version":"1.0.0.0","address":"0x9ef86ec254db98b8e086e36803ce23195a66711c","origin":"0x9d41fe3b45f3cacb1bebbb4e5670f88ff74ef1c4","create_time":1561359506,"enabled":true},
{"name":"__sys_UserRegister","version":"1.0.0.0","address":"0xae7236d1d1788612101c9ee6b25f71925db3bf0d","origin":"0x9d41fe3b45f3cacb1bebbb4e5670f88ff74ef1c4","create_time":1561359507,"enabled":true}
]
}
}
2. User rights and management
The permissions in PlatONE are all assigned to users in the system, and the roles of users represent the permissions of users. Currently, users can be assigned the following roles (permissions).
User roles (permissions) | effect |
---|---|
chainCreator | The chain creator, generated when the chain is created, is the account with the highest authority in the system |
chainAdmin | Chain manager, after being set by the chain creator, multiple chain managers can be set |
nodeAdmin | Node administrator, used to manage node information in the system |
contractAdmin | Contract administrator, can manage the permission control related to contracts in the system |
contractDeployer | Chain deployer, this role indicates that users can deploy contracts on the chain |
The permission scope of each role is shown in the following table
Chain Creator (Superpipe) | Chain manager (general management) | node administrator | contract manager | Contract deployer | |
---|---|---|---|---|---|
Assign or cancel chain administrators | √ | ||||
Designate or remove node administrators | √ | √ | |||
Designate or cancel contract administrators | √ | √ | |||
Specify or cancel the contract deployer | √ | √ | √ | ||
New Node Application | √ | √ | √ | ||
manage all nodes | √ | √ | |||
Set up a firewall for your own deployed contracts | √ | √ | √ | ||
Audit deployed contracts | √ | √ | √ | ||
Manage your own nodes | √ | √ | √ | ||
deploy contract | √ | √ | √ |
After the chain is started, the first account that deploys the system contract defaults to the chain creator (chainCreator).
If we need to set an account A as a chain admin (chainAdmin), we need to follow the following steps:
# 1. 账号A申请成为系统用户
# 使用账号A,调用用户注册合约(__sys_UserRegister)的registerUser接口
./ctool invoke \
--addr 0xae7236d1d1788612101c9ee6b25f71925db3bf0d \
--abi systemContract/userRegister/userRegister.cpp.abi.json \
--config config.json \
--func registerUser \
--param '{"address":"0x33d253386582f38c66cb5819bfbdaad0910339b3","name":"userA","mobile":"13111111111","email":"[email protected]","roles":["chainAdmin"],"remark":"平台用户申请"}'
# 2. chainCreator审核申请信息后,同意用户的申请行为
# 使用部署系统合约的账号(chainCreator)调用用户注册合约(__sys_UserRegister)的approve接口
./ctool invoke \
--addr 0xae7236d1d1788612101c9ee6b25f71925db3bf0d \
--abi systemContract/userRegister/userRegister.cpp.abi.json \
--config config.json \
--func approve \
--param "userA 的地址" \
--param 2
# 3. 查询用户信息,确认添加用户成功
# 可使用任意账号调用用户管理合约(__sys_UserRegister)的getAccountByAddress接口
./ctool invoke \
--addr 0x9d41fe3b45f3cacb1bebbb4e5670f88ff74ef1c4 \
--abi systemContract/userRegister/userRegister.cpp.abi.json \
--config config.json \
--func getAccountByAddress \
--param "userA 的地址" \
In PlatONE's permissions, a user can have multiple roles (permissions). If you need to add a role (permission) to an existing user, follow the steps below (take adding nodeAdmin and chainAdmin as an example):
# 1. chainCreator、chainAdmin这个两类角色才可以设置nodeAdmin角色,所以应该使用这两类用户调用用户注册合约(__sys_RoleManager)的addRole接口
./ctool invoke \
--addr 0xae7236d1d1788612101c9ee6b25f71925db3bf0d \
--abi systemContract/roleManager/roleManager.cpp.abi.json \
--config config.json \
--func addRole \
--param "userA" \
--param "userA 的地址" \
--param '["nodeAdmin","chainAdmin"]'
# 2. 查询用户信息,确认添加用户成功
# 可使用任意账号调用用户管理合约(__sys_RoleManager)的getRolesByAddress接口
./ctool invoke \
--addr 0x9d41fe3b45f3cacb1bebbb4e5670f88ff74ef1c4 \
--abi systemContract/roleManager/roleManager.cpp.abi.json \
--config config.json \
--func getRolesByAddress \
--param "userA 的地址" \
3. Node access permissions
In the PlatONE consortium chain, nodes are controlled through node management contracts.
Only the three types of users, chainCreator, chainAdmin and nodeAdmin, can set the node status in the system contract. These three types of accounts are required to call the contract when adding nodes, updating node status, and deleting nodes.
3.1 Add an observer node
# 1. 添加观察者节点, 观察者节点只同步区块数据,而不参与共识
# chainCreator、chainAdmin和nodeAdmin这个三类角色才可以设置nodeAdmin角色,所以应该使用这三类用户调用用户注册合约(__sys_NodeManager)的add接口
./ctool invoke \
--addr 0xae7236d1d1788612101c9ee6b25f71925db3bf0d \
--abi systemContract/nodeManager/nodeManager.cpp.abi.json \
--config config.json \
--func add \
--param '{"name":"node-${NODE_ID}","type":${NODE_TYPE},"publicKey":"${PUBKEY}","desc":"desc","externalIP":"${IP}","internalIP":"${IP}","rpcPort":${RPC_PORT},"p2pPort":${P2P_PORT},"root":${IS_ROOT},"owner":"0x${account}","status":1}'
The parameter information is a json string, and the user should fill in the corresponding fields. The following is the complete information of a node
{ "name":"node's name",
"type":0,
"publicKey":"71bb2aa47f4ddeccf80190bf98a80136ab52d6c8e2c4d54a11e690d4dffd9578f8c0ed614039b7ee06b55c7b96fdfe9099efa5dd12c6b1115f1c4817a093c1c7",
"desc":"node description",
"externalIP":"208.120.201.12",
"internalIP":"127.0.0.1",
"rpcPort":6790,
"p2pPort":16790,
"root":false,
"owner":"0xae7236d1d1788612101c9ee6b25f71925db3bf0d",
"status":1
}
3.2 Upgrade the node to a consensus node
# 2. 将节点升级为共识节点,共识节点即同步数据也参与共识
./ctool invoke \
--addr 0xae7236d1d1788612101c9ee6b25f71925db3bf0d \
--abi systemContract/nodeManager/nodeManager.cpp.abi.json \
--config config.json \
--func update \
--param "node name"
--param '{"type":1}'
3.3 Query all node information
# 3. 查询所有节点信息
./ctool invoke \
--addr 0xae7236d1d1788612101c9ee6b25f71925db3bf0d \
--abi systemContract/nodeManager/nodeManager.cpp.abi.json \
--config config.json \
--func getAllNodes
4. Contract deployment and calling permissions
4.1 Contract Deployment Permissions
The permission check for deploying contracts on the chain is disabled by default, and the administrator needs to call the parameter management contract to enable this function to check the permission to deploy contracts.
# 1. 启用合约部署的权限检查
# 参数: 0,默认值,不检查合约部署权限; 1, 检查合约部署权限
./ctool invoke \
--addr 0xae7236d1d1788612101c9ee6b25f71925db3bf0d \
--abi systemContract/paramManager/paramManager.cpp.abi.json \
--config config.json \
--func setCheckContractDeployPermission \
--param 1
# 查询合约部署权限检查是否开启
./ctool invoke \
--addr 0xae7236d1d1788612101c9ee6b25f71925db3bf0d \
--abi systemContract/paramManager/paramManager.cpp.abi.json \
--config config.json \
--func getCheckContractDeployPermission \
Only the following roles can deploy contracts. Users who do not have the following roles will not be able to deploy contracts on the chain.
- chainCreator
- chainAdmin
- contractAdmin
- contractDeployer
If an account needs to deploy contracts, the account needs to be set tocontractDeployer
4.2 Contract Call Permission | Contract Firewall
The calling authority of contracts in PlatONE is set by the contract firewall, and only the creator of the contract can set the firewall of the corresponding contract.
The contract firewall has access control at the contract interface level, which is implemented through the following two lists:
- ACCEPT: A list of addresses that can access the corresponding interface, equivalent to a whitelist
- REJECT: A list of addresses that deny access to the corresponding interface, equivalent to a blacklist
# 打开指定合约的防火墙
ctool fwInvoke --addr 0x22 --func '__sys_FwOpen()' --config ./config.json
# 关闭指定合约的防火墙
ctool fwInvoke --addr 0x22 --func '__sys_FwClose()' --config ./config.json
# 设定指定合约的白/黑名单
ctool fwInvoke --addr 0x22 --func '__sys_FwAdd("ACCEPT", "0x33:*|*:funcName2|0x55:funcName3")' --config ./config.json
ctool fwInvoke --addr 0x22 --func '__sys_FwAdd("REJECT", "0x33:*|*:funcName2|0x55:funcName3")' --config ./config.json
# 清空指定合约的白/黑名单
ctool fwInvoke --addr 0x22 --func '__sys_FwClear("ACCEPT")' --config ./config.json
ctool fwInvoke --addr 0x22 --func '__sys_FwClear("REJECT")' --config ./config.json
# 删除指定合约的白/黑名单里的指定地址
ctool fwInvoke --addr 0x22 --func '__sys_FwDel("ACCEPT", "0x33:*|*:funcName2|0x55:funcName3")' --config ./config.json
ctool fwInvoke --addr 0x22 --func '__sys_FwDel("REJECT", "0x33:*|*:funcName2|0x55:funcName3")' --config ./config.json
# 重置指定合约的白/黑名单
ctool fwInvoke --addr 0x22 --func '__sys_FwSet("ACCEPT", "0x33:*|*:funcName2|0x55:funcName3")' --config ./config.json
ctool fwInvoke --addr 0x22 --func '__sys_FwSet("REJECT", "0x33:*|*:funcName2|0x55:funcName3")' --config ./config.json
# 查询指定合约的防火墙状态
ctool fwInvoke --addr 0x22 --func '__sys_FwStatus()' --config ./config.json
Appendix A: System Contract Interfaces and Methods
A-1. cnsManager
int cnsRegisterFromInit(const char * name,const char * version)
int cnsRegister(const char * name,const char * version,const char * address)
int cnsUnregister(char * name,char * version)
const char * getContractAddress(char * name,char * version)
char * getRegisteredContracts(int pageNum,int pageSize)
char * getRegisteredContractsByAddress(char * origin,int pageNum,int pageSize)
int ifRegisteredByName(char * name)
int ifRegisteredByAddress(char * address)
char * getContractInfoByAddress(char * address)
char * getHistoryContractsByName(char * name)
THE 2. paramManager
int setGasContractName(const char * contractName)
const char * getGasContractName()
int setCBFTTimeParam(int produceDuration,int blockInterval)
const char * getCBFTTimeParam()
int setIsProduceEmptyBlock(int isProduceEmptyBlock)
int getIsProduceEmptyBlock()
int setTxGasLimit(unsigned long long txGasLimit)
unsigned long long getTxGasLimit()
int setBlockGasLimit(unsigned long long blockGasLimit)
unsigned long long getBlockGasLimit()
int setAllowAnyAccountDeployContract(int isAllowAnyAccountDeployContract)
int setCheckContractDeployPermission(int checkPermission)
int getCheckContractDeployPermission()
int getAllowAnyAccountDeployContract()
int setIsApproveDeployedContract(int isApproveDeployedContract)
int getIsApproveDeployedContract()
int setIsTxUseGas(int isTxUseGas)
int getIsTxUseGas()
A-3. userManager
int addUser(const char * userJson)
int enable(const char * userAddr)
int disable(const char * userAddr)
int delUser(const char * userAddr)
int update(const char * userAddr,const char * updateJson)
const char * getAccountByAddress(const char * address)
const char * getAccountByName(const char * name)
int isValidUser(const char * userAddr)
A-4. userRegister
int registerUser(const char * registJson)
int approve(const char * userAddress,int auditStatus)
const char * getAccountByAddress(const char * address)
const char * getAccountByUsername(const char * UserName)
const char * getAccountsByStatus(int pageNum,int pageSize,int accountStatus)
int getStatusByAddress(const char * address)
TO 5. roleManager
int addRole(const char * name,const char * address,const char * roles)
int removeRole(const char * address,const char * roles)
const char * getRolesByAddress(const char * address)
const char * getRolesByName(const char * name)
const char * getAccountsByRole(const char * role)
int hasRole(const char * addr,const char * role)
A-6. roleRegister
int registerRole(const char * roles)
int approveRole(const char * address,int status)
const char * getRegisterInfoByAddress(const char * address)
const char * getRegisterInfoByName(const char * name)
const char * getRegisterInfosByStatus(int status,int pageNum,int pageSize)
A-7. nodeManager
int add(const char * nodeJsonStr)
const char * getAllNodes()
int validJoinNode(const char * publicKey)
int nodesNum(const char * nodeJsonStr)
const char * getNodes(const char * nodeJsonStr)
int update(const char * name,const char * nodeJsonStr)
const char * getEnodeNodes(int deleted)
const char * getNormalEnodeNodes()
const char * getDeletedEnodeNodes()