Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
plugin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
link33
plugin
Commits
b23f5c28
Commit
b23f5c28
authored
May 07, 2020
by
caopingcp
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tendermint add aggregate signature
parent
4b5cd0a0
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
1228 additions
and
249 deletions
+1228
-249
go.mod
go.mod
+1
-0
go.sum
go.sum
+16
-0
chain33.test.toml
plugin/consensus/tendermint/chain33.test.toml
+19
-3
consensus_state.go
plugin/consensus/tendermint/consensus_state.go
+0
-0
node.go
plugin/consensus/tendermint/node.go
+35
-11
node_test.go
plugin/consensus/tendermint/node_test.go
+5
-5
peer_set.go
plugin/consensus/tendermint/peer_set.go
+59
-66
secret_connection.go
plugin/consensus/tendermint/secret_connection.go
+13
-11
state.go
plugin/consensus/tendermint/state.go
+1
-1
store.go
plugin/consensus/tendermint/store.go
+4
-0
tendermint.go
plugin/consensus/tendermint/tendermint.go
+50
-25
tendermint_test.go
plugin/consensus/tendermint/tendermint_test.go
+2
-3
nonePerf.go
plugin/consensus/tendermint/tools/nonePerf.go
+1
-1
block.go
plugin/consensus/tendermint/types/block.go
+45
-19
const.go
plugin/consensus/tendermint/types/const.go
+25
-1
height_vote_set.go
plugin/consensus/tendermint/types/height_vote_set.go
+24
-0
params.go
plugin/consensus/tendermint/types/params.go
+1
-1
priv_validator.go
plugin/consensus/tendermint/types/priv_validator.go
+4
-5
round_state.go
plugin/consensus/tendermint/types/round_state.go
+29
-3
signable.go
plugin/consensus/tendermint/types/signable.go
+106
-5
validator_set.go
plugin/consensus/tendermint/types/validator_set.go
+55
-34
vote_set.go
plugin/consensus/tendermint/types/vote_set.go
+154
-4
bls.go
plugin/crypto/bls/bls.go
+308
-0
bls_test.go
plugin/crypto/bls/bls_test.go
+185
-0
init.go
plugin/crypto/init/init.go
+1
-0
valnode.go
plugin/dapp/valnode/commands/valnode.go
+15
-6
exec.go
plugin/dapp/valnode/executor/exec.go
+12
-1
tendermint.proto
plugin/dapp/valnode/proto/tendermint.proto
+58
-44
tendermint.pb.go
plugin/dapp/valnode/types/tendermint.pb.go
+0
-0
No files found.
go.mod
View file @
b23f5c28
...
...
@@ -23,6 +23,7 @@ require (
github.com/miguelmota/go-solidity-sha3 v0.1.0
github.com/mr-tron/base58 v1.1.3
github.com/pborman/uuid v1.2.0
github.com/phoreproject/bls v0.0.0-20200525203911-a88a5ae26844
github.com/pkg/errors v0.8.1
github.com/prometheus/client_golang v0.9.2 // indirect
github.com/prometheus/common v0.4.1
...
...
go.sum
View file @
b23f5c28
This diff is collapsed.
Click to expand it.
plugin/consensus/tendermint/chain33.test.toml
View file @
b23f5c28
...
...
@@ -43,6 +43,8 @@ dbPath="datadir/addrbook"
dbCache
=
4
grpcLogFile
=
"grpc33.log"
[p2p.sub.dht]
channel
=
123
[rpc]
jrpcBindAddr
=
"localhost:8801"
...
...
@@ -73,6 +75,7 @@ powLimitBits = "0x1f2fffff"
[consensus.sub.tendermint]
genesis
=
"14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
genesisAmount
=
100000000
genesisBlockTime
=
1514533394
timeoutTxAvail
=
1000
timeoutPropose
=
1000
...
...
@@ -86,14 +89,21 @@ skipTimeoutCommit=false
createEmptyBlocks
=
true
createEmptyBlocksInterval
=
1
validatorNodes
=[
"127.0.0.1:46656"
,
"127.0.0.2:46656"
]
fastSync
=
false
# Propose阶段是否预执行区块
preExec
=
false
# 签名算法,支持"secp256k1","ed25519","sm2","bls",默认为"ed25519"
signName
=
"ed25519"
# 是否使用聚合签名,签名算法需支持该特性,比如"bls"
useAggregateSignature
=
false
[store]
name
=
"
mavl
"
name
=
"
kvmvcc
"
driver
=
"leveldb"
dbPath
=
"datadir/
mavltree
"
dbPath
=
"datadir/
kvmvcc
"
dbCache
=
128
[store.sub.
mavl
]
[store.sub.
kvmvcc
]
enableMavlPrefix
=
false
enableMVCC
=
false
...
...
@@ -126,3 +136,9 @@ signType="auth_ecdsa"
superManager
=[
"14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
,
]
[metrics]
#是否使能发送metrics数据的发送
enableMetrics
=
false
#数据保存模式
dataEmitMode
=
"influxdb"
plugin/consensus/tendermint/consensus_state.go
View file @
b23f5c28
This diff is collapsed.
Click to expand it.
plugin/consensus/tendermint/node.go
View file @
b23f5c28
...
...
@@ -25,6 +25,7 @@ const (
tryListenSeconds
=
5
handshakeTimeout
=
20
// * time.Second,
maxSendQueueSize
=
1024
minSendQueueSize
=
10
defaultSendTimeout
=
60
*
time
.
Second
//MaxMsgPacketPayloadSize define
MaxMsgPacketPayloadSize
=
10
*
1024
*
1024
...
...
@@ -57,11 +58,12 @@ func Parallel(tasks ...func()) {
wg
.
Wait
()
}
// Gen
Address
ByPubKey method
func
Gen
AddressByPubKey
(
pubkey
crypto
.
PubKey
)
[]
byte
{
// Gen
ID
ByPubKey method
func
Gen
IDByPubKey
(
pubkey
crypto
.
PubKey
)
ID
{
//must add 3 bytes ahead to make compatibly
typeAddr
:=
append
([]
byte
{
byte
(
0x01
),
byte
(
0x01
),
byte
(
0x20
)},
pubkey
.
Bytes
()
...
)
return
crypto
.
Ripemd160
(
typeAddr
)
typeAddr
:=
append
([]
byte
{
byte
(
0x01
),
byte
(
0x01
),
byte
(
0x20
)},
pubkey
.
Bytes
()[
:
32
]
...
)
address
:=
crypto
.
Ripemd160
(
typeAddr
)
return
ID
(
hex
.
EncodeToString
(
address
))
}
// IP2IPPort struct
...
...
@@ -129,6 +131,7 @@ type Node struct {
state
*
ConsensusState
broadcastChannel
chan
MsgInfo
unicastChannel
chan
MsgInfo
started
uint32
// atomic
stopped
uint32
// atomic
quit
chan
struct
{}
...
...
@@ -136,8 +139,6 @@ type Node struct {
// NewNode method
func
NewNode
(
seeds
[]
string
,
protocol
string
,
lAddr
string
,
privKey
crypto
.
PrivKey
,
network
string
,
version
string
,
state
*
ConsensusState
)
*
Node
{
address
:=
GenAddressByPubKey
(
privKey
.
PubKey
())
node
:=
&
Node
{
peerSet
:
NewPeerSet
(),
seeds
:
seeds
,
...
...
@@ -148,16 +149,18 @@ func NewNode(seeds []string, protocol string, lAddr string, privKey crypto.PrivK
privKey
:
privKey
,
Network
:
network
,
Version
:
version
,
ID
:
ID
(
hex
.
EncodeToString
(
address
)),
ID
:
GenIDByPubKey
(
privKey
.
PubKey
(
)),
dialing
:
NewMutexMap
(),
reconnecting
:
NewMutexMap
(),
broadcastChannel
:
make
(
chan
MsgInfo
,
maxSendQueueSize
),
unicastChannel
:
make
(
chan
MsgInfo
,
minSendQueueSize
),
state
:
state
,
localIPs
:
make
(
map
[
string
]
net
.
IP
),
}
state
.
SetOurID
(
node
.
ID
)
state
.
SetBroadcastChannel
(
node
.
broadcastChannel
)
state
.
SetUnicastChannel
(
node
.
unicastChannel
)
localIPs
:=
getNaiveExternalAddress
(
true
)
if
len
(
localIPs
)
>
0
{
...
...
@@ -179,7 +182,7 @@ func (node *Node) Start() {
if
err
==
nil
{
break
}
else
if
i
<
tryListenSeconds
-
1
{
time
.
Sleep
(
time
.
Second
*
1
)
time
.
Sleep
(
time
.
Second
)
}
}
if
err
!=
nil
{
...
...
@@ -213,6 +216,7 @@ func (node *Node) Start() {
go
node
.
StartConsensusRoutine
()
go
node
.
BroadcastRoutine
()
go
node
.
UnicastRoutine
()
}
}
...
...
@@ -305,13 +309,33 @@ func (node *Node) BroadcastRoutine() {
for
{
msg
,
ok
:=
<-
node
.
broadcastChannel
if
!
ok
{
tendermintlog
.
Debug
(
"broadcastChannel closed"
)
tendermintlog
.
Info
(
"broadcastChannel closed"
)
return
}
node
.
Broadcast
(
msg
)
}
}
// BroadcastRoutine receive to broadcast
func
(
node
*
Node
)
UnicastRoutine
()
{
for
{
msg
,
ok
:=
<-
node
.
unicastChannel
if
!
ok
{
tendermintlog
.
Info
(
"unicastChannel closed"
)
return
}
for
_
,
peer
:=
range
node
.
peerSet
.
List
()
{
if
peer
.
ID
()
==
msg
.
PeerID
{
success
:=
peer
.
Send
(
msg
)
if
!
success
{
tendermintlog
.
Error
(
"send failure in UnicastRoutine"
)
}
break
}
}
}
}
func
(
node
*
Node
)
connectComming
(
inConn
net
.
Conn
)
{
maxPeers
:=
maxNumPeers
if
maxPeers
<=
node
.
peerSet
.
Size
()
{
...
...
@@ -640,7 +664,7 @@ func dial(addr string) (net.Conn, error) {
func
newOutboundPeerConn
(
addr
string
,
ourNodePrivKey
crypto
.
PrivKey
,
onPeerError
func
(
Peer
,
interface
{}),
state
*
ConsensusState
)
(
*
peerConn
,
error
)
{
conn
,
err
:=
dial
(
addr
)
if
err
!=
nil
{
return
&
peerConn
{},
fmt
.
Errorf
(
"
Error creating peer
:%v"
,
err
)
return
&
peerConn
{},
fmt
.
Errorf
(
"
newOutboundPeerConn dial fail
:%v"
,
err
)
}
pc
,
err
:=
newPeerConn
(
conn
,
true
,
true
,
ourNodePrivKey
,
onPeerError
,
state
)
...
...
@@ -684,7 +708,7 @@ func newPeerConn(
// Encrypt connection
conn
,
err
=
MakeSecretConnection
(
conn
,
ourNodePrivKey
)
if
err
!=
nil
{
return
pc
,
fmt
.
Errorf
(
"
Error creating peer
:%v"
,
err
)
return
pc
,
fmt
.
Errorf
(
"
MakeSecretConnection fail
:%v"
,
err
)
}
// Only the information we already have
...
...
plugin/consensus/tendermint/node_test.go
View file @
b23f5c28
...
...
@@ -54,17 +54,19 @@ func TestParallel(t *testing.T) {
assert
.
Equal
(
t
,
6
,
sum
)
}
func
TestGen
Address
ByPubKey
(
t
*
testing
.
T
)
{
func
TestGen
ID
ByPubKey
(
t
*
testing
.
T
)
{
tmp
,
err
:=
hex
.
DecodeString
(
privKey
)
assert
.
Nil
(
t
,
err
)
priv
,
err
:=
secureConnCrypto
.
PrivKeyFromBytes
(
tmp
)
assert
.
Nil
(
t
,
err
)
addr
:=
GenAddressByPubKey
(
priv
.
PubKey
())
id
:=
GenIDByPubKey
(
priv
.
PubKey
())
addr
,
err
:=
hex
.
DecodeString
(
string
(
id
))
assert
.
Nil
(
t
,
err
)
strAddr
:=
fmt
.
Sprintf
(
"%X"
,
addr
)
assert
.
Equal
(
t
,
expectAddress
,
strAddr
)
fmt
.
Println
(
"TestGen
Address
ByPubKey ok"
)
fmt
.
Println
(
"TestGen
ID
ByPubKey ok"
)
}
func
TestIP2IPPort
(
t
*
testing
.
T
)
{
...
...
@@ -154,7 +156,6 @@ func testUpdateStateRoutine(t *testing.T, pc *peerConn) {
},
}
ps
:=
pc
.
state
pc
.
waitQuit
.
Add
(
1
)
go
pc
.
updateStateRoutine
()
//NewRoundStepID msg
...
...
@@ -249,7 +250,6 @@ func testUpdateStateRoutine(t *testing.T, pc *peerConn) {
assert
.
NotNil
(
t
,
ps
.
getVoteBitArray
(
3
,
2
,
ttypes
.
VoteTypePrecommit
))
pc
.
quitUpdate
<-
struct
{}{}
pc
.
waitQuit
.
Wait
()
fmt
.
Println
(
"testUpdateStateRoutine ok"
)
}
plugin/consensus/tendermint/peer_set.go
View file @
b23f5c28
...
...
@@ -8,13 +8,11 @@ import (
"bufio"
"bytes"
"encoding/binary"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net"
"reflect"
"runtime/debug"
"sync"
"sync/atomic"
"time"
...
...
@@ -56,8 +54,6 @@ type Peer interface {
Stop
()
SetTransferChannel
(
chan
MsgInfo
)
//Set(string, interface{})
//Get(string) interface{}
}
// PeerConnState struct
...
...
@@ -85,10 +81,8 @@ type peerConn struct {
started
uint32
//atomic
stopped
uint32
// atomic
quitSend
chan
struct
{}
quitUpdate
chan
struct
{}
quitBeat
chan
struct
{}
waitQuit
sync
.
WaitGroup
transferChannel
chan
MsgInfo
...
...
@@ -222,8 +216,7 @@ func (pc *peerConn) ID() ID {
if
len
(
pc
.
id
)
!=
0
{
return
pc
.
id
}
address
:=
GenAddressByPubKey
(
pc
.
conn
.
(
*
SecretConnection
)
.
RemotePubKey
())
pc
.
id
=
ID
(
hex
.
EncodeToString
(
address
))
pc
.
id
=
GenIDByPubKey
(
pc
.
conn
.
(
*
SecretConnection
)
.
RemotePubKey
())
return
pc
.
id
}
...
...
@@ -265,6 +258,11 @@ func (pc *peerConn) SetTransferChannel(transferChannel chan MsgInfo) {
pc
.
transferChannel
=
transferChannel
}
func
(
pc
*
peerConn
)
String
()
string
{
return
fmt
.
Sprintf
(
"PeerConn{outbound:%v persistent:%v ip:%s id:%s started:%v stopped:%v}"
,
pc
.
outbound
,
pc
.
persistent
,
pc
.
ip
.
String
(),
pc
.
id
,
pc
.
started
,
pc
.
stopped
)
}
func
(
pc
*
peerConn
)
CloseConn
()
{
err
:=
pc
.
conn
.
Close
()
// nolint: errcheck
if
err
!=
nil
{
...
...
@@ -358,7 +356,7 @@ func (pc *peerConn) Send(msg MsgInfo) bool {
atomic
.
AddInt32
(
&
pc
.
sendQueueSize
,
1
)
return
true
case
<-
time
.
After
(
defaultSendTimeout
)
:
tendermintlog
.
Error
(
"send msg timeout"
,
"peerip"
,
msg
.
PeerIP
,
"msg"
,
msg
.
Msg
)
tendermintlog
.
Error
(
"send msg timeout"
,
"peerip"
,
msg
.
PeerIP
,
"msg"
,
msg
)
return
false
}
}
...
...
@@ -379,9 +377,25 @@ func (pc *peerConn) TrySend(msg MsgInfo) bool {
// PickSendVote picks a vote and sends it to the peer.
// Returns true if vote was sent.
func
(
pc
*
peerConn
)
PickSendVote
(
votes
ttypes
.
VoteSetReader
)
bool
{
if
vote
,
ok
:=
pc
.
state
.
PickVoteToSend
(
votes
);
ok
{
if
useAggSig
{
if
pc
.
state
.
AggPrecommit
{
time
.
Sleep
(
pc
.
myState
.
PeerGossipSleep
())
return
false
}
aggVote
:=
votes
.
GetAggVote
()
if
aggVote
!=
nil
{
msg
:=
MsgInfo
{
TypeID
:
ttypes
.
AggVoteID
,
Msg
:
aggVote
.
AggVote
,
PeerID
:
pc
.
id
,
PeerIP
:
pc
.
ip
.
String
()}
tendermintlog
.
Debug
(
"Sending aggregate vote message"
,
"msg"
,
msg
)
if
pc
.
Send
(
msg
)
{
pc
.
state
.
SetHasAggPrecommit
(
aggVote
)
time
.
Sleep
(
pc
.
myState
.
PeerGossipSleep
())
return
true
}
}
return
false
}
else
if
vote
,
ok
:=
pc
.
state
.
PickVoteToSend
(
votes
);
ok
{
msg
:=
MsgInfo
{
TypeID
:
ttypes
.
VoteID
,
Msg
:
vote
.
Vote
,
PeerID
:
pc
.
id
,
PeerIP
:
pc
.
ip
.
String
()}
tendermintlog
.
Debug
(
"Sending vote message"
,
"
vote
"
,
msg
)
tendermintlog
.
Debug
(
"Sending vote message"
,
"
msg
"
,
msg
)
if
pc
.
Send
(
msg
)
{
pc
.
state
.
SetHasVote
(
vote
)
return
true
...
...
@@ -406,7 +420,6 @@ func (pc *peerConn) Start() error {
pc
.
pongChannel
=
make
(
chan
struct
{})
pc
.
sendQueue
=
make
(
chan
MsgInfo
,
maxSendQueueSize
)
pc
.
sendBuffer
=
make
([]
byte
,
0
,
MaxMsgPacketPayloadSize
)
pc
.
quitSend
=
make
(
chan
struct
{})
pc
.
quitUpdate
=
make
(
chan
struct
{})
pc
.
quitBeat
=
make
(
chan
struct
{})
pc
.
state
=
&
PeerConnState
{
ip
:
pc
.
ip
,
PeerRoundState
:
ttypes
.
PeerRoundState
{
...
...
@@ -417,7 +430,6 @@ func (pc *peerConn) Start() error {
}}
pc
.
updateStateQueue
=
make
(
chan
MsgInfo
,
maxSendQueueSize
)
pc
.
heartbeatQueue
=
make
(
chan
proto
.
Message
,
100
)
pc
.
waitQuit
.
Add
(
5
)
//heartbeatRoutine, updateStateRoutine,gossipDataRoutine,gossipVotesRoutine,queryMaj23Routine
go
pc
.
sendRoutine
()
go
pc
.
recvRoutine
()
...
...
@@ -434,27 +446,8 @@ func (pc *peerConn) Start() error {
func
(
pc
*
peerConn
)
Stop
()
{
if
atomic
.
CompareAndSwapUint32
(
&
pc
.
stopped
,
0
,
1
)
{
pc
.
quitSend
<-
struct
{}{}
pc
.
quitUpdate
<-
struct
{}{}
pc
.
quitBeat
<-
struct
{}{}
pc
.
waitQuit
.
Wait
()
tendermintlog
.
Info
(
"peerConn stop waitQuit"
,
"peerIP"
,
pc
.
ip
.
String
())
close
(
pc
.
sendQueue
)
pc
.
sendQueue
=
nil
pc
.
transferChannel
=
nil
pc
.
CloseConn
()
tendermintlog
.
Info
(
"peerConn stop finish"
,
"peerIP"
,
pc
.
ip
.
String
())
}
}
// Catch panics, usually caused by remote disconnects.
func
(
pc
*
peerConn
)
_recover
()
{
if
r
:=
recover
();
r
!=
nil
{
stack
:=
debug
.
Stack
()
err
:=
StackError
{
r
,
stack
}
pc
.
stopForError
(
err
)
tendermintlog
.
Info
(
"peerConn close connection"
,
"peerIP"
,
pc
.
ip
.
String
())
}
}
...
...
@@ -468,12 +461,9 @@ func (pc *peerConn) stopForError(r interface{}) {
}
func
(
pc
*
peerConn
)
sendRoutine
()
{
defer
pc
.
_recover
()
FOR_LOOP
:
for
{
select
{
case
<-
pc
.
quitSend
:
break
FOR_LOOP
case
msg
:=
<-
pc
.
sendQueue
:
bytes
,
err
:=
proto
.
Marshal
(
msg
.
Msg
)
if
err
!=
nil
{
...
...
@@ -525,7 +515,6 @@ FOR_LOOP:
}
func
(
pc
*
peerConn
)
recvRoutine
()
{
defer
pc
.
_recover
()
FOR_LOOP
:
for
{
//typeID+msgLen+msg
...
...
@@ -563,7 +552,7 @@ FOR_LOOP:
continue
}
if
pc
.
transferChannel
!=
nil
&&
(
pkt
.
TypeID
==
ttypes
.
ProposalID
||
pkt
.
TypeID
==
ttypes
.
VoteID
||
pkt
.
TypeID
==
ttypes
.
ProposalBlockID
)
{
pkt
.
TypeID
==
ttypes
.
ProposalBlockID
||
pkt
.
TypeID
==
ttypes
.
AggVoteID
)
{
pc
.
transferChannel
<-
MsgInfo
{
pkt
.
TypeID
,
realMsg
.
(
proto
.
Message
),
pc
.
ID
(),
pc
.
ip
.
String
()}
if
pkt
.
TypeID
==
ttypes
.
ProposalID
{
proposal
:=
realMsg
.
(
*
tmtypes
.
Proposal
)
...
...
@@ -577,6 +566,9 @@ FOR_LOOP:
block
:=
&
ttypes
.
TendermintBlock
{
TendermintBlock
:
realMsg
.
(
*
tmtypes
.
TendermintBlock
)}
tendermintlog
.
Debug
(
"Receiving proposal block"
,
"block-height"
,
block
.
Header
.
Height
,
"peerip"
,
pc
.
ip
.
String
())
pc
.
state
.
SetHasProposalBlock
(
block
)
}
else
if
pkt
.
TypeID
==
ttypes
.
AggVoteID
{
aggVote
:=
&
ttypes
.
AggVote
{
AggVote
:
realMsg
.
(
*
tmtypes
.
AggVote
)}
tendermintlog
.
Debug
(
"Receiving aggregate vote"
,
"aggVote-height"
,
aggVote
.
Height
,
"peerip"
,
pc
.
ip
.
String
())
}
}
else
if
pkt
.
TypeID
==
ttypes
.
ProposalHeartbeatID
{
pc
.
heartbeatQueue
<-
realMsg
.
(
*
tmtypes
.
Heartbeat
)
...
...
@@ -591,10 +583,8 @@ FOR_LOOP:
}
}
}
close
(
pc
.
pongChannel
)
close
(
pc
.
heartbeatQueue
)
close
(
pc
.
updateStateQueue
)
pc
.
quitUpdate
<-
struct
{}{}
pc
.
quitBeat
<-
struct
{}{}
tendermintlog
.
Info
(
"peerConn stop recvRoutine"
,
"peerIP"
,
pc
.
ip
.
String
())
}
...
...
@@ -603,7 +593,6 @@ FOR_LOOP:
for
{
select
{
case
<-
pc
.
quitUpdate
:
pc
.
waitQuit
.
Done
()
break
FOR_LOOP
case
msg
:=
<-
pc
.
updateStateQueue
:
typeID
:=
msg
.
TypeID
...
...
@@ -662,6 +651,7 @@ FOR_LOOP:
}
}
}
close
(
pc
.
updateStateQueue
)
tendermintlog
.
Info
(
"peerConn stop updateStateRoutine"
,
"peerIP"
,
pc
.
ip
.
String
())
}
...
...
@@ -670,15 +660,17 @@ FOR_LOOP:
for
{
select
{
case
<-
pc
.
quitBeat
:
pc
.
waitQuit
.
Done
()
break
FOR_LOOP
case
heartbeat
:=
<-
pc
.
heartbeatQueue
:
msg
:=
heartbeat
.
(
*
tmtypes
.
Heartbeat
)
tendermintlog
.
Debug
(
"Received proposal heartbeat message"
,
"height"
,
msg
.
Height
,
"round"
,
msg
.
Round
,
"sequence"
,
msg
.
Sequence
,
"valIdx"
,
msg
.
ValidatorIndex
,
"valAddr"
,
msg
.
ValidatorAddress
)
msg
,
ok
:=
heartbeat
.
(
*
tmtypes
.
Heartbeat
)
if
ok
{
tendermintlog
.
Debug
(
"Received proposal heartbeat message"
,
"height"
,
msg
.
Height
,
"round"
,
msg
.
Round
,
"sequence"
,
msg
.
Sequence
,
"valIdx"
,
msg
.
ValidatorIndex
,
"valAddr"
,
msg
.
ValidatorAddress
)
}
}
}
close
(
pc
.
heartbeatQueue
)
tendermintlog
.
Info
(
"peerConn stop heartbeatRoutine"
,
"peerIP"
,
pc
.
ip
.
String
())
}
...
...
@@ -687,7 +679,6 @@ OUTER_LOOP:
for
{
// Manage disconnects from self or peer.
if
!
pc
.
IsRunning
()
{
pc
.
waitQuit
.
Done
()
tendermintlog
.
Info
(
"peerConn stop gossipDataRoutine"
,
"peerIP"
,
pc
.
ip
.
String
())
return
}
...
...
@@ -789,7 +780,6 @@ OUTER_LOOP:
for
{
// Manage disconnects from self or peer.
if
!
pc
.
IsRunning
()
{
pc
.
waitQuit
.
Done
()
tendermintlog
.
Info
(
"peerConn stop gossipVotesRoutine"
,
"peerIP"
,
pc
.
ip
.
String
())
return
}
...
...
@@ -806,7 +796,7 @@ OUTER_LOOP:
// If height matches, then send LastCommit, Prevotes, Precommits.
if
rs
.
Height
==
prs
.
Height
{
if
pc
.
gossipVotesForHeight
(
rs
,
&
prs
.
PeerRoundState
)
{
if
!
useAggSig
&&
pc
.
gossipVotesForHeight
(
rs
,
&
prs
.
PeerRoundState
)
{
continue
OUTER_LOOP
}
}
...
...
@@ -914,7 +904,6 @@ OUTER_LOOP:
for
{
// Manage disconnects from self or peer.
if
!
pc
.
IsRunning
()
{
pc
.
waitQuit
.
Done
()
tendermintlog
.
Info
(
"peerConn stop queryMaj23Routine"
,
"peerIP"
,
pc
.
ip
.
String
())
return
}
...
...
@@ -1003,20 +992,6 @@ OUTER_LOOP:
}
}
// StackError struct
type
StackError
struct
{
Err
interface
{}
Stack
[]
byte
}
func
(
se
StackError
)
String
()
string
{
return
fmt
.
Sprintf
(
"Error: %v
\n
Stack: %s"
,
se
.
Err
,
se
.
Stack
)
}
func
(
se
StackError
)
Error
()
string
{
return
se
.
String
()
}
// GetRoundState returns an atomic snapshot of the PeerRoundState.
// There's no point in mutating it since it won't change PeerState.
func
(
ps
*
PeerConnState
)
GetRoundState
()
*
ttypes
.
PeerRoundState
{
...
...
@@ -1073,6 +1048,23 @@ func (ps *PeerConnState) SetHasProposalBlock(block *ttypes.TendermintBlock) {
ps
.
ProposalBlock
=
true
}
// SetHasAggPrecommit sets the given aggregate precommit as known for the peer.
func
(
ps
*
PeerConnState
)
SetHasAggPrecommit
(
aggVote
*
ttypes
.
AggVote
)
{
ps
.
mtx
.
Lock
()
defer
ps
.
mtx
.
Unlock
()
if
ps
.
Height
!=
aggVote
.
Height
||
ps
.
Round
!=
int
(
aggVote
.
Round
)
{
return
}
if
ps
.
AggPrecommit
{
return
}
tendermintlog
.
Debug
(
"Peer set aggregate precommit"
,
"peerip"
,
ps
.
ip
.
String
(),
"peer-state"
,
fmt
.
Sprintf
(
"%v/%v/%v"
,
ps
.
Height
,
ps
.
Round
,
ps
.
Step
),
"aggVote(H/R)"
,
fmt
.
Sprintf
(
"%v/%v"
,
aggVote
.
Height
,
aggVote
.
Round
))
ps
.
AggPrecommit
=
true
}
// PickVoteToSend picks a vote to send to the peer.
// Returns true if a vote was picked.
// NOTE: `votes` must be the correct Size() for the Height().
...
...
@@ -1266,6 +1258,7 @@ func (ps *PeerConnState) ApplyNewRoundStepMessage(msg *tmtypes.NewRoundStepMsg)
// We'll update the BitArray capacity later.
ps
.
Prevotes
=
nil
ps
.
Precommits
=
nil
ps
.
AggPrecommit
=
false
}
if
psHeight
==
msg
.
Height
&&
psRound
!=
int
(
msg
.
Round
)
&&
int
(
msg
.
Round
)
==
psCatchupCommitRound
{
// Peer caught up to CatchupCommitRound.
...
...
plugin/consensus/tendermint/secret_connection.go
View file @
b23f5c28
...
...
@@ -16,12 +16,13 @@ import (
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
"io"
"net"
"time"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/plugin/plugin/consensus/tendermint/types"
ttypes
"github.com/33cn/plugin/plugin/consensus/tendermint/types"
"golang.org/x/crypto/nacl/box"
"golang.org/x/crypto/nacl/secretbox"
"golang.org/x/crypto/ripemd160"
...
...
@@ -33,7 +34,6 @@ const (
dataMaxSize
=
1024
totalFrameSize
=
dataMaxSize
+
dataLenSize
sealedFrameSize
=
totalFrameSize
+
secretbox
.
Overhead
authSigMsgSize
=
(
32
)
+
(
64
)
)
// fixed size (length prefixed) byte arrays
// SecretConnection Implements net.Conn
...
...
@@ -62,7 +62,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
// (see DJB's Curve25519 paper: http://cr.yp.to/ecdh/curve25519-20060209.pdf)
remEphPub
,
err
:=
shareEphPubKey
(
conn
,
locEphPub
)
if
err
!=
nil
{
return
nil
,
err
return
nil
,
fmt
.
Errorf
(
"shareEphPubKey: %v"
,
err
)
}
// Compute common shared secret.
...
...
@@ -96,7 +96,7 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*
// Share (in secret) each other's pubkey & challenge signature
authSigMsg
,
err
:=
shareAuthSignature
(
sc
,
locPubKey
,
locSignature
)
if
err
!=
nil
{
return
nil
,
err
return
nil
,
fmt
.
Errorf
(
"shareAuthSignature: %v"
,
err
)
}
remPubKey
,
remSignature
:=
authSigMsg
.
Key
,
authSigMsg
.
Sig
if
!
remPubKey
.
VerifyBytes
(
challenge
[
:
],
remSignature
)
{
...
...
@@ -205,7 +205,7 @@ func genEphKeys() (ephPub, ephPriv *[32]byte) {
var
err
error
ephPub
,
ephPriv
,
err
=
box
.
GenerateKey
(
crand
.
Reader
)
if
err
!=
nil
{
types
.
PanicCrisis
(
"Could not generate ephemeral keypairs"
)
t
t
ypes
.
PanicCrisis
(
"Could not generate ephemeral keypairs"
)
}
return
}
...
...
@@ -282,26 +282,28 @@ type authSigMessage struct {
func
shareAuthSignature
(
sc
io
.
ReadWriter
,
pubKey
crypto
.
PubKey
,
signature
crypto
.
Signature
)
(
*
authSigMessage
,
error
)
{
var
recvMsg
authSigMessage
var
err1
,
err2
error
pubLen
:=
len
(
pubKey
.
Bytes
())
sigLen
:=
len
(
signature
.
Bytes
())
Parallel
(
func
()
{
msgByte
:=
make
([]
byte
,
len
(
pubKey
.
Bytes
())
+
len
(
signature
.
Bytes
())
)
copy
(
msgByte
,
pubKey
.
Bytes
())
copy
(
msgByte
[
len
(
pubKey
.
Bytes
())
:
],
signature
.
Bytes
())
msgByte
:=
make
([]
byte
,
pubLen
+
sigLen
)
copy
(
msgByte
,
pubKey
.
Bytes
()
[
:
pubLen
]
)
copy
(
msgByte
[
pubLen
:
],
signature
.
Bytes
())
_
,
err1
=
sc
.
Write
(
msgByte
)
},
func
()
{
readBuffer
:=
make
([]
byte
,
authSigMsgSize
)
readBuffer
:=
make
([]
byte
,
pubLen
+
sigLen
)
_
,
err2
=
io
.
ReadFull
(
sc
,
readBuffer
)
if
err2
!=
nil
{
return
}
recvMsg
.
Key
,
err2
=
t
ypes
.
ConsensusCrypto
.
PubKeyFromBytes
(
readBuffer
[
:
32
])
recvMsg
.
Key
,
err2
=
t
types
.
ConsensusCrypto
.
PubKeyFromBytes
(
readBuffer
[
:
pubLen
])
if
err2
!=
nil
{
return
}
recvMsg
.
Sig
,
err2
=
t
ypes
.
ConsensusCrypto
.
SignatureFromBytes
(
readBuffer
[
32
:
])
recvMsg
.
Sig
,
err2
=
t
types
.
ConsensusCrypto
.
SignatureFromBytes
(
readBuffer
[
pubLen
:
])
if
err2
!=
nil
{
return
}
...
...
plugin/consensus/tendermint/state.go
View file @
b23f5c28
...
...
@@ -385,7 +385,7 @@ func getprivkey(key string) crypto.PrivKey {
if
err
!=
nil
{
panic
(
err
)
}
priv
,
err
:=
cr
.
PrivKeyFromBytes
(
bkey
)
priv
,
err
:=
cr
.
PrivKeyFromBytes
(
bkey
[
:
32
]
)
if
err
!=
nil
{
panic
(
err
)
}
...
...
plugin/consensus/tendermint/store.go
View file @
b23f5c28
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
tendermint
import
(
...
...
plugin/consensus/tendermint/tendermint.go
View file @
b23f5c28
...
...
@@ -24,11 +24,14 @@ import (
"github.com/golang/protobuf/proto"
)
const
tendermintVersion
=
"0.1.0"
const
(
tendermintVersion
=
"0.1.0"
)
var
(
tendermintlog
=
log15
.
New
(
"module"
,
"tendermint"
)
genesis
string
genesisAmount
int64
=
1e8
genesisBlockTime
int64
timeoutTxAvail
int32
=
1000
timeoutPropose
int32
=
3000
// millisecond
...
...
@@ -41,12 +44,15 @@ var (
skipTimeoutCommit
=
false
createEmptyBlocks
=
false
fastSync
=
false
preExec
=
false
createEmptyBlocksInterval
int32
// second
validatorNodes
=
[]
string
{
"127.0.0.1:46656"
}
peerGossipSleepDuration
int32
=
1
00
peerGossipSleepDuration
int32
=
2
00
peerQueryMaj23SleepDuration
int32
=
2000
zeroHash
[
32
]
byte
random
*
rand
.
Rand
signName
=
"ed25519"
useAggSig
=
false
)
func
init
()
{
...
...
@@ -65,7 +71,6 @@ type Client struct {
pubKey
string
csState
*
ConsensusState
csStore
*
ConsensusStore
// save consensus state
crypto
crypto
.
Crypto
node
*
Node
txsAvailable
chan
int64
stopC
chan
struct
{}
...
...
@@ -73,6 +78,7 @@ type Client struct {
type
subConfig
struct
{
Genesis
string
`json:"genesis"`
GenesisAmount
int64
`json:"genesisAmount"`
GenesisBlockTime
int64
`json:"genesisBlockTime"`
TimeoutTxAvail
int32
`json:"timeoutTxAvail"`
TimeoutPropose
int32
`json:"timeoutPropose"`
...
...
@@ -87,9 +93,12 @@ type subConfig struct {
CreateEmptyBlocksInterval
int32
`json:"createEmptyBlocksInterval"`
ValidatorNodes
[]
string
`json:"validatorNodes"`
FastSync
bool
`json:"fastSync"`
PreExec
bool
`json:"preExec"`
SignName
string
`json:"signName"`
UseAggregateSignature
bool
`json:"useAggregateSignature"`
}
func
(
client
*
Client
)
applyConfig
(
sub
[]
byte
)
{
func
applyConfig
(
sub
[]
byte
)
{
var
subcfg
subConfig
if
sub
!=
nil
{
types
.
MustDecode
(
sub
,
&
subcfg
)
...
...
@@ -97,6 +106,9 @@ func (client *Client) applyConfig(sub []byte) {
if
subcfg
.
Genesis
!=
""
{
genesis
=
subcfg
.
Genesis
}
if
subcfg
.
GenesisAmount
>
0
{
genesisAmount
=
subcfg
.
GenesisAmount
}
if
subcfg
.
GenesisBlockTime
>
0
{
genesisBlockTime
=
subcfg
.
GenesisBlockTime
}
...
...
@@ -133,6 +145,11 @@ func (client *Client) applyConfig(sub []byte) {
validatorNodes
=
subcfg
.
ValidatorNodes
}
fastSync
=
subcfg
.
FastSync
preExec
=
subcfg
.
PreExec
if
subcfg
.
SignName
!=
""
{
signName
=
subcfg
.
SignName
}
useAggSig
=
subcfg
.
UseAggregateSignature
}
// DefaultDBProvider returns a database using the DBBackend and DBDir
...
...
@@ -144,37 +161,47 @@ func DefaultDBProvider(name string) dbm.DB {
// New ...
func
New
(
cfg
*
types
.
Consensus
,
sub
[]
byte
)
queue
.
Module
{
tendermintlog
.
Info
(
"Start to create tendermint client"
)
applyConfig
(
sub
)
//init rand
ttypes
.
Init
()
genDoc
,
err
:=
ttypes
.
GenesisDocFromFile
(
"genesis.json"
)
if
err
!=
nil
{
tendermintlog
.
Error
(
"
NewTendermintClient"
,
"msg"
,
"GenesisDocFromFile failded"
,
"error"
,
err
)
signType
,
ok
:=
ttypes
.
SignMap
[
signName
]
if
!
ok
{
tendermintlog
.
Error
(
"
Invalid sign name"
)
return
nil
}
cr
,
err
:=
crypto
.
New
(
types
.
GetSignName
(
""
,
types
.
ED25519
))
ttypes
.
CryptoName
=
types
.
GetSignName
(
""
,
signType
)
cr
,
err
:=
crypto
.
New
(
ttypes
.
CryptoName
)
if
err
!=
nil
{
tendermintlog
.
Error
(
"NewTendermintClient"
,
"err"
,
err
)
return
nil
}
ttypes
.
ConsensusCrypto
=
cr
priv
,
err
:=
cr
.
GenKey
()
if
useAggSig
{
_
,
err
=
crypto
.
ToAggregate
(
ttypes
.
ConsensusCrypto
)
if
err
!=
nil
{
tendermintlog
.
Error
(
"ConsensusCrypto not support aggregate signature"
,
"name"
,
ttypes
.
CryptoName
)
return
nil
}
}
genDoc
,
err
:=
ttypes
.
GenesisDocFromFile
(
"genesis.json"
)
if
err
!=
nil
{
tendermintlog
.
Error
(
"NewTendermintClient"
,
"
GenKey er
r"
,
err
)
tendermintlog
.
Error
(
"NewTendermintClient"
,
"
msg"
,
"GenesisDocFromFile fail"
,
"erro
r"
,
err
)
return
nil
}
privValidator
:=
ttypes
.
LoadOrGenPrivValidatorFS
(
"priv_validator.json"
)
if
privValidator
==
nil
{
tendermintlog
.
Error
(
"NewTendermintClient create priv_validator file fail
ed
"
)
tendermintlog
.
Error
(
"NewTendermintClient create priv_validator file fail"
)
return
nil
}
ttypes
.
InitMessageMap
()
priv
:=
privValidator
.
PrivKey
pubkey
:=
privValidator
.
GetPubKey
()
.
KeyString
()
c
:=
drivers
.
NewBaseClient
(
cfg
)
client
:=
&
Client
{
...
...
@@ -184,21 +211,13 @@ func New(cfg *types.Consensus, sub []byte) queue.Module {
privKey
:
priv
,
pubKey
:
pubkey
,
csStore
:
NewConsensusStore
(),
crypto
:
cr
,
txsAvailable
:
make
(
chan
int64
,
1
),
stopC
:
make
(
chan
struct
{},
1
),
}
c
.
SetChild
(
client
)
client
.
applyConfig
(
sub
)
return
client
}
// PrivValidator returns the Node's PrivValidator.
func
(
client
*
Client
)
PrivValidator
()
ttypes
.
PrivValidator
{
return
client
.
privValidator
}
// GenesisDoc returns the Node's GenesisDoc.
func
(
client
*
Client
)
GenesisDoc
()
*
ttypes
.
GenesisDoc
{
return
client
.
genesisDoc
...
...
@@ -216,6 +235,7 @@ func (client *Client) GenesisState() *State {
// Close TODO:may need optimize
func
(
client
*
Client
)
Close
()
{
client
.
BaseClient
.
Close
()
client
.
node
.
Stop
()
client
.
stopC
<-
struct
{}{}
tendermintlog
.
Info
(
"consensus tendermint closed"
)
...
...
@@ -335,7 +355,7 @@ func (client *Client) CreateGenesisTx() (ret []*types.Transaction) {
//gen payload
g
:=
&
cty
.
CoinsAction_Genesis
{}
g
.
Genesis
=
&
types
.
AssetsGenesis
{}
g
.
Genesis
.
Amount
=
1e8
*
types
.
Coin
g
.
Genesis
.
Amount
=
genesisAmount
*
types
.
Coin
tx
.
Payload
=
types
.
Encode
(
&
cty
.
CoinsAction
{
Value
:
g
,
Ty
:
cty
.
CoinsActionGenesis
})
ret
=
append
(
ret
,
&
tx
)
return
...
...
@@ -405,10 +425,13 @@ func (client *Client) ProcEvent(msg *queue.Message) bool {
// CreateBlock a routine monitor whether some transactions available and tell client by available channel
func
(
client
*
Client
)
CreateBlock
()
{
issleep
:=
true
for
{
if
client
.
IsClosed
()
{
tendermintlog
.
Info
(
"CreateBlock quit"
)
break
}
if
!
client
.
csState
.
IsRunning
()
{
tendermintlog
.
Error
(
"consensus not running now
"
)
tendermintlog
.
Info
(
"consensus not running
"
)
time
.
Sleep
(
time
.
Second
)
continue
}
...
...
@@ -483,7 +506,6 @@ func (client *Client) BuildBlock() *types.Block {
client
.
AddTxsToBlock
(
&
newblock
,
txs
)
//固定难度
newblock
.
Difficulty
=
cfg
.
GetP
(
0
)
.
PowLimitBits
//newblock.TxHash = merkle.CalcMerkleRoot(newblock.Txs)
newblock
.
BlockTime
=
types
.
Now
()
.
Unix
()
if
lastBlock
.
BlockTime
>=
newblock
.
BlockTime
{
newblock
.
BlockTime
=
lastBlock
.
BlockTime
+
1
...
...
@@ -498,6 +520,9 @@ func (client *Client) CommitBlock(block *types.Block) error {
if
retErr
!=
nil
{
tendermintlog
.
Info
(
"CommitBlock fail"
,
"err"
,
retErr
)
if
client
.
WaitBlock
(
block
.
Height
)
{
if
!
preExec
{
return
nil
}
curBlock
,
err
:=
client
.
RequestBlock
(
block
.
Height
)
if
err
==
nil
{
if
bytes
.
Equal
(
curBlock
.
Hash
(
cfg
),
block
.
Hash
(
cfg
))
{
...
...
@@ -636,7 +661,7 @@ func (client *Client) Query_NodeInfo(req *types.ReqNil) (types.Message, error) {
return
&
tmtypes
.
ValidatorSet
{
Validators
:
validators
,
Proposer
:
&
tmtypes
.
Validator
{}},
nil
}
//比较newBlock是不是最优区块
//
CmpBestBlock
比较newBlock是不是最优区块
func
(
client
*
Client
)
CmpBestBlock
(
newBlock
*
types
.
Block
,
cmpBlock
*
types
.
Block
)
bool
{
return
false
}
plugin/consensus/tendermint/tendermint_test.go
View file @
b23f5c28
...
...
@@ -272,13 +272,12 @@ func CheckState(t *testing.T, client *Client) {
assert
.
Equal
(
t
,
client
.
csState
.
Prevote
(
0
),
1000
*
time
.
Millisecond
)
assert
.
Equal
(
t
,
client
.
csState
.
Precommit
(
0
),
1000
*
time
.
Millisecond
)
assert
.
Equal
(
t
,
client
.
csState
.
PeerGossipSleep
(),
1
00
*
time
.
Millisecond
)
assert
.
Equal
(
t
,
client
.
csState
.
PeerGossipSleep
(),
2
00
*
time
.
Millisecond
)
assert
.
Equal
(
t
,
client
.
csState
.
PeerQueryMaj23Sleep
(),
2000
*
time
.
Millisecond
)
assert
.
Equal
(
t
,
client
.
csState
.
IsProposer
(),
true
)
assert
.
Nil
(
t
,
client
.
csState
.
GetPrevotesState
(
state
.
LastBlockHeight
,
0
,
nil
))
assert
.
Nil
(
t
,
client
.
csState
.
GetPrecommitsState
(
state
.
LastBlockHeight
,
0
,
nil
))
assert
.
NotEmpty
(
t
,
client
.
PrivValidator
())
assert
.
NotEmpty
(
t
,
client
.
csState
.
GetPrivValidator
())
assert
.
Len
(
t
,
client
.
GenesisDoc
()
.
Validators
,
1
)
msg1
,
err
:=
client
.
Query_IsHealthy
(
&
types
.
ReqNil
{})
...
...
plugin/consensus/tendermint/tools/nonePerf.go
View file @
b23f5c28
...
...
@@ -139,7 +139,7 @@ func Put(ip string, size string, privkey string) {
fmt
.
Fprintln
(
os
.
Stderr
,
err
)
return
}
url
:=
"http://"
+
ip
+
":
9
801"
url
:=
"http://"
+
ip
+
":
8
801"
if
privkey
==
""
{
_
,
priv
:=
genaddress
()
privkey
=
common
.
ToHex
(
priv
.
Bytes
())
...
...
plugin/consensus/tendermint/types/block.go
View file @
b23f5c28
...
...
@@ -13,18 +13,11 @@ import (
"time"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/common/merkle"
"github.com/33cn/chain33/types"
tmtypes
"github.com/33cn/plugin/plugin/dapp/valnode/types"
)
var
(
blocklog
=
log15
.
New
(
"module"
,
"tendermint-block"
)
// ConsensusCrypto define
ConsensusCrypto
crypto
.
Crypto
)
// BlockID struct
type
BlockID
struct
{
tmtypes
.
BlockID
...
...
@@ -88,11 +81,6 @@ func (b *TendermintBlock) ValidateBasic() error {
return
errors
.
New
(
"Zero Header.Height"
)
}
newTxs
:=
int64
(
len
(
b
.
Data
.
Txs
))
if
b
.
Header
.
NumTxs
!=
newTxs
{
return
fmt
.
Errorf
(
"Wrong Header.NumTxs. Expected %v, got %v"
,
newTxs
,
b
.
Header
.
NumTxs
)
}
if
b
.
Header
.
TotalTxs
<
0
{
return
errors
.
New
(
"Negative Header.TotalTxs"
)
}
...
...
@@ -192,7 +180,7 @@ func (h *Header) Hash() []byte {
}
bytes
,
err
:=
json
.
Marshal
(
h
)
if
err
!=
nil
{
block
log
.
Error
(
"block header Hash() marshal failed"
,
"error"
,
err
)
tt
log
.
Error
(
"block header Hash() marshal failed"
,
"error"
,
err
)
return
nil
}
return
crypto
.
Ripemd160
(
bytes
)
...
...
@@ -254,6 +242,9 @@ func (commit *Commit) FirstPrecommit() *tmtypes.Vote {
// Height returns the height of the commit
func
(
commit
*
Commit
)
Height
()
int64
{
if
commit
.
AggVote
!=
nil
{
return
commit
.
AggVote
.
Height
}
if
len
(
commit
.
Precommits
)
==
0
{
return
0
}
...
...
@@ -262,6 +253,9 @@ func (commit *Commit) Height() int64 {
// Round returns the round of the commit
func
(
commit
*
Commit
)
Round
()
int
{
if
commit
.
AggVote
!=
nil
{
return
int
(
commit
.
AggVote
.
Round
)
}
if
len
(
commit
.
Precommits
)
==
0
{
return
0
}
...
...
@@ -283,6 +277,10 @@ func (commit *Commit) Size() int {
// BitArray returns a BitArray of which validators voted in this commit
func
(
commit
*
Commit
)
BitArray
()
*
BitArray
{
if
commit
.
AggVote
!=
nil
{
bitArray
:=
&
BitArray
{
TendermintBitArray
:
commit
.
AggVote
.
ValidatorArray
}
return
bitArray
.
copy
()
}
if
commit
.
bitArray
==
nil
{
commit
.
bitArray
=
NewBitArray
(
len
(
commit
.
Precommits
))
for
i
,
precommit
:=
range
commit
.
Precommits
{
...
...
@@ -301,7 +299,16 @@ func (commit *Commit) GetByIndex(index int) *Vote {
// IsCommit returns true if there is at least one vote
func
(
commit
*
Commit
)
IsCommit
()
bool
{
return
len
(
commit
.
Precommits
)
!=
0
return
len
(
commit
.
Precommits
)
!=
0
||
commit
.
AggVote
!=
nil
}
// GetAggVote ...
func
(
commit
*
Commit
)
GetAggVote
()
*
AggVote
{
if
commit
==
nil
{
return
nil
}
aggVote
:=
&
AggVote
{
commit
.
AggVote
}
return
aggVote
.
Copy
()
}
// ValidateBasic performs basic validation that doesn't involve state data.
...
...
@@ -338,18 +345,35 @@ func (commit *Commit) ValidateBasic() error {
round
,
precommit
.
Round
)
}
}
// validate the aggVote
if
commit
.
AggVote
!=
nil
{
if
commit
.
AggVote
.
Type
!=
uint32
(
VoteTypePrecommit
)
{
return
fmt
.
Errorf
(
"Invalid aggVote type. Expected Precommit, got %v"
,
commit
.
AggVote
.
Type
)
}
if
commit
.
AggVote
.
Height
!=
height
{
return
fmt
.
Errorf
(
"Invalid aggVote height. Expected %v, got %v"
,
height
,
commit
.
AggVote
.
Height
)
}
if
int
(
commit
.
AggVote
.
Round
)
!=
round
{
return
fmt
.
Errorf
(
"Invalid aggVote round. Expected %v, got %v"
,
round
,
commit
.
AggVote
.
Round
)
}
}
return
nil
}
// Hash returns the hash of the commit
func
(
commit
*
Commit
)
Hash
()
[]
byte
{
if
commit
.
hash
==
nil
{
bs
:=
make
([][]
byte
,
len
(
commit
.
Precommits
))
for
i
,
item
:=
range
commit
.
Precommits
{
precommit
:=
Vote
{
Vote
:
item
}
bs
[
i
]
=
precommit
.
Hash
()
if
commit
.
AggVote
!=
nil
{
aggVote
:=
&
AggVote
{
AggVote
:
commit
.
AggVote
}
commit
.
hash
=
aggVote
.
Hash
()
}
else
{
bs
:=
make
([][]
byte
,
len
(
commit
.
Precommits
))
for
i
,
item
:=
range
commit
.
Precommits
{
precommit
:=
Vote
{
Vote
:
item
}
bs
[
i
]
=
precommit
.
Hash
()
}
commit
.
hash
=
merkle
.
GetMerkleRoot
(
bs
)
}
commit
.
hash
=
merkle
.
GetMerkleRoot
(
bs
)
}
return
commit
.
hash
}
...
...
@@ -366,9 +390,11 @@ func (commit *Commit) StringIndented(indent string) string {
return
Fmt
(
`Commit{
%s BlockID: %v
%s Precommits: %v
%s AggVote: %v
%s}#%v`
,
indent
,
commit
.
BlockID
,
indent
,
strings
.
Join
(
precommitStrings
,
"
\n
"
+
indent
+
" "
),
indent
,
commit
.
AggVote
.
String
(),
indent
,
commit
.
hash
)
}
...
...
plugin/consensus/tendermint/types/
errors
.go
→
plugin/consensus/tendermint/types/
const
.go
View file @
b23f5c28
...
...
@@ -4,7 +4,17 @@
package
types
import
"errors"
import
(
"errors"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
)
const
(
AuthBLS
=
259
)
var
(
// ErrHeightLessThanOne error type
...
...
@@ -18,3 +28,17 @@ var (
// ErrLastBlockID error type
ErrLastBlockID
=
errors
.
New
(
"ErrLastBlockID"
)
)
var
(
ttlog
=
log15
.
New
(
"module"
,
"tendermint-types"
)
// ConsensusCrypto define
ConsensusCrypto
crypto
.
Crypto
CryptoName
string
// SignMap define sign type
SignMap
=
map
[
string
]
int
{
"secp256k1"
:
types
.
SECP256K1
,
"ed25519"
:
types
.
ED25519
,
"sm2"
:
types
.
SM2
,
"bls"
:
AuthBLS
,
}
)
plugin/consensus/tendermint/types/height_vote_set.go
View file @
b23f5c28
...
...
@@ -138,6 +138,30 @@ func (hvs *HeightVoteSet) AddVote(vote *Vote, peerID string) (added bool, err er
return
}
// AddAggVote Duplicate votes return added=false, err=nil.
// By convention, peerKey is "" if origin is self.
func
(
hvs
*
HeightVoteSet
)
AddAggVote
(
vote
*
AggVote
,
peerID
string
)
(
added
bool
,
err
error
)
{
hvs
.
mtx
.
Lock
()
defer
hvs
.
mtx
.
Unlock
()
if
!
IsVoteTypeValid
(
byte
(
vote
.
Type
))
{
return
}
round
:=
int
(
vote
.
Round
)
voteSet
:=
hvs
.
getVoteSet
(
round
,
byte
(
vote
.
Type
))
if
voteSet
==
nil
{
if
rndz
:=
hvs
.
peerCatchupRounds
[
peerID
];
len
(
rndz
)
<
2
{
hvs
.
addRound
(
int
(
vote
.
Round
))
voteSet
=
hvs
.
getVoteSet
(
round
,
byte
(
vote
.
Type
))
hvs
.
peerCatchupRounds
[
peerID
]
=
append
(
rndz
,
round
)
}
else
{
err
=
errors
.
New
(
"Peer has sent a aggregate vote that does not match our round for more than one round"
)
return
}
}
added
,
err
=
voteSet
.
AddAggVote
(
vote
)
return
}
// Prevotes ...
func
(
hvs
*
HeightVoteSet
)
Prevotes
(
round
int
)
*
VoteSet
{
hvs
.
mtx
.
Lock
()
...
...
plugin/consensus/tendermint/types/params.go
View file @
b23f5c28
...
...
@@ -113,7 +113,7 @@ func (params *ConsensusParams) Validate() error {
func
(
params
*
ConsensusParams
)
Hash
()
[]
byte
{
bytes
,
err
:=
json
.
Marshal
(
params
)
if
err
!=
nil
{
block
log
.
Error
(
"block header Hash() marshal failed"
,
"error"
,
err
)
tt
log
.
Error
(
"block header Hash() marshal failed"
,
"error"
,
err
)
return
nil
}
return
crypto
.
Ripemd160
(
bytes
)
...
...
plugin/consensus/tendermint/types/priv_validator.go
View file @
b23f5c28
...
...
@@ -6,6 +6,7 @@ package types
import
(
"bytes"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
...
...
@@ -14,8 +15,6 @@ import (
"sync"
"time"
"encoding/hex"
"github.com/33cn/chain33/common/crypto"
)
...
...
@@ -296,15 +295,15 @@ func (pv *PrivValidatorImp) save() {
LastStep
:
pv
.
LastStep
,
LastSignature
:
nil
,
}
privValFS
.
PrivKey
=
KeyText
{
Kind
:
"ed25519"
,
Data
:
Fmt
(
"%X"
,
pv
.
PrivKey
.
Bytes
()[
:
])}
privValFS
.
PubKey
=
KeyText
{
Kind
:
"ed25519"
,
Data
:
pv
.
PubKey
.
KeyString
()}
privValFS
.
PrivKey
=
KeyText
{
Kind
:
CryptoName
,
Data
:
Fmt
(
"%X"
,
pv
.
PrivKey
.
Bytes
()[
:
])}
privValFS
.
PubKey
=
KeyText
{
Kind
:
CryptoName
,
Data
:
pv
.
PubKey
.
KeyString
()}
if
len
(
pv
.
LastSignBytes
)
!=
0
{
tmp
:=
Fmt
(
"%X"
,
pv
.
LastSignBytes
[
:
])
privValFS
.
LastSignBytes
=
tmp
}
if
pv
.
LastSignature
!=
nil
{
sig
:=
Fmt
(
"%X"
,
pv
.
LastSignature
.
Bytes
()[
:
])
privValFS
.
LastSignature
=
&
KeyText
{
Kind
:
"ed25519"
,
Data
:
sig
}
privValFS
.
LastSignature
=
&
KeyText
{
Kind
:
CryptoName
,
Data
:
sig
}
}
jsonBytes
,
err
:=
json
.
Marshal
(
privValFS
)
if
err
!=
nil
{
...
...
plugin/consensus/tendermint/types/round_state.go
View file @
b23f5c28
...
...
@@ -42,6 +42,7 @@ const (
ProposalHeartbeatID
=
byte
(
0x08
)
ProposalBlockID
=
byte
(
0x09
)
ValidBlockID
=
byte
(
0x0a
)
AggVoteID
=
byte
(
0x0b
)
PacketTypePing
=
byte
(
0xff
)
PacketTypePong
=
byte
(
0xfe
)
...
...
@@ -60,6 +61,7 @@ func InitMessageMap() {
ProposalHeartbeatID
:
reflect
.
TypeOf
(
tmtypes
.
Heartbeat
{}),
ProposalBlockID
:
reflect
.
TypeOf
(
tmtypes
.
TendermintBlock
{}),
ValidBlockID
:
reflect
.
TypeOf
(
tmtypes
.
ValidBlockMsg
{}),
AggVoteID
:
reflect
.
TypeOf
(
tmtypes
.
AggVote
{}),
}
}
...
...
@@ -186,6 +188,7 @@ type PeerRoundState struct {
LastCommit
*
BitArray
// All commit precommits of commit for last height.
CatchupCommitRound
int
// Round that we have commit for. Not necessarily unique. -1 if none.
CatchupCommit
*
BitArray
// All commit precommits peer has for this height & CatchupCommitRound
AggPrecommit
bool
// True if peer has aggregate precommit for this round
}
// String returns a string representation of the PeerRoundState
...
...
@@ -204,17 +207,19 @@ func (prs PeerRoundState) StringIndented(indent string) string {
%s Prevotes %v
%s Precommits %v
%s LastCommit %v (round %v)
%s Catchup %v (round %v)
%s CatchupCommit %v (round %v)
%s AggPrecommit %v
%s}`
,
indent
,
prs
.
Height
,
prs
.
Round
,
prs
.
Step
,
prs
.
StartTime
,
indent
,
prs
.
Proposal
,
indent
,
prs
.
ProposalBlock
,
indent
,
prs
.
ProposalBlock
,
indent
,
prs
.
ProposalBlock
Hash
,
indent
,
prs
.
ProposalPOL
,
prs
.
ProposalPOLRound
,
indent
,
prs
.
Prevotes
,
indent
,
prs
.
Precommits
,
indent
,
prs
.
LastCommit
,
prs
.
LastCommitRound
,
indent
,
prs
.
CatchupCommit
,
prs
.
CatchupCommitRound
,
indent
,
prs
.
AggPrecommit
,
indent
)
}
...
...
@@ -274,6 +279,12 @@ type CanonicalJSONOnceVote struct {
Vote
CanonicalJSONVote
`json:"vote"`
}
// CanonicalJSONOnceAggVote ...
type
CanonicalJSONOnceAggVote
struct
{
ChainID
string
`json:"chain_id"`
AggVote
CanonicalJSONVote
`json:"agg_vote"`
}
// CanonicalJSONOnceHeartbeat ...
type
CanonicalJSONOnceHeartbeat
struct
{
ChainID
string
`json:"chain_id"`
...
...
@@ -305,11 +316,26 @@ func CanonicalProposal(proposal *Proposal) CanonicalJSONProposal {
// CanonicalVote ...
func
CanonicalVote
(
vote
*
Vote
)
CanonicalJSONVote
{
timestamp
:=
""
if
!
vote
.
UseAggSig
{
timestamp
=
CanonicalTime
(
time
.
Unix
(
0
,
vote
.
Timestamp
))
}
return
CanonicalJSONVote
{
BlockID
:
CanonicalJSONBlockID
{
Hash
:
vote
.
BlockID
.
Hash
},
Height
:
vote
.
Height
,
Round
:
int
(
vote
.
Round
),
Timestamp
:
timestamp
,
Type
:
byte
(
vote
.
Type
),
}
}
// CanonicalAggVote ...
func
CanonicalAggVote
(
vote
*
AggVote
)
CanonicalJSONVote
{
return
CanonicalJSONVote
{
BlockID
:
CanonicalJSONBlockID
{
Hash
:
vote
.
BlockID
.
Hash
},
Height
:
vote
.
Height
,
Round
:
int
(
vote
.
Round
),
Timestamp
:
CanonicalTime
(
time
.
Unix
(
0
,
vote
.
Timestamp
))
,
Timestamp
:
""
,
Type
:
byte
(
vote
.
Type
),
}
}
...
...
plugin/consensus/tendermint/types/signable.go
View file @
b23f5c28
...
...
@@ -13,7 +13,6 @@ import (
"time"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/log/log15"
tmtypes
"github.com/33cn/plugin/plugin/dapp/valnode/types"
)
...
...
@@ -27,7 +26,7 @@ var (
ErrVoteNonDeterministicSignature
=
errors
.
New
(
"Non-deterministic signature"
)
ErrVoteConflict
=
errors
.
New
(
"Conflicting vote"
)
ErrVoteNil
=
errors
.
New
(
"Nil vote"
)
votelog
=
log15
.
New
(
"module"
,
"tendermint-
vote"
)
ErrAggVoteNil
=
errors
.
New
(
"Nil aggregate
vote"
)
)
// Signable is an interface for all signable things.
...
...
@@ -156,7 +155,7 @@ func (vote *Vote) WriteSignBytes(chainID string, w io.Writer, n *int, err *error
byteVote
,
e
:=
json
.
Marshal
(
&
canonical
)
if
e
!=
nil
{
*
err
=
e
vote
log
.
Error
(
"vote WriteSignBytes marshal failed"
,
"err"
,
e
)
tt
log
.
Error
(
"vote WriteSignBytes marshal failed"
,
"err"
,
e
)
return
}
number
,
writeErr
:=
w
.
Write
(
byteVote
)
...
...
@@ -200,7 +199,7 @@ func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error {
sig
,
err
:=
ConsensusCrypto
.
SignatureFromBytes
(
vote
.
Signature
)
if
err
!=
nil
{
votelog
.
Error
(
"vote Verify failed
"
,
"err"
,
err
)
ttlog
.
Error
(
"vote Verify fail
"
,
"err"
,
err
)
return
err
}
...
...
@@ -217,7 +216,109 @@ func (vote *Vote) Hash() []byte {
}
bytes
,
err
:=
json
.
Marshal
(
vote
)
if
err
!=
nil
{
votelog
.
Error
(
"vote hash marshal failed"
,
"err"
,
err
)
ttlog
.
Error
(
"vote hash marshal failed"
,
"err"
,
err
)
return
nil
}
return
crypto
.
Ripemd160
(
bytes
)
}
// AggVote Represents a prevote, precommit, or commit vote from validators for consensus.
type
AggVote
struct
{
*
tmtypes
.
AggVote
}
// WriteSignBytes ...
func
(
aggVote
*
AggVote
)
WriteSignBytes
(
chainID
string
,
w
io
.
Writer
,
n
*
int
,
err
*
error
)
{
if
*
err
!=
nil
{
return
}
canonical
:=
CanonicalJSONOnceAggVote
{
chainID
,
CanonicalAggVote
(
aggVote
),
}
byteVote
,
e
:=
json
.
Marshal
(
&
canonical
)
if
e
!=
nil
{
*
err
=
e
ttlog
.
Error
(
"aggVote WriteSignBytes marshal failed"
,
"err"
,
e
)
return
}
number
,
writeErr
:=
w
.
Write
(
byteVote
)
*
n
=
number
*
err
=
writeErr
}
// Verify ...
func
(
aggVote
*
AggVote
)
Verify
(
chainID
string
,
valSet
*
ValidatorSet
)
error
{
aggSig
,
err
:=
ConsensusCrypto
.
SignatureFromBytes
(
aggVote
.
Signature
)
if
err
!=
nil
{
return
errors
.
New
(
"invalid aggregate signature"
)
}
pubs
:=
make
([]
crypto
.
PubKey
,
0
)
arr
:=
&
BitArray
{
TendermintBitArray
:
aggVote
.
ValidatorArray
}
for
i
,
val
:=
range
valSet
.
Validators
{
if
arr
.
GetIndex
(
i
)
{
pub
,
_
:=
ConsensusCrypto
.
PubKeyFromBytes
(
val
.
PubKey
)
pubs
=
append
(
pubs
,
pub
)
}
}
origVote
:=
&
Vote
{
&
tmtypes
.
Vote
{
BlockID
:
aggVote
.
BlockID
,
Height
:
aggVote
.
Height
,
Round
:
aggVote
.
Round
,
Timestamp
:
aggVote
.
Timestamp
,
Type
:
aggVote
.
Type
,
UseAggSig
:
true
,
}}
aggr
,
err
:=
crypto
.
ToAggregate
(
ConsensusCrypto
)
if
err
!=
nil
{
return
err
}
err
=
aggr
.
VerifyAggregatedOne
(
pubs
,
SignBytes
(
chainID
,
origVote
),
aggSig
)
if
err
!=
nil
{
ttlog
.
Error
(
"aggVote Verify fail"
,
"err"
,
err
,
"aggVote"
,
aggVote
,
"aggSig"
,
aggSig
)
return
err
}
return
nil
}
// Copy ...
func
(
aggVote
*
AggVote
)
Copy
()
*
AggVote
{
copy
:=
*
aggVote
return
&
copy
}
func
(
aggVote
*
AggVote
)
String
()
string
{
if
aggVote
==
nil
{
return
"nil-AggVote"
}
var
typeString
string
switch
byte
(
aggVote
.
Type
)
{
case
VoteTypePrevote
:
typeString
=
"Prevote"
case
VoteTypePrecommit
:
typeString
=
"Precommit"
default
:
PanicSanity
(
"Unknown vote type"
)
}
bitArray
:=
&
BitArray
{
TendermintBitArray
:
aggVote
.
ValidatorArray
}
return
fmt
.
Sprintf
(
"AggVote{%X %v/%02d/%v(%v) %X %X @ %s %v}"
,
Fingerprint
(
aggVote
.
ValidatorAddress
),
aggVote
.
Height
,
aggVote
.
Round
,
aggVote
.
Type
,
typeString
,
Fingerprint
(
aggVote
.
BlockID
.
Hash
),
aggVote
.
Signature
,
CanonicalTime
(
time
.
Unix
(
0
,
aggVote
.
Timestamp
)),
bitArray
)
}
// Hash ...
func
(
aggVote
*
AggVote
)
Hash
()
[]
byte
{
if
aggVote
==
nil
{
return
nil
}
bytes
,
err
:=
json
.
Marshal
(
aggVote
)
if
err
!=
nil
{
ttlog
.
Error
(
"aggVote hash marshal failed"
,
"err"
,
err
)
return
nil
}
...
...
plugin/consensus/tendermint/types/validator_set.go
View file @
b23f5c28
...
...
@@ -12,13 +12,10 @@ import (
"strings"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/common/merkle"
"github.com/pkg/errors"
)
var
validatorsetlog
=
log15
.
New
(
"module"
,
"tendermint-val"
)
// Validator ...
type
Validator
struct
{
Address
[]
byte
`json:"address"`
...
...
@@ -313,7 +310,7 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height
if
valSet
.
Size
()
!=
len
(
commit
.
Precommits
)
{
return
fmt
.
Errorf
(
"Invalid commit -- wrong set size: %v vs %v"
,
valSet
.
Size
(),
len
(
commit
.
Precommits
))
}
validatorse
tlog
.
Debug
(
"VerifyCommit will get commit height"
,
"height"
,
commit
.
Height
())
t
tlog
.
Debug
(
"VerifyCommit will get commit height"
,
"height"
,
commit
.
Height
())
commitHeight
:=
commit
.
Height
()
if
height
!=
commitHeight
{
return
fmt
.
Errorf
(
"VerifyCommit 1 Invalid commit -- wrong height: %v vs %v"
,
height
,
commitHeight
)
...
...
@@ -322,41 +319,65 @@ func (valSet *ValidatorSet) VerifyCommit(chainID string, blockID BlockID, height
talliedVotingPower
:=
int64
(
0
)
round
:=
commit
.
Round
()
for
idx
,
item
:=
range
commit
.
Precommits
{
// may be nil if validator skipped.
if
item
==
nil
||
len
(
item
.
Signature
)
==
0
{
continue
}
precommit
:=
&
Vote
{
Vote
:
item
}
if
precommit
.
Height
!=
height
{
return
fmt
.
Errorf
(
"VerifyCommit 2 Invalid commit -- wrong height: %v vs %v"
,
height
,
precommit
.
Height
)
}
if
int
(
precommit
.
Round
)
!=
round
{
return
fmt
.
Errorf
(
"Invalid commit -- wrong round: %v vs %v"
,
round
,
precommit
.
Round
)
}
if
precommit
.
Type
!=
uint32
(
VoteTypePrecommit
)
{
return
fmt
.
Errorf
(
"Invalid commit -- not precommit @ index %v"
,
idx
)
if
commit
.
AggVote
!=
nil
{
aggVote
:=
&
AggVote
{
AggVote
:
commit
.
AggVote
}
// Make sure the step matches
if
(
aggVote
.
Height
!=
height
)
||
(
int
(
aggVote
.
Round
)
!=
round
)
||
(
aggVote
.
Type
!=
uint32
(
VoteTypePrecommit
))
{
return
errors
.
Wrapf
(
ErrVoteUnexpectedStep
,
"Got %d/%d/%d, expected %d/%d/%d"
,
height
,
round
,
VoteTypePrecommit
,
aggVote
.
Height
,
aggVote
.
Round
,
aggVote
.
Type
)
}
_
,
val
:=
valSet
.
GetByIndex
(
idx
)
// Validate signature
precommitSignBytes
:=
SignBytes
(
chainID
,
precommit
)
sig
,
err
:=
ConsensusCrypto
.
SignatureFromBytes
(
precommit
.
Signature
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"VerifyCommit SignatureFromBytes [%X] failed:%v"
,
precommit
.
Signature
,
err
)
}
pubkey
,
err
:=
ConsensusCrypto
.
PubKeyFromBytes
(
val
.
PubKey
)
// Check signature
err
:=
aggVote
.
Verify
(
chainID
,
valSet
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"VerifyCommit PubKeyFromBytes [%X] failed:%v"
,
val
.
PubKey
,
err
)
return
err
}
if
!
pubkey
.
VerifyBytes
(
precommitSignBytes
,
sig
)
{
return
fmt
.
Errorf
(
"Invalid commit -- invalid signature: %v"
,
precommit
)
// calc voting power
arr
:=
&
BitArray
{
TendermintBitArray
:
aggVote
.
ValidatorArray
}
for
i
,
val
:=
range
valSet
.
Validators
{
if
arr
.
GetIndex
(
i
)
{
talliedVotingPower
+=
val
.
VotingPower
}
}
if
!
bytes
.
Equal
(
blockID
.
Hash
,
precommit
.
BlockID
.
Hash
)
{
continue
// Not an error, but doesn't count
}
else
{
for
idx
,
item
:=
range
commit
.
Precommits
{
// may be nil if validator skipped.
if
item
==
nil
||
len
(
item
.
Signature
)
==
0
{
continue
}
precommit
:=
&
Vote
{
Vote
:
item
}
if
precommit
.
Height
!=
height
{
return
fmt
.
Errorf
(
"VerifyCommit 2 Invalid commit -- wrong height: %v vs %v"
,
height
,
precommit
.
Height
)
}
if
int
(
precommit
.
Round
)
!=
round
{
return
fmt
.
Errorf
(
"Invalid commit -- wrong round: %v vs %v"
,
round
,
precommit
.
Round
)
}
if
precommit
.
Type
!=
uint32
(
VoteTypePrecommit
)
{
return
fmt
.
Errorf
(
"Invalid commit -- not precommit @ index %v"
,
idx
)
}
_
,
val
:=
valSet
.
GetByIndex
(
idx
)
// Validate signature
precommitSignBytes
:=
SignBytes
(
chainID
,
precommit
)
sig
,
err
:=
ConsensusCrypto
.
SignatureFromBytes
(
precommit
.
Signature
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"VerifyCommit SignatureFromBytes [%X] failed:%v"
,
precommit
.
Signature
,
err
)
}
pubkey
,
err
:=
ConsensusCrypto
.
PubKeyFromBytes
(
val
.
PubKey
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"VerifyCommit PubKeyFromBytes [%X] failed:%v"
,
val
.
PubKey
,
err
)
}
if
!
pubkey
.
VerifyBytes
(
precommitSignBytes
,
sig
)
{
return
fmt
.
Errorf
(
"Invalid commit -- invalid signature: %v"
,
precommit
)
}
if
!
bytes
.
Equal
(
blockID
.
Hash
,
precommit
.
BlockID
.
Hash
)
{
continue
// Not an error, but doesn't count
}
// Good precommit!
talliedVotingPower
+=
val
.
VotingPower
}
// Good precommit!
talliedVotingPower
+=
val
.
VotingPower
}
if
talliedVotingPower
>
valSet
.
TotalVotingPower
()
*
2
/
3
{
...
...
plugin/consensus/tendermint/types/vote_set.go
View file @
b23f5c28
...
...
@@ -8,7 +8,9 @@ import (
"bytes"
"strings"
"sync"
"time"
"github.com/33cn/chain33/common/crypto"
tmtypes
"github.com/33cn/plugin/plugin/dapp/valnode/types"
"github.com/pkg/errors"
)
...
...
@@ -63,6 +65,7 @@ type VoteSet struct {
maj23
*
tmtypes
.
BlockID
// First 2/3 majority seen
votesByBlock
map
[
string
]
*
blockVotes
// string(blockHash|blockParts) -> blockVotes
peerMaj23s
map
[
string
]
*
tmtypes
.
BlockID
// Maj23 for each peer
aggVote
*
AggVote
// aggregate vote
}
// NewVoteSet Constructs a new VoteSet struct used to accumulate votes for given height/round.
...
...
@@ -82,6 +85,7 @@ func NewVoteSet(chainID string, height int64, round int, voteType byte, valSet *
maj23
:
nil
,
votesByBlock
:
make
(
map
[
string
]
*
blockVotes
,
valSet
.
Size
()),
peerMaj23s
:
make
(
map
[
string
]
*
tmtypes
.
BlockID
),
aggVote
:
nil
,
}
}
...
...
@@ -133,7 +137,7 @@ func (voteSet *VoteSet) Size() int {
// NOTE: Vote must not be nil
func
(
voteSet
*
VoteSet
)
AddVote
(
vote
*
Vote
)
(
added
bool
,
err
error
)
{
if
voteSet
==
nil
{
PanicSanity
(
"AddVote() on nil VoteS
et"
)
return
false
,
errors
.
New
(
"nil vote s
et"
)
}
voteSet
.
mtx
.
Lock
()
defer
voteSet
.
mtx
.
Unlock
()
...
...
@@ -291,6 +295,146 @@ func (voteSet *VoteSet) addVerifiedVote(vote *Vote, blockKey string, votingPower
return
true
,
conflicting
}
// AddAggVote Returns added=true if aggVote is valid and new
func
(
voteSet
*
VoteSet
)
AddAggVote
(
vote
*
AggVote
)
(
bool
,
error
)
{
if
voteSet
==
nil
{
return
false
,
errors
.
New
(
"nil vote set"
)
}
if
vote
==
nil
{
return
false
,
ErrAggVoteNil
}
voteSet
.
mtx
.
Lock
()
defer
voteSet
.
mtx
.
Unlock
()
valAddr
:=
vote
.
ValidatorAddress
valset
:=
voteSet
.
valSet
if
len
(
valAddr
)
==
0
{
return
false
,
errors
.
Wrap
(
ErrVoteInvalidValidatorAddress
,
"Empty address"
)
}
// Make sure the step matches
if
(
vote
.
Height
!=
voteSet
.
height
)
||
(
int
(
vote
.
Round
)
!=
voteSet
.
round
)
||
(
vote
.
Type
!=
uint32
(
voteSet
.
voteType
))
{
return
false
,
errors
.
Wrapf
(
ErrVoteUnexpectedStep
,
"Got %d/%d/%d, expected %d/%d/%d"
,
voteSet
.
height
,
voteSet
.
round
,
voteSet
.
voteType
,
vote
.
Height
,
vote
.
Round
,
vote
.
Type
)
}
// Ensure that signer is proposer
propAddr
:=
valset
.
Proposer
.
Address
if
!
bytes
.
Equal
(
valAddr
,
propAddr
)
{
return
false
,
errors
.
Wrapf
(
ErrVoteInvalidValidatorAddress
,
"aggVote.ValidatorAddress (%X) does not match proposer address (%X)"
,
valAddr
,
propAddr
)
}
// If we already know of this vote, return false
if
voteSet
.
aggVote
!=
nil
{
if
bytes
.
Equal
(
voteSet
.
aggVote
.
Signature
,
vote
.
Signature
)
{
return
false
,
nil
// duplicate
}
return
false
,
errors
.
Wrapf
(
ErrVoteNonDeterministicSignature
,
"Existing vote: %v; New vote: %v"
,
voteSet
.
aggVote
,
vote
)
}
// Check signature
err
:=
vote
.
Verify
(
voteSet
.
chainID
,
voteSet
.
valSet
)
if
err
!=
nil
{
return
false
,
err
}
// Check maj32
sum
:=
int64
(
0
)
arr
:=
&
BitArray
{
TendermintBitArray
:
vote
.
ValidatorArray
}
for
i
,
val
:=
range
valset
.
Validators
{
if
arr
.
GetIndex
(
i
)
{
sum
+=
val
.
VotingPower
}
}
quorum
:=
voteSet
.
valSet
.
TotalVotingPower
()
*
2
/
3
+
1
if
sum
<
quorum
{
return
false
,
errors
.
New
(
"less than 2/3 total power"
)
}
voteSet
.
votesBitArray
=
arr
.
copy
()
voteSet
.
aggVote
=
vote
voteSet
.
maj23
=
vote
.
BlockID
voteSet
.
sum
=
sum
votesByBlock
:=
newBlockVotes
(
false
,
voteSet
.
valSet
.
Size
())
votesByBlock
.
bitArray
=
arr
.
copy
()
votesByBlock
.
sum
=
sum
voteSet
.
votesByBlock
[
string
(
voteSet
.
maj23
.
Hash
)]
=
votesByBlock
return
true
,
nil
}
// SetAggVote generate aggregate vote when voteSet have 2/3 majority
func
(
voteSet
*
VoteSet
)
SetAggVote
()
error
{
if
voteSet
==
nil
{
return
errors
.
New
(
"nil vote set"
)
}
if
voteSet
.
maj23
==
nil
{
return
errors
.
New
(
"no 2/3 majority in voteSet"
)
}
voteSet
.
mtx
.
Lock
()
defer
voteSet
.
mtx
.
Unlock
()
blockKey
:=
string
(
voteSet
.
maj23
.
Hash
)
votesByBlock
,
ok
:=
voteSet
.
votesByBlock
[
blockKey
]
if
!
ok
{
return
errors
.
New
(
"no 2/3 majority blockKey"
)
}
bitArray
:=
votesByBlock
.
bitArray
.
copy
()
sigs
:=
make
([]
crypto
.
Signature
,
0
)
for
_
,
vote
:=
range
votesByBlock
.
votes
{
if
vote
!=
nil
{
sig
,
err
:=
ConsensusCrypto
.
SignatureFromBytes
(
vote
.
Signature
)
if
err
!=
nil
{
return
errors
.
New
(
"invalid aggregate signature"
)
}
sigs
=
append
(
sigs
,
sig
)
}
}
aggr
,
err
:=
crypto
.
ToAggregate
(
ConsensusCrypto
)
if
err
!=
nil
{
return
err
}
aggSig
,
err
:=
aggr
.
Aggregate
(
sigs
)
if
err
!=
nil
{
return
err
}
aggVote
:=
&
AggVote
{
&
tmtypes
.
AggVote
{
ValidatorAddress
:
voteSet
.
valSet
.
Proposer
.
Address
,
ValidatorArray
:
bitArray
.
TendermintBitArray
,
Height
:
voteSet
.
height
,
Round
:
int32
(
voteSet
.
round
),
Timestamp
:
time
.
Now
()
.
UnixNano
(),
Type
:
uint32
(
voteSet
.
voteType
),
BlockID
:
voteSet
.
maj23
,
Signature
:
aggSig
.
Bytes
(),
}}
// Verify aggVote
err
=
aggVote
.
Verify
(
voteSet
.
chainID
,
voteSet
.
valSet
)
if
err
!=
nil
{
return
err
}
voteSet
.
aggVote
=
aggVote
return
nil
}
// GetAggVote ...
func
(
voteSet
*
VoteSet
)
GetAggVote
()
*
AggVote
{
if
voteSet
==
nil
{
return
nil
}
voteSet
.
mtx
.
Lock
()
defer
voteSet
.
mtx
.
Unlock
()
if
voteSet
.
aggVote
==
nil
{
return
nil
}
return
voteSet
.
aggVote
.
Copy
()
}
// SetPeerMaj23 If a peer claims that it has 2/3 majority for given blockKey, call this.
// NOTE: if there are too many peers, or too much peer churn,
// this can cause memory issues.
...
...
@@ -446,12 +590,12 @@ func (voteSet *VoteSet) StringIndented(indent string) string {
}
}
return
Fmt
(
`VoteSet{
%s H:%v R:%v T:%v
%s H:%v R:%v T:%v
+2/3:%X
%s %v
%s %v
%s %v
%s}`
,
indent
,
voteSet
.
height
,
voteSet
.
round
,
voteSet
.
voteType
,
indent
,
voteSet
.
height
,
voteSet
.
round
,
voteSet
.
voteType
,
voteSet
.
maj23
,
indent
,
strings
.
Join
(
voteStrings
,
"
\n
"
+
indent
+
" "
),
indent
,
voteSet
.
votesBitArray
,
indent
,
voteSet
.
peerMaj23s
,
...
...
@@ -491,10 +635,15 @@ func (voteSet *VoteSet) MakeCommit() *tmtypes.TendermintCommit {
votesCopy
[
i
]
=
&
tmtypes
.
Vote
{}
}
}
//copy(votesCopy, voteSet.votes)
var
aggVote
*
tmtypes
.
AggVote
if
voteSet
.
aggVote
!=
nil
{
copy
:=
voteSet
.
aggVote
.
Copy
()
aggVote
=
copy
.
AggVote
}
return
&
tmtypes
.
TendermintCommit
{
BlockID
:
voteSet
.
maj23
,
Precommits
:
votesCopy
,
AggVote
:
aggVote
,
}
}
...
...
@@ -549,4 +698,5 @@ type VoteSetReader interface {
BitArray
()
*
BitArray
GetByIndex
(
int
)
*
Vote
IsCommit
()
bool
GetAggVote
()
*
AggVote
}
plugin/crypto/bls/bls.go
0 → 100644
View file @
b23f5c28
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
bls
import
(
"bytes"
"crypto/rand"
"errors"
"fmt"
"github.com/33cn/chain33/common/crypto"
"github.com/phoreproject/bls/g1pubs"
)
const
(
BLSPrivateKeyLength
=
32
BLSPublicKeyLength
=
48
BLSSignatureLength
=
96
)
// Driver driver
type
Driver
struct
{}
// GenKey create private key
func
(
d
Driver
)
GenKey
()
(
crypto
.
PrivKey
,
error
)
{
privKeyBytes
:=
new
([
BLSPrivateKeyLength
]
byte
)
priv
,
err
:=
g1pubs
.
RandKey
(
rand
.
Reader
)
if
err
!=
nil
{
return
nil
,
err
}
privBytes
:=
priv
.
Serialize
()
copy
(
privKeyBytes
[
:
],
privBytes
[
:
])
return
PrivKeyBLS
(
*
privKeyBytes
),
nil
}
// PrivKeyFromBytes create private key from bytes
func
(
d
Driver
)
PrivKeyFromBytes
(
b
[]
byte
)
(
privKey
crypto
.
PrivKey
,
err
error
)
{
if
len
(
b
)
!=
BLSPrivateKeyLength
{
return
nil
,
errors
.
New
(
"invalid bls priv key byte"
)
}
privKeyBytes
:=
new
([
BLSPrivateKeyLength
]
byte
)
copy
(
privKeyBytes
[
:
],
b
[
:
BLSPrivateKeyLength
])
priv
:=
g1pubs
.
DeserializeSecretKey
(
*
privKeyBytes
)
if
priv
==
nil
{
return
nil
,
errors
.
New
(
"invalid bls privkey"
)
}
privBytes
:=
priv
.
Serialize
()
copy
(
privKeyBytes
[
:
],
privBytes
[
:
])
return
PrivKeyBLS
(
*
privKeyBytes
),
nil
}
// PubKeyFromBytes create public key from bytes
func
(
d
Driver
)
PubKeyFromBytes
(
b
[]
byte
)
(
pubKey
crypto
.
PubKey
,
err
error
)
{
if
len
(
b
)
!=
BLSPublicKeyLength
{
return
nil
,
errors
.
New
(
"invalid bls pub key byte"
)
}
pubKeyBytes
:=
new
([
BLSPublicKeyLength
]
byte
)
copy
(
pubKeyBytes
[
:
],
b
[
:
])
return
PubKeyBLS
(
*
pubKeyBytes
),
nil
}
// SignatureFromBytes create signature from bytes
func
(
d
Driver
)
SignatureFromBytes
(
b
[]
byte
)
(
sig
crypto
.
Signature
,
err
error
)
{
sigBytes
:=
new
([
BLSSignatureLength
]
byte
)
copy
(
sigBytes
[
:
],
b
[
:
])
return
SignatureBLS
(
*
sigBytes
),
nil
}
//Aggregate aggregates signatures together into a new signature.
func
(
d
Driver
)
Aggregate
(
sigs
[]
crypto
.
Signature
)
(
crypto
.
Signature
,
error
)
{
if
len
(
sigs
)
==
0
{
return
nil
,
errors
.
New
(
"no signatures to aggregate"
)
}
g1sigs
:=
make
([]
*
g1pubs
.
Signature
,
0
,
len
(
sigs
))
for
i
,
sig
:=
range
sigs
{
g1sig
,
err
:=
ConvertToSignature
(
sig
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"%v(index: %d)"
,
err
,
i
)
}
g1sigs
=
append
(
g1sigs
,
g1sig
)
}
agsig
:=
g1pubs
.
AggregateSignatures
(
g1sigs
)
return
SignatureBLS
(
agsig
.
Serialize
()),
nil
}
//AggregatePublic aggregates public keys together into a new PublicKey.
func
(
d
Driver
)
AggregatePublic
(
pubs
[]
crypto
.
PubKey
)
(
crypto
.
PubKey
,
error
)
{
if
len
(
pubs
)
==
0
{
return
nil
,
errors
.
New
(
"no public keys to aggregate"
)
}
//blank public key
g1pubs
:=
g1pubs
.
NewAggregatePubkey
()
for
i
,
pub
:=
range
pubs
{
g1pub
,
err
:=
ConvertToPublicKey
(
pub
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"%v(index: %d)"
,
err
,
i
)
}
g1pubs
.
Aggregate
(
g1pub
)
}
return
PubKeyBLS
(
g1pubs
.
Serialize
()),
nil
}
// VerifyAggregatedOne verifies each public key against a message.
func
(
d
Driver
)
VerifyAggregatedOne
(
pubs
[]
crypto
.
PubKey
,
m
[]
byte
,
sig
crypto
.
Signature
)
error
{
g1pubs
:=
make
([]
*
g1pubs
.
PublicKey
,
0
,
len
(
pubs
))
for
i
,
pub
:=
range
pubs
{
g1pub
,
err
:=
ConvertToPublicKey
(
pub
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"%v(index: %d)"
,
err
,
i
)
}
g1pubs
=
append
(
g1pubs
,
g1pub
)
}
g1sig
,
err
:=
ConvertToSignature
(
sig
)
if
err
!=
nil
{
return
err
}
if
g1sig
.
VerifyAggregateCommon
(
g1pubs
,
m
)
{
return
nil
}
return
errors
.
New
(
"bls signature mismatch"
)
}
// VerifyAggregatedN verifies each public key against each message.
func
(
d
Driver
)
VerifyAggregatedN
(
pubs
[]
crypto
.
PubKey
,
ms
[][]
byte
,
sig
crypto
.
Signature
)
error
{
g1pubs
:=
make
([]
*
g1pubs
.
PublicKey
,
0
,
len
(
pubs
))
for
i
,
pub
:=
range
pubs
{
g1pub
,
err
:=
ConvertToPublicKey
(
pub
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"%v(index: %d)"
,
err
,
i
)
}
g1pubs
=
append
(
g1pubs
,
g1pub
)
}
g1sig
,
err
:=
ConvertToSignature
(
sig
)
if
err
!=
nil
{
return
err
}
if
len
(
g1pubs
)
!=
len
(
ms
)
{
return
fmt
.
Errorf
(
"different length of pubs and messages, %d vs %d"
,
len
(
g1pubs
),
len
(
ms
))
}
if
g1sig
.
VerifyAggregate
(
g1pubs
,
ms
)
{
return
nil
}
return
errors
.
New
(
"bls signature mismatch"
)
}
// ConvertToSignature convert to BLS Signature
func
ConvertToSignature
(
sig
crypto
.
Signature
)
(
*
g1pubs
.
Signature
,
error
)
{
// unwrap if needed
if
wrap
,
ok
:=
sig
.
(
SignatureS
);
ok
{
sig
=
wrap
.
Signature
}
sigBLS
,
ok
:=
sig
.
(
SignatureBLS
)
if
!
ok
{
return
nil
,
errors
.
New
(
"invalid bls signature"
)
}
g1sig
,
err
:=
g1pubs
.
DeserializeSignature
(
sigBLS
)
if
err
!=
nil
{
return
nil
,
err
}
return
g1sig
,
nil
}
// ConvertToPublicKey convert to BLS PublicKey
func
ConvertToPublicKey
(
pub
crypto
.
PubKey
)
(
*
g1pubs
.
PublicKey
,
error
)
{
pubBLS
,
ok
:=
pub
.
(
PubKeyBLS
)
if
!
ok
{
return
nil
,
errors
.
New
(
"invalid bls public key"
)
}
g1pub
,
err
:=
g1pubs
.
DeserializePublicKey
(
pubBLS
)
if
err
!=
nil
{
return
nil
,
err
}
return
g1pub
,
nil
}
// PrivKeyBLS PrivKey
type
PrivKeyBLS
[
BLSPrivateKeyLength
]
byte
// Bytes convert to bytes
func
(
privKey
PrivKeyBLS
)
Bytes
()
[]
byte
{
s
:=
make
([]
byte
,
BLSPrivateKeyLength
)
copy
(
s
,
privKey
[
:
])
return
s
}
// Sign create signature
func
(
privKey
PrivKeyBLS
)
Sign
(
msg
[]
byte
)
crypto
.
Signature
{
priv
:=
g1pubs
.
DeserializeSecretKey
(
privKey
)
sig
:=
g1pubs
.
Sign
(
msg
,
priv
)
return
SignatureBLS
(
sig
.
Serialize
())
}
// PubKey convert to public key
func
(
privKey
PrivKeyBLS
)
PubKey
()
crypto
.
PubKey
{
priv
:=
g1pubs
.
DeserializeSecretKey
(
privKey
)
return
PubKeyBLS
(
g1pubs
.
PrivToPub
(
priv
)
.
Serialize
())
}
// Equals check privkey is equal
func
(
privKey
PrivKeyBLS
)
Equals
(
other
crypto
.
PrivKey
)
bool
{
if
otherSecp
,
ok
:=
other
.
(
PrivKeyBLS
);
ok
{
return
bytes
.
Equal
(
privKey
[
:
],
otherSecp
[
:
])
}
return
false
}
// String convert to string
func
(
privKey
PrivKeyBLS
)
String
()
string
{
return
fmt
.
Sprintf
(
"PrivKeyBLS{*****}"
)
}
// PubKeyBLS PubKey
type
PubKeyBLS
[
BLSPublicKeyLength
]
byte
// Bytes convert to bytes
func
(
pubKey
PubKeyBLS
)
Bytes
()
[]
byte
{
s
:=
make
([]
byte
,
BLSPublicKeyLength
)
copy
(
s
,
pubKey
[
:
])
return
s
}
// VerifyBytes verify signature
func
(
pubKey
PubKeyBLS
)
VerifyBytes
(
msg
[]
byte
,
sig
crypto
.
Signature
)
bool
{
pub
,
err
:=
g1pubs
.
DeserializePublicKey
(
pubKey
)
if
err
!=
nil
{
fmt
.
Println
(
"invalid bls pubkey"
)
return
false
}
g1sig
,
err
:=
ConvertToSignature
(
sig
)
if
err
!=
nil
{
fmt
.
Println
(
"ConvertToSignature fail:"
,
err
)
return
false
}
return
g1pubs
.
Verify
(
msg
,
pub
,
g1sig
)
}
// String convert to string
func
(
pubKey
PubKeyBLS
)
String
()
string
{
return
fmt
.
Sprintf
(
"PubKeyBLS{%X}"
,
pubKey
[
:
])
}
// KeyString Must return the full bytes in hex.
// Used for map keying, etc.
func
(
pubKey
PubKeyBLS
)
KeyString
()
string
{
return
fmt
.
Sprintf
(
"%X"
,
pubKey
[
:
])
}
// Equals check public key is equal
func
(
pubKey
PubKeyBLS
)
Equals
(
other
crypto
.
PubKey
)
bool
{
if
otherSecp
,
ok
:=
other
.
(
PubKeyBLS
);
ok
{
return
bytes
.
Equal
(
pubKey
[
:
],
otherSecp
[
:
])
}
return
false
}
// SignatureBLS Signature
type
SignatureBLS
[
BLSSignatureLength
]
byte
// SignatureS signature struct
type
SignatureS
struct
{
crypto
.
Signature
}
// Bytes convert signature to bytes
func
(
sig
SignatureBLS
)
Bytes
()
[]
byte
{
s
:=
make
([]
byte
,
len
(
sig
))
copy
(
s
,
sig
[
:
])
return
s
}
// IsZero check signature is zero
func
(
sig
SignatureBLS
)
IsZero
()
bool
{
return
len
(
sig
)
==
0
}
// String convert signature to string
func
(
sig
SignatureBLS
)
String
()
string
{
fingerprint
:=
make
([]
byte
,
len
(
sig
[
:
]))
copy
(
fingerprint
,
sig
[
:
])
return
fmt
.
Sprintf
(
"/%X.../"
,
fingerprint
)
}
// Equals check signature equals
func
(
sig
SignatureBLS
)
Equals
(
other
crypto
.
Signature
)
bool
{
if
otherEd
,
ok
:=
other
.
(
SignatureBLS
);
ok
{
return
bytes
.
Equal
(
sig
[
:
],
otherEd
[
:
])
}
return
false
}
// Name name
const
Name
=
"bls"
// ID id
const
ID
=
259
func
init
()
{
crypto
.
Register
(
Name
,
&
Driver
{})
crypto
.
RegisterType
(
Name
,
ID
)
}
plugin/crypto/bls/bls_test.go
0 → 100644
View file @
b23f5c28
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
bls
import
(
"fmt"
"testing"
"github.com/33cn/chain33/common/crypto"
"github.com/stretchr/testify/assert"
)
var
blsDrv
=
&
Driver
{}
func
TestGenKey
(
t
*
testing
.
T
)
{
sk
,
err
:=
blsDrv
.
GenKey
()
assert
.
NoError
(
t
,
err
)
assert
.
NotEmpty
(
t
,
sk
)
pk
:=
sk
.
PubKey
()
assert
.
NotEmpty
(
t
,
pk
)
sk2
,
_
:=
blsDrv
.
GenKey
()
assert
.
NotEqual
(
t
,
sk
.
Bytes
(),
sk2
.
Bytes
(),
"should not generate two same key"
,
sk
,
sk2
)
}
func
TestSignAndVerify
(
t
*
testing
.
T
)
{
sk
,
_
:=
blsDrv
.
GenKey
()
pk
:=
sk
.
PubKey
()
m1
:=
[]
byte
(
"message to be signed. 将要做签名的消息"
)
// sign and verify
sig1
:=
sk
.
Sign
(
m1
)
ret
:=
pk
.
VerifyBytes
(
m1
,
sig1
)
assert
.
Equal
(
t
,
true
,
ret
)
// different message should have different signature
m2
:=
[]
byte
(
"message to be signed. 将要做签名的消息."
)
sig2
:=
sk
.
Sign
(
m2
)
assert
.
NotEqual
(
t
,
sig1
,
sig2
,
"different message got the same signature"
,
sig1
,
sig2
)
// different key should have different signature for a same message.
sk2
,
_
:=
blsDrv
.
GenKey
()
sig12
:=
sk2
.
Sign
(
m1
)
ret
=
pk
.
VerifyBytes
(
m1
,
sig12
)
assert
.
Equal
(
t
,
false
,
ret
)
}
func
TestAggregate
(
t
*
testing
.
T
)
{
m
:=
[]
byte
(
"message to be signed. 将要做签名的消息"
)
n
:=
8
pubs
:=
make
([]
crypto
.
PubKey
,
0
,
n
)
sigs
:=
make
([]
crypto
.
Signature
,
0
,
n
)
//signatures for the same message
msgs
:=
make
([][]
byte
,
0
,
n
)
dsigs
:=
make
([]
crypto
.
Signature
,
0
,
n
)
//signatures for each (key,message) pair
for
i
:=
0
;
i
<
n
;
i
++
{
sk
,
_
:=
blsDrv
.
GenKey
()
pk
:=
sk
.
PubKey
()
pubs
=
append
(
pubs
,
pk
)
sigs
=
append
(
sigs
,
sk
.
Sign
(
m
))
msgi
:=
append
(
m
,
byte
(
i
))
msgs
=
append
(
msgs
,
msgi
)
dsigs
=
append
(
dsigs
,
sk
.
Sign
(
msgi
))
}
asig
,
err
:=
blsDrv
.
Aggregate
(
sigs
)
assert
.
NoError
(
t
,
err
)
// One
err
=
blsDrv
.
VerifyAggregatedOne
(
pubs
,
m
,
asig
)
assert
.
NoError
(
t
,
err
)
apub
,
err
:=
blsDrv
.
AggregatePublic
(
pubs
)
assert
.
NoError
(
t
,
err
)
ret
:=
apub
.
VerifyBytes
(
m
,
asig
)
assert
.
Equal
(
t
,
true
,
ret
)
// N
adsig
,
err
:=
blsDrv
.
Aggregate
(
dsigs
)
assert
.
NoError
(
t
,
err
)
err
=
blsDrv
.
VerifyAggregatedN
(
pubs
,
msgs
,
adsig
)
assert
.
NoError
(
t
,
err
)
//lose some messages will cause an error
err
=
blsDrv
.
VerifyAggregatedN
(
pubs
,
msgs
[
1
:
],
adsig
)
assert
.
Error
(
t
,
err
)
//with out-of-order public keys, will has no effect on VerifyAggregatedOne, but DO effects VerifyAggregatedN
pubs
[
0
],
pubs
[
1
]
=
pubs
[
1
],
pubs
[
0
]
err
=
blsDrv
.
VerifyAggregatedOne
(
pubs
,
m
,
asig
)
assert
.
NoError
(
t
,
err
)
err
=
blsDrv
.
VerifyAggregatedN
(
pubs
,
msgs
,
adsig
)
assert
.
Error
(
t
,
err
)
//invalid length
_
,
err
=
blsDrv
.
Aggregate
(
nil
)
assert
.
Error
(
t
,
err
)
_
,
err
=
blsDrv
.
AggregatePublic
(
make
([]
crypto
.
PubKey
,
0
))
assert
.
Error
(
t
,
err
)
}
//benchmark
func
BenchmarkBLSAggregateSignature
(
b
*
testing
.
B
)
{
msg
:=
[]
byte
(
">16 character identical message"
)
n
:=
200
sigs
:=
make
([]
crypto
.
Signature
,
0
,
n
)
//signatures for the same message
for
i
:=
0
;
i
<
n
;
i
++
{
sk
,
_
:=
blsDrv
.
GenKey
()
sigs
=
append
(
sigs
,
sk
.
Sign
(
msg
))
}
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
blsDrv
.
Aggregate
(
sigs
)
//nolint:errcheck
}
}
func
BenchmarkBLSSign
(
b
*
testing
.
B
)
{
sks
:=
make
([]
crypto
.
PrivKey
,
b
.
N
)
msgs
:=
make
([][]
byte
,
0
,
b
.
N
)
for
i
:=
range
sks
{
sks
[
i
],
_
=
blsDrv
.
GenKey
()
msgs
=
append
(
msgs
,
[]
byte
(
fmt
.
Sprintf
(
"Hello world! 16 characters %d"
,
i
)))
}
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
sks
[
i
]
.
Sign
(
msgs
[
i
])
}
}
func
BenchmarkBLSVerify
(
b
*
testing
.
B
)
{
sk
,
_
:=
blsDrv
.
GenKey
()
pk
:=
sk
.
PubKey
()
m
:=
[]
byte
(
">16 character identical message"
)
sig
:=
sk
.
Sign
(
m
)
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
pk
.
VerifyBytes
(
m
,
sig
)
//nolint:errcheck
}
}
func
BenchmarkBlsManager_VerifyAggregatedOne
(
b
*
testing
.
B
)
{
m
:=
[]
byte
(
"message to be signed. 将要做签名的消息"
)
n
:=
100
pubs
:=
make
([]
crypto
.
PubKey
,
0
,
n
)
sigs
:=
make
([]
crypto
.
Signature
,
0
,
n
)
//signatures for the same message
for
i
:=
0
;
i
<
n
;
i
++
{
sk
,
_
:=
blsDrv
.
GenKey
()
pk
:=
sk
.
PubKey
()
pubs
=
append
(
pubs
,
pk
)
sigs
=
append
(
sigs
,
sk
.
Sign
(
m
))
}
asig
,
_
:=
blsDrv
.
Aggregate
(
sigs
)
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
blsDrv
.
VerifyAggregatedOne
(
pubs
,
m
,
asig
)
//nolint:errcheck
}
}
func
BenchmarkBlsManager_VerifyAggregatedN
(
b
*
testing
.
B
)
{
m
:=
[]
byte
(
"message to be signed. 将要做签名的消息"
)
n
:=
100
pubs
:=
make
([]
crypto
.
PubKey
,
0
,
n
)
sigs
:=
make
([]
crypto
.
Signature
,
0
,
n
)
msgs
:=
make
([][]
byte
,
0
,
n
)
for
i
:=
0
;
i
<
n
;
i
++
{
mi
:=
append
(
m
,
byte
(
i
))
sk
,
_
:=
blsDrv
.
GenKey
()
pk
:=
sk
.
PubKey
()
pubs
=
append
(
pubs
,
pk
)
sigs
=
append
(
sigs
,
sk
.
Sign
(
mi
))
msgs
=
append
(
msgs
,
mi
)
}
asig
,
_
:=
blsDrv
.
Aggregate
(
sigs
)
b
.
ResetTimer
()
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
blsDrv
.
VerifyAggregatedN
(
pubs
,
msgs
,
asig
)
//nolint:errcheck
}
}
plugin/crypto/init/init.go
View file @
b23f5c28
package
init
import
(
_
"github.com/33cn/plugin/plugin/crypto/bls"
//auto gen
_
"github.com/33cn/plugin/plugin/crypto/ecdsa"
//auto gen
_
"github.com/33cn/plugin/plugin/crypto/sm2"
//auto gen
)
plugin/dapp/valnode/commands/valnode.go
View file @
b23f5c28
...
...
@@ -25,6 +25,7 @@ var (
strChars
=
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
// 62 characters
genFile
=
"genesis_file.json"
pvFile
=
"priv_validator_"
AuthBLS
=
259
)
// ValCmd valnode cmd register
...
...
@@ -164,8 +165,9 @@ func CreateCmd() *cobra.Command {
}
func
addCreateCmdFlags
(
cmd
*
cobra
.
Command
)
{
cmd
.
Flags
()
.
StringP
(
"num"
,
"n"
,
""
,
"
N
um of the keyfile to create"
)
cmd
.
Flags
()
.
StringP
(
"num"
,
"n"
,
""
,
"
n
um of the keyfile to create"
)
cmd
.
MarkFlagRequired
(
"num"
)
cmd
.
Flags
()
.
StringP
(
"type"
,
"t"
,
"ed25519"
,
"sign type of the keyfile (secp256k1, ed25519, sm2, bls)"
)
}
// RandStr ...
...
...
@@ -192,10 +194,11 @@ MAIN_LOOP:
return
string
(
chars
)
}
func
initCryptoImpl
()
error
{
cr
,
err
:=
crypto
.
New
(
types
.
GetSignName
(
""
,
types
.
ED25519
))
func
initCryptoImpl
(
signType
int
)
error
{
ttypes
.
CryptoName
=
types
.
GetSignName
(
""
,
signType
)
cr
,
err
:=
crypto
.
New
(
ttypes
.
CryptoName
)
if
err
!=
nil
{
fmt
.
Printf
(
"
New crypto impl failed err
: %v"
,
err
)
fmt
.
Printf
(
"
Init crypto fail
: %v"
,
err
)
return
err
}
ttypes
.
ConsensusCrypto
=
cr
...
...
@@ -204,7 +207,13 @@ func initCryptoImpl() error {
func
createFiles
(
cmd
*
cobra
.
Command
,
args
[]
string
)
{
// init crypto instance
err
:=
initCryptoImpl
()
ty
,
_
:=
cmd
.
Flags
()
.
GetString
(
"type"
)
signType
,
ok
:=
ttypes
.
SignMap
[
ty
]
if
!
ok
{
fmt
.
Println
(
"type parameter is not valid"
)
return
}
err
:=
initCryptoImpl
(
signType
)
if
err
!=
nil
{
return
}
...
...
@@ -232,7 +241,7 @@ func createFiles(cmd *cobra.Command, args []string) {
// create genesis validator by the pubkey of private validator
gv
:=
ttypes
.
GenesisValidator
{
PubKey
:
ttypes
.
KeyText
{
Kind
:
"ed25519"
,
Data
:
privValidator
.
GetPubKey
()
.
KeyString
()},
PubKey
:
ttypes
.
KeyText
{
Kind
:
ttypes
.
CryptoName
,
Data
:
privValidator
.
GetPubKey
()
.
KeyString
()},
Power
:
10
,
}
genDoc
.
Validators
=
append
(
genDoc
.
Validators
,
gv
)
...
...
plugin/dapp/valnode/executor/exec.go
View file @
b23f5c28
...
...
@@ -35,11 +35,22 @@ func (val *ValNode) Exec_BlockInfo(blockInfo *pty.TendermintBlockInfo, tx *types
return
receipt
,
nil
}
func
getConfigKey
(
key
string
,
db
dbm
.
KV
)
([]
byte
,
error
)
{
configKey
:=
types
.
ConfigKey
(
key
)
value
,
err
:=
db
.
Get
([]
byte
(
configKey
))
if
err
!=
nil
{
clog
.
Error
(
"getConfigKey not find"
,
"configKey"
,
configKey
,
"err"
,
err
)
return
nil
,
err
}
return
value
,
nil
}
func
getManageKey
(
key
string
,
db
dbm
.
KV
)
([]
byte
,
error
)
{
manageKey
:=
types
.
ManageKey
(
key
)
value
,
err
:=
db
.
Get
([]
byte
(
manageKey
))
if
err
!=
nil
{
return
nil
,
err
clog
.
Info
(
"getManageKey not find"
,
"manageKey"
,
manageKey
,
"err"
,
err
)
return
getConfigKey
(
key
,
db
)
}
return
value
,
nil
}
...
...
plugin/dapp/valnode/proto/tendermint.proto
View file @
b23f5c28
...
...
@@ -5,86 +5,88 @@ import "blockchain.proto";
package
types
;
message
BlockID
{
bytes
H
ash
=
1
;
bytes
h
ash
=
1
;
}
message
TendermintBitArray
{
int32
B
its
=
1
;
repeated
uint64
E
lems
=
2
;
int32
b
its
=
1
;
repeated
uint64
e
lems
=
2
;
}
message
Vote
{
bytes
ValidatorAddress
=
1
;
int32
ValidatorIndex
=
2
;
int64
Height
=
3
;
int32
Round
=
4
;
int64
Timestamp
=
5
;
uint32
Type
=
6
;
BlockID
BlockID
=
7
;
bytes
Signature
=
8
;
bytes
validatorAddress
=
1
;
int32
validatorIndex
=
2
;
int64
height
=
3
;
int32
round
=
4
;
int64
timestamp
=
5
;
uint32
type
=
6
;
BlockID
blockID
=
7
;
bytes
signature
=
8
;
bool
useAggSig
=
9
;
}
message
TendermintCommit
{
BlockID
BlockID
=
1
;
repeated
Vote
Precommits
=
2
;
BlockID
blockID
=
1
;
repeated
Vote
precommits
=
2
;
AggVote
aggVote
=
3
;
}
message
TendermintBlockInfo
{
State
S
tate
=
2
;
Proposal
P
roposal
=
3
;
State
s
tate
=
2
;
Proposal
p
roposal
=
3
;
TendermintBlock
block
=
4
;
}
message
BlockSize
{
int32
M
axBytes
=
1
;
int32
M
axTxs
=
2
;
int64
M
axGas
=
3
;
int32
m
axBytes
=
1
;
int32
m
axTxs
=
2
;
int64
m
axGas
=
3
;
}
message
TxSize
{
int32
M
axBytes
=
1
;
int64
M
axGas
=
2
;
int32
m
axBytes
=
1
;
int64
m
axGas
=
2
;
}
message
BlockGossip
{
int32
B
lockPartSizeBytes
=
1
;
int32
b
lockPartSizeBytes
=
1
;
}
message
EvidenceParams
{
int64
M
axAge
=
1
;
int64
m
axAge
=
1
;
}
message
ConsensusParams
{
BlockSize
B
lockSize
=
1
;
TxSize
T
xSize
=
2
;
BlockGossip
B
lockGossip
=
3
;
EvidenceParams
E
videnceParams
=
4
;
BlockSize
b
lockSize
=
1
;
TxSize
t
xSize
=
2
;
BlockGossip
b
lockGossip
=
3
;
EvidenceParams
e
videnceParams
=
4
;
}
message
Validator
{
bytes
A
ddress
=
1
;
bytes
P
ubKey
=
2
;
int64
V
otingPower
=
3
;
int64
A
ccum
=
4
;
bytes
a
ddress
=
1
;
bytes
p
ubKey
=
2
;
int64
v
otingPower
=
3
;
int64
a
ccum
=
4
;
}
message
ValidatorSet
{
repeated
Validator
V
alidators
=
1
;
Validator
P
roposer
=
2
;
repeated
Validator
v
alidators
=
1
;
Validator
p
roposer
=
2
;
}
message
State
{
string
C
hainID
=
1
;
int64
L
astBlockHeight
=
2
;
int64
L
astBlockTotalTx
=
3
;
BlockID
L
astBlockID
=
4
;
int64
L
astBlockTime
=
5
;
ValidatorSet
V
alidators
=
6
;
ValidatorSet
L
astValidators
=
7
;
int64
L
astHeightValidatorsChanged
=
8
;
ConsensusParams
C
onsensusParams
=
9
;
int64
L
astHeightConsensusParamsChanged
=
10
;
bytes
L
astResultsHash
=
11
;
bytes
A
ppHash
=
12
;
string
c
hainID
=
1
;
int64
l
astBlockHeight
=
2
;
int64
l
astBlockTotalTx
=
3
;
BlockID
l
astBlockID
=
4
;
int64
l
astBlockTime
=
5
;
ValidatorSet
v
alidators
=
6
;
ValidatorSet
l
astValidators
=
7
;
int64
l
astHeightValidatorsChanged
=
8
;
ConsensusParams
c
onsensusParams
=
9
;
int64
l
astHeightConsensusParamsChanged
=
10
;
bytes
l
astResultsHash
=
11
;
bytes
a
ppHash
=
12
;
}
message
TendermintBlockHeader
{
...
...
@@ -173,4 +175,15 @@ message Heartbeat {
message
IsHealthy
{
bool
isHealthy
=
1
;
}
message
AggVote
{
bytes
validatorAddress
=
1
;
TendermintBitArray
validatorArray
=
2
;
int64
height
=
3
;
int32
round
=
4
;
int64
timestamp
=
5
;
uint32
type
=
6
;
BlockID
blockID
=
7
;
bytes
signature
=
8
;
}
\ No newline at end of file
plugin/dapp/valnode/types/tendermint.pb.go
View file @
b23f5c28
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment