Skip to content

Commit 38d21fb

Browse files
committed
Merge branch 'readonlycrosschain' of https://github.com/springrain/xupercore into readonlycrosschain
2 parents c08880d + b0000e1 commit 38d21fb

37 files changed

Lines changed: 668 additions & 273 deletions

bcs/consensus/pow/pow.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ func NewPoWConsensus(cCtx context.ConsensusCtx, cCfg def.ConsensusConfig) base.C
9090
if target > 256 {
9191
pow.bitcoinFlag = true
9292
}
93+
pow.targetBits = target
94+
pow.maxDifficulty = big.NewInt(int64(config.MaxTarget))
9395
// 重启时需要重新更新目标target
9496
tipBlock := cCtx.Ledger.GetTipBlock()
9597
if tipBlock.GetHeight() > cCfg.StartHeight {
@@ -101,8 +103,6 @@ func NewPoWConsensus(cCtx context.ConsensusCtx, cCfg def.ConsensusConfig) base.C
101103
target = bits
102104
cCtx.XLog.Debug("PoW::NewPoWConsensus::refreshDifficulty after restart.")
103105
}
104-
pow.targetBits = target
105-
pow.maxDifficulty = big.NewInt(int64(config.MaxTarget))
106106
if pow.bitcoinFlag {
107107
// 通过MaxTarget和DefaultTarget解析maxDifficulty和DefaultDifficulty
108108
md, fNegative, fOverflow := SetCompact(config.MaxTarget)
@@ -229,7 +229,7 @@ func (pow *PoWConsensus) CheckMinerMatch(ctx xcontext.XContext, block context.Bl
229229
if err != nil {
230230
ctx.GetLog().Warn("PoW::CheckMinerMatch::verifyECDSA error", "error", err, "miner", string(block.GetProposer()))
231231
}
232-
if valid && pow.Ledger.GetTipBlock().GetHeight() < block.GetHeight() {
232+
if valid && pow.Ledger.QueryTipBlockHeader().GetHeight() < block.GetHeight() {
233233
pow.status.newHeight = block.GetHeight()
234234
pow.newblock <- block.GetHeight()
235235
}
@@ -238,7 +238,7 @@ func (pow *PoWConsensus) CheckMinerMatch(ctx xcontext.XContext, block context.Bl
238238

239239
// ProcessBeforeMiner 更新下一次pow挖矿时的targetBits
240240
func (pow *PoWConsensus) ProcessBeforeMiner(timestamp int64) ([]byte, []byte, error) {
241-
tipHeight := pow.Ledger.GetTipBlock().GetHeight()
241+
tipHeight := pow.Ledger.QueryTipBlockHeader().GetHeight()
242242
preBlock, err := pow.Ledger.QueryBlockHeaderByHeight(tipHeight)
243243
if err != nil {
244244
pow.XLog.Error("PoW::ProcessBeforeMiner::cannnot find preBlock", "logid", pow.XLog.GetLogId())
@@ -261,7 +261,7 @@ func (pow *PoWConsensus) ProcessBeforeMiner(timestamp int64) ([]byte, []byte, er
261261

262262
// ProcessConfirmBlock 此处更新最新的block高度
263263
func (pow *PoWConsensus) ProcessConfirmBlock(block context.BlockInterface) error {
264-
if pow.Ledger.GetTipBlock().GetHeight() < block.GetHeight() {
264+
if pow.Ledger.QueryTipBlockHeader().GetHeight() < block.GetHeight() {
265265
pow.status.newHeight = block.GetHeight()
266266
}
267267
return nil

bcs/consensus/tdpos/kernel_contract.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -397,8 +397,14 @@ func (tp *tdposConsensus) runGetTdposInfos(contractCtx contract.KContext) (*cont
397397
return common.NewContractErrResponse(common.StatusErr, "Internal error."), err
398398
}
399399
}
400-
r := `{"nominate":` + fmt.Sprintf("%v", nominateValue) + `,"vote":` + fmt.Sprintf("%v", voteMap) + `,"revoke":` + fmt.Sprintf("%v", revokeValue) + `}`
401-
return common.NewContractOKResponse([]byte(r)), nil
400+
401+
return_map := map[string]interface{}{
402+
"nominate": nominateValue,
403+
"vote": voteMap,
404+
"revoke": revokeValue,
405+
}
406+
return_bytes, _ := json.Marshal(return_map)
407+
return common.NewContractOKResponse(return_bytes), nil
402408
}
403409

404410
func (tp *tdposConsensus) checkArgs(txArgs map[string][]byte) (string, error) {

bcs/consensus/tdpos/schedule.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ func (s *tdposSchedule) GetLeader(round int64) string {
157157
if proposers == nil {
158158
return ""
159159
}
160-
addTime := s.calAddTime(round, s.ledger.GetTipBlock().GetHeight())
160+
addTime := s.calAddTime(round, s.ledger.QueryTipBlockHeader().GetHeight())
161161
_, pos, _ := s.minerScheduling(time.Now().UnixNano() + addTime)
162162
if pos >= s.proposerNum {
163163
return ""
@@ -222,7 +222,7 @@ func (s *tdposSchedule) CalculateProposers(height int64) ([]string, error) {
222222
if height < s.startHeight+3 {
223223
return s.initValidators, nil
224224
}
225-
addTime := s.calAddTime(height, s.ledger.GetTipBlock().GetHeight())
225+
addTime := s.calAddTime(height, s.ledger.QueryTipBlockHeader().GetHeight())
226226
inputTerm, _, _ := s.minerScheduling(time.Now().UnixNano() + addTime)
227227
if s.curTerm == inputTerm {
228228
return s.validators, nil
@@ -303,7 +303,7 @@ func (s *tdposSchedule) CalOldProposers(height int64, timestamp int64, storage [
303303
if height < s.startHeight+3 {
304304
return s.initValidators, nil
305305
}
306-
tipHeight := s.ledger.GetTipBlock().GetHeight()
306+
tipHeight := s.ledger.QueryTipBlockHeader().GetHeight()
307307
if tipHeight > height {
308308
// 情况一:读取历史值,height对应区块存在于账本中,此时分成历史Key读取和计算差值两部分
309309
return s.calHisValidators(height)

bcs/consensus/tdpos/tdpos.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ func NewTdposConsensus(cCtx cctx.ConsensusCtx, cCfg def.ConsensusConfig) base.Co
9292
contractGetTdposInfos: tdpos.runGetTdposInfos,
9393
}
9494
for method, f := range tdposKMethods {
95-
if _, err := cCtx.Contract.GetKernRegistry().GetKernMethod(schedule.bindContractBucket, method); err != nil {
96-
cCtx.Contract.GetKernRegistry().RegisterKernMethod(schedule.bindContractBucket, method, f)
97-
}
95+
// 若有历史句柄,删除老句柄
96+
cCtx.Contract.GetKernRegistry().UnregisterKernMethod(schedule.bindContractBucket, method)
97+
cCtx.Contract.GetKernRegistry().RegisterKernMethod(schedule.bindContractBucket, method, f)
9898
}
9999

100100
// 凡属于共识升级的逻辑,新建的Tdpos实例将直接将当前值置为true,原因是上一共识模块已经在当前值生成了高度为trigger height的区块,新的实例会再生成一边
@@ -116,7 +116,7 @@ func NewTdposConsensus(cCtx cctx.ConsensusCtx, cCfg def.ConsensusConfig) base.Co
116116
CurrentView: cCfg.StartHeight,
117117
}
118118
// 重启状态检查1,pacemaker需要重置
119-
tipHeight := cCtx.Ledger.GetTipBlock().GetHeight()
119+
tipHeight := cCtx.Ledger.QueryTipBlockHeader().GetHeight()
120120
if !bytes.Equal(qcTree.GetGenesisQC().In.GetProposalId(), qcTree.GetRootQC().In.GetProposalId()) {
121121
pacemaker.CurrentView = tipHeight - 1
122122
}
@@ -169,18 +169,18 @@ Again:
169169
}
170170
// 即现在有可能发生候选人变更,此时需要拿tipHeight-3=H高度的稳定高度当作快照,故input时的高度一定是TipHeight
171171
if term > tp.election.curTerm {
172-
tp.election.UpdateProposers(tp.election.ledger.GetTipBlock().GetHeight())
172+
tp.election.UpdateProposers(tp.election.ledger.QueryTipBlockHeader().GetHeight())
173173
}
174174
// 查当前term 和 pos是否是自己
175175
tp.election.curTerm = term
176176
tp.election.miner = tp.election.validators[pos]
177177
// master check
178178
if tp.election.validators[pos] == tp.election.address {
179-
tp.log.Debug("consensus:tdpos:CompeteMaster: now xterm infos", "term", term, "pos", pos, "blockPos", blockPos, "master", true, "height", tp.election.ledger.GetTipBlock().GetHeight())
179+
tp.log.Debug("consensus:tdpos:CompeteMaster: now xterm infos", "term", term, "pos", pos, "blockPos", blockPos, "master", true, "height", tp.election.ledger.QueryTipBlockHeader().GetHeight())
180180
s := tp.needSync()
181181
return true, s, nil
182182
}
183-
tp.log.Debug("consensus:tdpos:CompeteMaster: now xterm infos", "term", term, "pos", pos, "blockPos", blockPos, "master", false, "height", tp.election.ledger.GetTipBlock().GetHeight())
183+
tp.log.Debug("consensus:tdpos:CompeteMaster: now xterm infos", "term", term, "pos", pos, "blockPos", blockPos, "master", false, "height", tp.election.ledger.QueryTipBlockHeader().GetHeight())
184184
return false, false, nil
185185
}
186186

bcs/consensus/tdpos/tdpos_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
func getTdposConsensusConf() string {
1818
return `{
19+
"version": "2",
1920
"timestamp": "1559021720000000000",
2021
"proposer_num": "2",
2122
"period": "3000",
@@ -31,6 +32,7 @@ func getTdposConsensusConf() string {
3132

3233
func getBFTTdposConsensusConf() string {
3334
return `{
35+
"version": "2",
3436
"timestamp": "1559021720000000000",
3537
"proposer_num": "2",
3638
"period": "3000",

bcs/consensus/xpoa/common.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package xpoa
33
import (
44
"encoding/json"
55
"errors"
6+
"strconv"
67
)
78

89
var (
@@ -30,7 +31,6 @@ const (
3031
)
3132

3233
type xpoaConfig struct {
33-
Version int64 `json:"version,omitempty"`
3434
// 每个候选人每轮出块个数
3535
BlockNum int64 `json:"block_num"`
3636
// 单位为毫秒
@@ -103,3 +103,28 @@ func (a aksSlice) Less(i, j int) bool {
103103
}
104104
return a[j].Weight < a[i].Weight
105105
}
106+
107+
type xpoaStringConfig struct {
108+
Version string `json:"version,omitempty"`
109+
}
110+
111+
type xpoaIntConfig struct {
112+
Version int64 `json:"version,omitempty"`
113+
}
114+
115+
// ParseVersion 支持string格式和int格式的version type
116+
func ParseVersion(cfg string) (int64, error) {
117+
intVersion := xpoaIntConfig{}
118+
if err := json.Unmarshal([]byte(cfg), &intVersion); err == nil {
119+
return intVersion.Version, nil
120+
}
121+
strVersion := xpoaStringConfig{}
122+
if err := json.Unmarshal([]byte(cfg), &strVersion); err != nil {
123+
return 0, err
124+
}
125+
version, err := strconv.ParseInt(strVersion.Version, 10, 64)
126+
if err != nil {
127+
return 0, err
128+
}
129+
return version, nil
130+
}

bcs/consensus/xpoa/common_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,40 @@ func TestLoadValidatorsMultiInfo(t *testing.T) {
4242
t.Error("TestLoadValidatorsMultiInfo error 2.")
4343
}
4444
}
45+
46+
func TestParseVersion(t *testing.T) {
47+
strVersion := `{
48+
"version": "2"
49+
}`
50+
v, err := ParseVersion(strVersion)
51+
if err != nil {
52+
t.Error("ParseVersion err, err: ", err)
53+
return
54+
}
55+
if v != 2 {
56+
t.Error("ParseVersion err, v: ", v)
57+
return
58+
}
59+
intVersion := `{
60+
"version": 3
61+
}`
62+
v, err = ParseVersion(intVersion)
63+
if err != nil {
64+
t.Error("ParseVersion err, err: ", err)
65+
return
66+
}
67+
if v != 3 {
68+
t.Error("ParseVersion err, v: ", v)
69+
return
70+
}
71+
empryVersion := `{}`
72+
v, err = ParseVersion(empryVersion)
73+
if err != nil {
74+
t.Error("ParseVersion err, err: ", err)
75+
return
76+
}
77+
if v != 0 {
78+
t.Error("ParseVersion err, v: ", v)
79+
return
80+
}
81+
}

bcs/consensus/xpoa/kernel_contract.go

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,25 @@ func (x *xpoaConsensus) methodEditValidates(contractCtx contract.KContext) (*con
3333
if err != nil {
3434
return common.NewContractErrResponse(common.StatusBadRequest, "invalid acl: pls check accept value."), err
3535
}
36-
if !x.isAuthAddress(aks, acceptValue) {
36+
37+
curValiBytes, err := contractCtx.Get(x.election.bindContractBucket,
38+
[]byte(fmt.Sprintf("%d_%s", x.election.consensusVersion, validateKeys)))
39+
curVali, err := func() ([]string, error) {
40+
if err != nil || curValiBytes == nil {
41+
return x.election.initValidators, nil
42+
}
43+
var curValiKey ProposerInfo
44+
err = json.Unmarshal(curValiBytes, &curValiKey)
45+
if err != nil {
46+
x.log.Error("Unmarshal error")
47+
return nil, err
48+
}
49+
return curValiKey.Address, nil
50+
}()
51+
if err != nil {
52+
return common.NewContractErrResponse(common.StatusBadRequest, err.Error()), err
53+
}
54+
if !x.isAuthAddress(curVali, aks, acceptValue, x.election.enableBFT) {
3755
return common.NewContractErrResponse(common.StatusBadRequest, aclErr.Error()), aclErr
3856
}
3957

@@ -87,10 +105,18 @@ func (x *xpoaConsensus) methodGetValidates(contractCtx contract.KContext) (*cont
87105
}
88106

89107
// isAuthAddress 判断输入aks是否能在贪心下仍能满足签名数量>33%(Chained-BFT装载) or 50%(一般情况)
90-
func (x *xpoaConsensus) isAuthAddress(aks map[string]float64, threshold float64) bool {
108+
func (x *xpoaConsensus) isAuthAddress(validators []string, aks map[string]float64, threshold float64, enableBFT bool) bool {
109+
// 0. 是否是单个候选人
110+
if len(validators) == 1 {
111+
weight, ok := aks[validators[0]]
112+
if !ok {
113+
return false
114+
}
115+
return weight >= threshold
116+
}
91117
// 1. 判断aks中的地址是否是当前集合地址
92118
for addr, _ := range aks {
93-
if !Find(addr, x.election.validators) {
119+
if !Find(addr, validators) {
94120
return false
95121
}
96122
}
@@ -106,15 +132,14 @@ func (x *xpoaConsensus) isAuthAddress(aks map[string]float64, threshold float64)
106132
greedyCount := 0
107133
sum := threshold
108134
for i := 0; i < len(aks); i++ {
109-
if sum > 0 {
110-
sum -= s[i].Weight
111-
greedyCount++
112-
continue
135+
if sum <= 0 {
136+
break
113137
}
114-
break
138+
sum -= s[i].Weight
139+
greedyCount++
115140
}
116-
if !x.election.enableBFT {
117-
return greedyCount >= len(x.election.validators)/2+1
141+
if !enableBFT {
142+
return greedyCount >= len(validators)/2+1
118143
}
119-
return CalFault(int64(greedyCount), int64(len(x.election.validators)))
144+
return CalFault(int64(greedyCount), int64(len(validators)))
120145
}

bcs/consensus/xpoa/kernel_contract_test.go

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,15 @@ var (
1212
"dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN": 0.5,
1313
"WNWk3ekXeM5M2232dY2uCJmEqWhfQiDYT": 0.5,
1414
}
15-
)
16-
17-
func TestIsAuthAddress(t *testing.T) {
18-
cCtx, err := prepare(getXpoaConsensusConf())
19-
if err != nil {
20-
t.Error("prepare error", "error", err)
21-
return
22-
}
23-
i := NewXpoaConsensus(*cCtx, getConfig(getXpoaConsensusConf()))
24-
xpoa, ok := i.(*xpoaConsensus)
25-
if !ok {
26-
t.Error("transfer err.")
15+
aks2 = map[string]float64{
16+
"dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN": 0.5,
17+
"WNWk3ekXeM5M2232dY2uCJmEqWhfQiDYT": 0.6,
2718
}
28-
if !xpoa.isAuthAddress(aks, 0.6) {
29-
t.Error("isAuthAddress err.")
19+
aks3 = map[string]float64{
20+
"dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN": 0.4,
21+
"WNWk3ekXeM5M2232dY2uCJmEqWhfQiDYT": 0.6,
3022
}
31-
}
23+
)
3224

3325
func NewEditArgs() map[string][]byte {
3426
a := make(map[string][]byte)
@@ -85,3 +77,36 @@ func TestMethodGetValidates(t *testing.T) {
8577
return
8678
}
8779
}
80+
81+
func TestIsAuthAddress(t *testing.T) {
82+
cCtx, err := prepare(getXpoaConsensusConf())
83+
if err != nil {
84+
t.Error("prepare error", "error", err)
85+
return
86+
}
87+
i := NewXpoaConsensus(*cCtx, getConfig(getXpoaConsensusConf()))
88+
xpoa, ok := i.(*xpoaConsensus)
89+
if !ok {
90+
t.Error("transfer err.")
91+
return
92+
}
93+
v1 := []string{"dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN", "WNWk3ekXeM5M2232dY2uCJmEqWhfQiDYT"}
94+
if !xpoa.isAuthAddress(v1, aks, 0.6, false) {
95+
t.Error("isAuthAddress err.")
96+
return
97+
}
98+
v2 := []string{"dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN"}
99+
if xpoa.isAuthAddress(v2, aks2, 0.6, true) {
100+
t.Error("isAuthAddress err.")
101+
return
102+
}
103+
v3 := []string{"WNWk3ekXeM5M2232dY2uCJmEqWhfQiDYT"}
104+
if !xpoa.isAuthAddress(v3, aks2, 0.6, true) {
105+
t.Error("isAuthAddress err.")
106+
return
107+
}
108+
v4 := []string{"dpzuVdosQrF2kmzumhVeFQZa1aYcdgFpN", "WNWk3ekXeM5M2232dY2uCJmEqWhfQiDYT"}
109+
if !xpoa.isAuthAddress(v4, aks2, 0.7, true) {
110+
t.Error("isAuthAddress err.")
111+
}
112+
}

bcs/consensus/xpoa/schedule.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ type xpoaSchedule struct {
3434
ledger cctx.LedgerRely
3535
}
3636

37-
func NewXpoaSchedule(xconfig *xpoaConfig, cCtx context.ConsensusCtx, startHeight int64) *xpoaSchedule {
37+
func NewXpoaSchedule(xconfig *xpoaConfig, cCtx context.ConsensusCtx, startHeight, version int64) *xpoaSchedule {
3838
s := xpoaSchedule{
3939
address: cCtx.Network.PeerInfo().Account,
4040
period: xconfig.Period,
4141
blockNum: xconfig.BlockNum,
4242
startHeight: startHeight,
4343
consensusName: "poa",
44-
consensusVersion: xconfig.Version,
44+
consensusVersion: version,
4545
bindContractBucket: poaBucket,
4646
ledger: cCtx.Ledger,
4747
log: cCtx.XLog,
@@ -99,7 +99,7 @@ func (s *xpoaSchedule) GetLeader(round int64) string {
9999
}
100100
// 计算round对应的timestamp大致区间
101101
nTime := time.Now().UnixNano()
102-
if round > s.ledger.GetTipBlock().GetHeight() {
102+
if round > s.ledger.QueryTipBlockHeader().GetHeight() {
103103
nTime += s.period * int64(time.Millisecond)
104104
}
105105
_, pos, _ := s.minerScheduling(nTime, len(v))

0 commit comments

Comments
 (0)