aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorJhih-Ming Huang <jm@byzantine-lab.io>2019-08-16 16:28:50 +0800
committerWei-Ning Huang <w@byzantine-lab.io>2019-09-17 16:57:31 +0800
commit0594f51ee194bc975a75d293a789d98f47f3f4d9 (patch)
tree552839016bb000cb8000efd91356304ee993b7a5 /core
parent3430fc0db2e1b0fdba84b97924d0151e446805c9 (diff)
downloadgo-tangerine-0594f51ee194bc975a75d293a789d98f47f3f4d9.tar
go-tangerine-0594f51ee194bc975a75d293a789d98f47f3f4d9.tar.gz
go-tangerine-0594f51ee194bc975a75d293a789d98f47f3f4d9.tar.bz2
go-tangerine-0594f51ee194bc975a75d293a789d98f47f3f4d9.tar.lz
go-tangerine-0594f51ee194bc975a75d293a789d98f47f3f4d9.tar.xz
go-tangerine-0594f51ee194bc975a75d293a789d98f47f3f4d9.tar.zst
go-tangerine-0594f51ee194bc975a75d293a789d98f47f3f4d9.zip
core: add p2p whitelist for consortium
Diffstat (limited to 'core')
-rw-r--r--core/vm/oracle_contract_abi.go840
-rw-r--r--core/vm/oracle_contracts.go182
-rw-r--r--core/vm/oracle_contracts_test.go191
3 files changed, 842 insertions, 371 deletions
diff --git a/core/vm/oracle_contract_abi.go b/core/vm/oracle_contract_abi.go
index 535161bd4..23ec7cd9d 100644
--- a/core/vm/oracle_contract_abi.go
+++ b/core/vm/oracle_contract_abi.go
@@ -56,6 +56,60 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "MinStake",
+ "type": "uint256"
+ },
+ {
+ "name": "LockupPeriod",
+ "type": "uint256"
+ },
+ {
+ "name": "MinGasPrice",
+ "type": "uint256"
+ },
+ {
+ "name": "BlockGasLimit",
+ "type": "uint256"
+ },
+ {
+ "name": "LambdaBA",
+ "type": "uint256"
+ },
+ {
+ "name": "LambdaDKG",
+ "type": "uint256"
+ },
+ {
+ "name": "NotaryParamAlpha",
+ "type": "uint256"
+ },
+ {
+ "name": "NotaryParamBeta",
+ "type": "uint256"
+ },
+ {
+ "name": "RoundLength",
+ "type": "uint256"
+ },
+ {
+ "name": "MinBlockInterval",
+ "type": "uint256"
+ },
+ {
+ "name": "FineValues",
+ "type": "uint256[]"
+ }
+ ],
+ "name": "updateConfiguration",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [],
"name": "totalSupply",
@@ -70,6 +124,39 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "PublicKey",
+ "type": "bytes"
+ }
+ ],
+ "name": "addDKGMasterPublicKey",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "addressWhitelist",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [
{
@@ -139,6 +226,20 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "MPKReady",
+ "type": "bytes"
+ }
+ ],
+ "name": "addDKGMPKReady",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [],
"name": "miningVelocity",
@@ -153,6 +254,20 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Finalize",
+ "type": "bytes"
+ }
+ ],
+ "name": "addDKGFinalize",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [],
"name": "lambdaBA",
@@ -167,6 +282,42 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Amount",
+ "type": "uint256"
+ }
+ ],
+ "name": "unstake",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Type",
+ "type": "uint256"
+ },
+ {
+ "name": "Arg1",
+ "type": "bytes"
+ },
+ {
+ "name": "Arg2",
+ "type": "bytes"
+ }
+ ],
+ "name": "report",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [],
"name": "minStake",
@@ -181,6 +332,66 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [],
+ "name": "stake",
+ "outputs": [],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [],
+ "name": "withdraw",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "NodeAddress",
+ "type": "address"
+ }
+ ],
+ "name": "payFine",
+ "outputs": [],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "NewPublicKey",
+ "type": "bytes"
+ }
+ ],
+ "name": "replaceNodePublicKey",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "NewOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferNodeOwnership",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [],
"name": "crsRound",
@@ -223,6 +434,48 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Success",
+ "type": "bytes"
+ }
+ ],
+ "name": "addDKGSuccess",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "withdrawable",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "NewSignedCRS",
+ "type": "bytes"
+ }
+ ],
+ "name": "resetDKG",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [
{
@@ -258,6 +511,20 @@ const GovernanceABIJSON = `
{
"constant": true,
"inputs": [],
+ "name": "whitelistLength",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
"name": "dkgRound",
"outputs": [
{
@@ -270,6 +537,24 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "OldOwner",
+ "type": "address"
+ },
+ {
+ "name": "NewOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferNodeOwnershipByFoundation",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [],
"name": "totalStaked",
@@ -317,6 +602,25 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "addr",
+ "type": "address"
+ }
+ ],
+ "name": "removeFromWhitelist",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [],
"name": "roundLength",
@@ -382,6 +686,25 @@ const GovernanceABIJSON = `
"inputs": [
{
"name": "",
+ "type": "address"
+ }
+ ],
+ "name": "whitelistOffsetByAddress",
+ "outputs": [
+ {
+ "name": "",
+ "type": "int256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [
+ {
+ "name": "",
"type": "bytes32"
}
],
@@ -463,6 +786,20 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Complaint",
+ "type": "bytes"
+ }
+ ],
+ "name": "addDKGComplaint",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [
{
@@ -529,6 +866,50 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Round",
+ "type": "uint256"
+ },
+ {
+ "name": "SignedCRS",
+ "type": "bytes"
+ }
+ ],
+ "name": "proposeCRS",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "Name",
+ "type": "string"
+ },
+ {
+ "name": "Email",
+ "type": "string"
+ },
+ {
+ "name": "Location",
+ "type": "string"
+ },
+ {
+ "name": "Url",
+ "type": "string"
+ }
+ ],
+ "name": "updateNodeInfo",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [
{
@@ -548,6 +929,36 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "PublicKey",
+ "type": "bytes"
+ },
+ {
+ "name": "Name",
+ "type": "string"
+ },
+ {
+ "name": "Email",
+ "type": "string"
+ },
+ {
+ "name": "Location",
+ "type": "string"
+ },
+ {
+ "name": "Url",
+ "type": "string"
+ }
+ ],
+ "name": "register",
+ "outputs": [],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [
{
@@ -595,6 +1006,25 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "addr",
+ "type": "address"
+ }
+ ],
+ "name": "addToWhitelist",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
"constant": true,
"inputs": [
{
@@ -666,6 +1096,48 @@ const GovernanceABIJSON = `
"type": "function"
},
{
+ "constant": false,
+ "inputs": [
+ {
+ "name": "NewOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferOwnership",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "nodesLength",
+ "outputs": [
+ {
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "isConsortium",
+ "outputs": [
+ {
+ "name": "",
+ "type": "bool"
+ }
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
"anonymous": false,
"inputs": [],
"name": "ConfigurationChanged",
@@ -874,374 +1346,6 @@ const GovernanceABIJSON = `
],
"name": "DKGReset",
"type": "event"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "NewOwner",
- "type": "address"
- }
- ],
- "name": "transferOwnership",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "MinStake",
- "type": "uint256"
- },
- {
- "name": "LockupPeriod",
- "type": "uint256"
- },
- {
- "name": "MinGasPrice",
- "type": "uint256"
- },
- {
- "name": "BlockGasLimit",
- "type": "uint256"
- },
- {
- "name": "LambdaBA",
- "type": "uint256"
- },
- {
- "name": "LambdaDKG",
- "type": "uint256"
- },
- {
- "name": "NotaryParamAlpha",
- "type": "uint256"
- },
- {
- "name": "NotaryParamBeta",
- "type": "uint256"
- },
- {
- "name": "RoundLength",
- "type": "uint256"
- },
- {
- "name": "MinBlockInterval",
- "type": "uint256"
- },
- {
- "name": "FineValues",
- "type": "uint256[]"
- }
- ],
- "name": "updateConfiguration",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "Complaint",
- "type": "bytes"
- }
- ],
- "name": "addDKGComplaint",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "PublicKey",
- "type": "bytes"
- }
- ],
- "name": "addDKGMasterPublicKey",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "MPKReady",
- "type": "bytes"
- }
- ],
- "name": "addDKGMPKReady",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "Finalize",
- "type": "bytes"
- }
- ],
- "name": "addDKGFinalize",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "Success",
- "type": "bytes"
- }
- ],
- "name": "addDKGSuccess",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "NodeAddress",
- "type": "address"
- }
- ],
- "name": "payFine",
- "outputs": [],
- "payable": true,
- "stateMutability": "payable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "nodesLength",
- "outputs": [
- {
- "name": "",
- "type": "uint256"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "Round",
- "type": "uint256"
- },
- {
- "name": "SignedCRS",
- "type": "bytes"
- }
- ],
- "name": "proposeCRS",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "Type",
- "type": "uint256"
- },
- {
- "name": "Arg1",
- "type": "bytes"
- },
- {
- "name": "Arg2",
- "type": "bytes"
- }
- ],
- "name": "report",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "NewSignedCRS",
- "type": "bytes"
- }
- ],
- "name": "resetDKG",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "PublicKey",
- "type": "bytes"
- },
- {
- "name": "Name",
- "type": "string"
- },
- {
- "name": "Email",
- "type": "string"
- },
- {
- "name": "Location",
- "type": "string"
- },
- {
- "name": "Url",
- "type": "string"
- }
- ],
- "name": "register",
- "outputs": [],
- "payable": true,
- "stateMutability": "payable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "NewPublicKey",
- "type": "bytes"
- }
- ],
- "name": "replaceNodePublicKey",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [],
- "name": "stake",
- "outputs": [],
- "payable": true,
- "stateMutability": "payable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "NewOwner",
- "type": "address"
- }
- ],
- "name": "transferNodeOwnership",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "OldOwner",
- "type": "address"
- },
- {
- "name": "NewOwner",
- "type": "address"
- }
- ],
- "name": "transferNodeOwnershipByFoundation",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "Amount",
- "type": "uint256"
- }
- ],
- "name": "unstake",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [
- {
- "name": "Name",
- "type": "string"
- },
- {
- "name": "Email",
- "type": "string"
- },
- {
- "name": "Location",
- "type": "string"
- },
- {
- "name": "Url",
- "type": "string"
- }
- ],
- "name": "updateNodeInfo",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": false,
- "inputs": [],
- "name": "withdraw",
- "outputs": [],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
- },
- {
- "constant": true,
- "inputs": [],
- "name": "withdrawable",
- "outputs": [
- {
- "name": "",
- "type": "bool"
- }
- ],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
}
]
`
diff --git a/core/vm/oracle_contracts.go b/core/vm/oracle_contracts.go
index ddcd6d3f6..130d5bf24 100644
--- a/core/vm/oracle_contracts.go
+++ b/core/vm/oracle_contracts.go
@@ -99,6 +99,9 @@ const (
minBlockIntervalLoc
fineValuesLoc
finedRecordsLoc
+ isConsortiumLoc
+ addressWhitelistLoc
+ whitelistOffsetByAddressLoc
)
func publicKeyToNodeKeyAddress(pkBytes []byte) (common.Address, error) {
@@ -124,7 +127,7 @@ func IdToAddress(id coreTypes.NodeID) common.Address {
return common.BytesToAddress(id.Hash[12:])
}
-// State manipulation helper fro the governance contract.
+// State manipulation helper for the governance contract.
type GovernanceState struct {
StateDB StateDB
}
@@ -984,6 +987,80 @@ func (s *GovernanceState) SetFineRecords(recordHash Bytes32, status bool) {
s.setStateBigInt(loc, big.NewInt(value))
}
+// bool public isConsortium;
+func (s *GovernanceState) IsConsortium() bool {
+ return s.getStateBigInt(big.NewInt(isConsortiumLoc)).Cmp(big.NewInt(0)) > 0
+}
+func (s *GovernanceState) EnableConsortium() {
+ s.setStateBigInt(big.NewInt(isConsortiumLoc), big.NewInt(1))
+}
+
+// address[] public addressWhitelist;
+func (s *GovernanceState) LenWhitelist() *big.Int {
+ return s.getStateBigInt(big.NewInt(addressWhitelistLoc))
+}
+func (s *GovernanceState) AddressWhitelist(index *big.Int) common.Address {
+ arrayBaseLoc := s.getSlotLoc(big.NewInt(addressWhitelistLoc))
+ return common.BigToAddress(s.getStateBigInt(new(big.Int).Add(arrayBaseLoc, index)))
+}
+func (s *GovernanceState) AddressWhitelists() []common.Address {
+ len := s.LenWhitelist()
+ result := make([]common.Address, len.Uint64())
+ for i := 0; i < int(len.Uint64()); i++ {
+ result[i] = s.AddressWhitelist(big.NewInt(int64(i)))
+ }
+ return result
+}
+func (s *GovernanceState) putAddressWhitelist(addr common.Address, offset *big.Int) {
+ arrayBaseLoc := s.getSlotLoc(big.NewInt(addressWhitelistLoc))
+ loc := new(big.Int).Add(arrayBaseLoc, offset)
+ s.setState(common.BigToHash(loc), addr.Hash())
+ s.putWhitelistOffsetByAddress(addr, offset)
+}
+func (s *GovernanceState) AddToWhitelist(addr common.Address) *big.Int {
+ offset := s.WhitelistOffsetByAddress(addr)
+ if offset.Cmp(bigZero) >= 0 {
+ return offset
+ }
+ len := s.getStateBigInt(big.NewInt(addressWhitelistLoc))
+ s.putAddressWhitelist(addr, len)
+ len = new(big.Int).Add(len, big.NewInt(1))
+ s.setStateBigInt(big.NewInt(addressWhitelistLoc), len)
+ return len
+}
+func (s *GovernanceState) DeleteAddressWhitelist(addr common.Address) *big.Int {
+ offset := s.WhitelistOffsetByAddress(addr)
+ if offset.Cmp(bigZero) < 0 {
+ return offset
+ }
+ s.DeleteWhitelistOffsetByAddress(addr)
+ len := s.getStateBigInt(big.NewInt(addressWhitelistLoc))
+ newLen := new(big.Int).Sub(len, big.NewInt(1))
+ if len.Cmp(big.NewInt(1)) > 0 && offset.Cmp(newLen) != 0 {
+ lastAddr := s.AddressWhitelist(newLen)
+ s.putAddressWhitelist(lastAddr, offset)
+ }
+ s.setStateBigInt(
+ big.NewInt(addressWhitelistLoc),
+ newLen,
+ )
+ return len
+}
+
+// mapping(address => int256) whitelistOffsetByAddress
+func (s *GovernanceState) WhitelistOffsetByAddress(addr common.Address) *big.Int {
+ loc := s.getMapLoc(big.NewInt(whitelistOffsetByAddressLoc), addr.Bytes())
+ return new(big.Int).Sub(s.getStateBigInt(loc), big.NewInt(1))
+}
+func (s *GovernanceState) putWhitelistOffsetByAddress(addr common.Address, offset *big.Int) {
+ loc := s.getMapLoc(big.NewInt(whitelistOffsetByAddressLoc), addr.Bytes())
+ s.setStateBigInt(loc, new(big.Int).Add(offset, big.NewInt(1)))
+}
+func (s *GovernanceState) DeleteWhitelistOffsetByAddress(addr common.Address) {
+ loc := s.getMapLoc(big.NewInt(whitelistOffsetByAddressLoc), addr.Bytes())
+ s.setStateBigInt(loc, big.NewInt(0))
+}
+
// Initialize initializes governance contract state.
func (s *GovernanceState) Initialize(config *params.DexconConfig, totalSupply *big.Int) {
if config.NextHalvingSupply.Cmp(totalSupply) <= 0 {
@@ -1009,6 +1086,22 @@ func (s *GovernanceState) Initialize(config *params.DexconConfig, totalSupply *b
// Set DKGRound.
s.SetDKGRound(big.NewInt(int64(dexCore.DKGDelayRound)))
+
+ // Set Whitelist
+ s.setWhitelist(config.IsConsortium)
+}
+
+func (s *GovernanceState) setWhitelist(isConsortium bool) {
+ if isConsortium {
+ s.EnableConsortium()
+ for _, node := range s.Nodes() {
+ address, err := publicKeyToNodeKeyAddress(node.PublicKey)
+ if err != nil {
+ panic(err)
+ }
+ s.AddToWhitelist(address)
+ }
+ }
}
// Register is a helper function for creating genesis state.
@@ -1079,6 +1172,8 @@ func (s *GovernanceState) Configuration() *params.DexconConfig {
RoundLength: s.getStateBigInt(big.NewInt(roundLengthLoc)).Uint64(),
MinBlockInterval: s.getStateBigInt(big.NewInt(minBlockIntervalLoc)).Uint64(),
FineValues: s.FineValues(),
+ AddressWhitelist: s.AddressWhitelists(),
+ IsConsortium: s.getStateBigInt(big.NewInt(isConsortiumLoc)).Uint64() != 0,
}
}
@@ -1098,7 +1193,11 @@ func (s *GovernanceState) UpdateConfiguration(cfg *params.DexconConfig) {
s.setStateBigInt(big.NewInt(roundLengthLoc), big.NewInt(int64(cfg.RoundLength)))
s.setStateBigInt(big.NewInt(minBlockIntervalLoc), big.NewInt(int64(cfg.MinBlockInterval)))
s.SetFineValues(cfg.FineValues)
-
+ if cfg.IsConsortium {
+ for _, addr := range cfg.AddressWhitelist {
+ s.AddToWhitelist(addr)
+ }
+ }
// Calculate set size.
s.CalNotarySetSize()
}
@@ -2274,6 +2373,20 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re
return nil, errExecutionReverted
}
return g.addDKGSuccess(Success)
+ case "addToWhitelist":
+ var address common.Address
+ if err := method.Inputs.Unpack(&address, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ offset, err := g.addToWhitelist(address)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ res, err := method.Outputs.Pack(offset)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
case "nodesLength":
res, err := method.Outputs.Pack(g.state.LenNodes())
if err != nil {
@@ -2295,6 +2408,20 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re
return nil, errExecutionReverted
}
return g.proposeCRS(args.Round, args.SignedCRS)
+ case "removeFromWhitelist":
+ var address common.Address
+ if err := method.Inputs.Unpack(&address, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ offset, err := g.removeFromWhitelist(address)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ res, err := method.Outputs.Pack(offset)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
case "report":
args := struct {
Type *big.Int
@@ -2371,6 +2498,12 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re
return nil, errExecutionReverted
}
return g.updateNodeInfo(args.Name, args.Email, args.Location, args.Url)
+ case "whitelistLength":
+ res, err := method.Outputs.Pack(g.state.LenWhitelist())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
case "withdraw":
return g.withdraw()
case "withdrawable":
@@ -2379,11 +2512,21 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re
return nil, errExecutionReverted
}
return res, nil
-
// --------------------------------
// Solidity auto generated methods.
// --------------------------------
+ case "addressWhitelist":
+ offset := new(big.Int)
+ if err := method.Inputs.Unpack(&offset, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ address := g.state.AddressWhitelist(offset)
+ res, err := method.Outputs.Pack(address)
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
case "blockGasLimit":
res, err := method.Outputs.Pack(g.state.BlockGasLimit())
if err != nil {
@@ -2538,6 +2681,12 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re
return nil, errExecutionReverted
}
return res, nil
+ case "isConsortium":
+ res, err := method.Outputs.Pack(g.state.IsConsortium())
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
case "lambdaBA":
res, err := method.Outputs.Pack(g.state.LambdaBA())
if err != nil {
@@ -2694,7 +2843,18 @@ func (g *GovernanceContract) Run(evm *EVM, input []byte, contract *Contract) (re
return nil, errExecutionReverted
}
return res, nil
+ case "whitelistOffsetByAddress":
+ address := common.Address{}
+ if err := method.Inputs.Unpack(&address, arguments); err != nil {
+ return nil, errExecutionReverted
+ }
+ res, err := method.Outputs.Pack(g.state.WhitelistOffsetByAddress(address))
+ if err != nil {
+ return nil, errExecutionReverted
+ }
+ return res, nil
}
+
return nil, errExecutionReverted
}
@@ -2801,6 +2961,22 @@ func (g *GovernanceContract) replaceNodePublicKey(newPublicKey []byte) ([]byte,
return nil, nil
}
+func (g *GovernanceContract) addToWhitelist(addr common.Address) (*big.Int, error) {
+ // Only owner can update whitelist.
+ if g.contract.Caller() != g.state.Owner() {
+ return nil, errExecutionReverted
+ }
+ return g.state.AddToWhitelist(addr), nil
+}
+
+func (g *GovernanceContract) removeFromWhitelist(addr common.Address) (*big.Int, error) {
+ // Only owner can update whitelist.
+ if g.contract.Caller() != g.state.Owner() {
+ return nil, errExecutionReverted
+ }
+ return g.state.DeleteAddressWhitelist(addr), nil
+}
+
func PackProposeCRS(round uint64, signedCRS []byte) ([]byte, error) {
method := GovernanceABI.Name2Method["proposeCRS"]
res, err := method.Inputs.Pack(big.NewInt(int64(round)), signedCRS)
diff --git a/core/vm/oracle_contracts_test.go b/core/vm/oracle_contracts_test.go
index 192628b22..bf2f7c71a 100644
--- a/core/vm/oracle_contracts_test.go
+++ b/core/vm/oracle_contracts_test.go
@@ -1022,6 +1022,137 @@ func (g *GovernanceContractTestSuite) TestMiscVariableReading() {
g.Require().NoError(err)
}
+func (g *GovernanceContractTestSuite) TestIsConsortium() {
+ var isConsortium bool
+
+ _, addr1 := newPrefundAccount(g.stateDB)
+
+ input, err := GovernanceABI.ABI.Pack("isConsortium")
+ g.Require().NoError(err)
+ res, err := g.call(GovernanceContractAddress, addr1, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = GovernanceABI.ABI.Unpack(&isConsortium, "isConsortium", res)
+ g.Require().NoError(err)
+ g.Require().Equal(false, isConsortium)
+
+ g.s.EnableConsortium()
+ res, err = g.call(GovernanceContractAddress, addr1, input, big.NewInt(0))
+ g.Require().NoError(err)
+ err = GovernanceABI.ABI.Unpack(&isConsortium, "isConsortium", res)
+ g.Require().NoError(err)
+ g.Require().Equal(true, isConsortium)
+}
+
+func (g *GovernanceContractTestSuite) TestUpdateWhitelist() {
+ checkLength := func(expectLen *big.Int) {
+ var length *big.Int
+
+ lenInput, err := GovernanceABI.ABI.Pack("whitelistLength")
+ g.Require().NoError(err)
+ res, err := g.call(GovernanceContractAddress, g.config.Owner, lenInput, big.NewInt(0))
+ err = GovernanceABI.ABI.Unpack(&length, "whitelistLength", res)
+ g.Require().NoError(err)
+ g.Require().Equal(expectLen.Int64(), length.Int64())
+ }
+ check := func(addr common.Address, offset *big.Int) {
+ var resOffset *big.Int
+ var resAddr common.Address
+
+ value := big.NewInt(0)
+ // check offset
+ input, err := GovernanceABI.ABI.Pack("whitelistOffsetByAddress", addr)
+ g.Require().NoError(err)
+ res, err := g.call(GovernanceContractAddress, addr, input, value)
+ g.Require().NoError(err)
+ err = GovernanceABI.ABI.Unpack(&resOffset, "whitelistOffsetByAddress", res)
+ g.Require().NoError(err)
+ g.Require().Equal(offset.Int64(), resOffset.Int64())
+
+ // check address
+ if offset.Cmp(big.NewInt(0)) >= 0 {
+ input, err = GovernanceABI.ABI.Pack("addressWhitelist", offset)
+ res, err = g.call(GovernanceContractAddress, addr, input, value)
+ g.Require().NoError(err)
+ err = GovernanceABI.ABI.Unpack(&resAddr, "addressWhitelist", res)
+ g.Require().NoError(err)
+ g.Require().Equal(addr, resAddr)
+ }
+ }
+ _, addr1 := newPrefundAccount(g.stateDB)
+ _, addr2 := newPrefundAccount(g.stateDB)
+ _, addr3 := newPrefundAccount(g.stateDB)
+
+ input, err := GovernanceABI.ABI.Pack("addToWhitelist", addr1)
+ g.Require().NoError(err)
+
+ // Call with non-owner.
+ _, err = g.call(GovernanceContractAddress, addr1, input, big.NewInt(0))
+ g.Require().NotNil(err)
+ // Call with owner.
+ _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0))
+ g.Require().NoError(err)
+ checkLength(big.NewInt(1))
+ // duplicated call should not affect
+ _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0))
+ g.Require().NoError(err)
+ checkLength(big.NewInt(1))
+ // append addr2
+ input, err = GovernanceABI.ABI.Pack("addToWhitelist", addr2)
+ g.Require().NoError(err)
+ _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0))
+ g.Require().NoError(err)
+
+ checkLength(big.NewInt(2))
+ check(addr1, big.NewInt(0))
+ check(addr2, big.NewInt(1))
+
+ // delete addr2
+ input, err = GovernanceABI.ABI.Pack("removeFromWhitelist", addr2)
+ g.Require().NoError(err)
+ // Call with non-owner.
+ _, err = g.call(GovernanceContractAddress, addr1, input, big.NewInt(0))
+ g.Require().NotNil(err)
+ // Call with owner
+ _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0))
+ g.Require().NoError(err)
+ check(addr2, big.NewInt(-1))
+ checkLength(big.NewInt(1))
+
+ // append addr2 back
+ input, err = GovernanceABI.ABI.Pack("addToWhitelist", addr2)
+ g.Require().NoError(err)
+ _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0))
+ g.Require().NoError(err)
+ checkLength(big.NewInt(2))
+ check(addr1, big.NewInt(0))
+ check(addr2, big.NewInt(1))
+
+ // delete addr1
+ input, err = GovernanceABI.ABI.Pack("removeFromWhitelist", addr1)
+ g.Require().NoError(err)
+ _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0))
+ g.Require().NoError(err)
+ check(addr1, big.NewInt(-1))
+ check(addr2, big.NewInt(0))
+ checkLength(big.NewInt(1))
+
+ // delete addr2
+ input, err = GovernanceABI.ABI.Pack("removeFromWhitelist", addr2)
+ g.Require().NoError(err)
+ _, err = g.call(GovernanceContractAddress, g.config.Owner, input, big.NewInt(0))
+ g.Require().NoError(err)
+ check(addr1, big.NewInt(-1))
+ check(addr2, big.NewInt(-1))
+ checkLength(big.NewInt(0))
+
+ // duplicated delete addr2
+ input, err = GovernanceABI.ABI.Pack("removeFromWhitelist", addr2)
+ g.Require().NoError(err)
+ // delete not in whitelist address
+ input, err = GovernanceABI.ABI.Pack("removeFromWhitelist", addr3)
+ g.Require().NoError(err)
+}
+
func (g *GovernanceContractTestSuite) TestHalvingCondition() {
// TotalSupply 2.5B reached
g.s.MiningHalved()
@@ -1244,6 +1375,66 @@ func (g *GovernanceContractTestSuite) TestResetDKG() {
}
}
+func (g *GovernanceContractTestSuite) TestConsortium() {
+ g.Require().False(g.s.IsConsortium())
+ g.s.EnableConsortium()
+ g.Require().True(g.s.IsConsortium())
+}
+
+func (g *GovernanceContractTestSuite) TestAddWhitelist() {
+ _, addr1 := newPrefundAccount(g.stateDB)
+ _, addr2 := newPrefundAccount(g.stateDB)
+ _, addr3 := newPrefundAccount(g.stateDB)
+ // no address in list
+ expectAddress := g.s.AddressWhitelist(big.NewInt(0))
+ g.Require().Equal(common.Address{}, expectAddress)
+ expectAddrList := g.s.AddressWhitelists()
+ g.Require().Equal([]common.Address{}, expectAddrList)
+
+ // insert addr
+ g.s.AddToWhitelist(addr1)
+ g.s.AddToWhitelist(addr1) // duplicated insertion should be ignored
+ expectAddress = g.s.AddressWhitelist(big.NewInt(0))
+ g.Require().Equal(addr1, expectAddress)
+ expectAddrList = g.s.AddressWhitelists()
+ g.Require().Equal([]common.Address{addr1}, expectAddrList)
+
+ g.s.AddToWhitelist(addr2)
+ expectAddress = g.s.AddressWhitelist(big.NewInt(1))
+ g.Require().Equal(addr2, expectAddress)
+ expectAddrList = g.s.AddressWhitelists()
+ g.Require().Equal([]common.Address{addr1, addr2}, expectAddrList)
+
+ offset := g.s.WhitelistOffsetByAddress(addr1)
+ g.Require().Equal(true, offset.Cmp(big.NewInt(0)) == 0)
+ offset = g.s.WhitelistOffsetByAddress(addr2)
+ g.Require().Equal(true, offset.Cmp(big.NewInt(1)) == 0)
+ offset = g.s.WhitelistOffsetByAddress(addr3)
+ g.Require().Equal(true, offset.Cmp(big.NewInt(-1)) == 0)
+
+ // remove addr
+ g.s.DeleteAddressWhitelist(addr1)
+ g.s.DeleteAddressWhitelist(addr1) // duplicated remove should be ignored
+
+ offset = g.s.WhitelistOffsetByAddress(addr1)
+ g.Require().Equal(true, offset.Cmp(big.NewInt(-1)) == 0)
+ offset = g.s.WhitelistOffsetByAddress(addr2)
+ g.Require().Equal(true, offset.Cmp(big.NewInt(0)) == 0)
+
+ expectAddress = g.s.AddressWhitelist(big.NewInt(0))
+ g.Require().Equal(addr2, expectAddress)
+ expectAddrList = g.s.AddressWhitelists()
+ g.Require().Equal([]common.Address{addr2}, expectAddrList)
+
+ g.s.DeleteAddressWhitelist(addr2)
+
+ offset = g.s.WhitelistOffsetByAddress(addr2)
+ g.Require().Equal(true, offset.Cmp(big.NewInt(-1)) == 0)
+
+ expectAddrList = g.s.AddressWhitelists()
+ g.Require().Equal([]common.Address{}, expectAddrList)
+}
+
func TestGovernanceContract(t *testing.T) {
suite.Run(t, new(GovernanceContractTestSuite))
}