github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/consensus/ipbft/types/sign_aggr.go (about) 1 package types 2 3 import ( 4 //"bytes" 5 //"errors" 6 "fmt" 7 "math/big" 8 9 . "github.com/intfoundation/go-common" 10 "github.com/intfoundation/go-crypto" 11 //"github.com/intfoundation/go-data" 12 "github.com/intfoundation/go-wire" 13 "io" 14 ) 15 16 //------------------------ signature aggregation ------------------- 17 const MaxSignAggrSize = 22020096 // 21MB TODO make it configurable 18 19 type SignAggr struct { 20 ChainID string 21 Height uint64 `json:"height"` 22 Round int `json:"round"` 23 Type byte `json:"type"` 24 NumValidators int `json:"numValidators"` 25 BlockID BlockID `json:"blockid"` 26 Maj23 BlockID `json:"maj23"` 27 BitArray *BitArray `json:"bitarray"` 28 Sum int64 `json:"sum"` 29 30 // BLS signature aggregation to be added here 31 SignatureAggr crypto.BLSSignature `json:"SignatureAggr"` 32 SignBytes []byte `json:"sign_bytes"` 33 } 34 35 func (sa *SignAggr) WriteSignBytes(chainID string, w io.Writer, n *int, err *error) { 36 wire.WriteJSON(CanonicalJSONOnceSignAggr{ 37 chainID, 38 CanonicalJSONSignAggr{ 39 sa.Height, 40 sa.Round, 41 sa.Type, 42 sa.NumValidators, 43 CanonicalBlockID(sa.BlockID), 44 CanonicalBlockID(sa.BlockID), 45 sa.Sum, 46 }, 47 }, w, n, err) 48 } 49 50 func MakeSignAggr(height uint64, round int, mtype byte, numValidators int, blockID BlockID, chainID string, bitArray *BitArray, signAggr crypto.BLSSignature) *SignAggr { 51 return &SignAggr{ 52 Height: height, 53 Round: round, 54 Type: mtype, 55 NumValidators: numValidators, 56 BlockID: blockID, 57 Maj23: blockID, 58 ChainID: chainID, 59 BitArray: bitArray, 60 SignatureAggr: signAggr, 61 Sum: 0, 62 } 63 } 64 65 func (sa *SignAggr) SignAggr() crypto.BLSSignature { 66 if sa != nil { 67 return sa.SignatureAggr 68 } else { 69 return nil 70 } 71 } 72 73 func (sa *SignAggr) SignRound() int { 74 if sa == nil { 75 return -1 76 } else { 77 return sa.Round 78 } 79 } 80 81 func (sa *SignAggr) HasTwoThirdsMajority(valSet *ValidatorSet) bool { 82 if valSet == nil { 83 return false 84 } 85 _, votesSum, totalVotes, err := valSet.TalliedVotingPower(sa.BitArray) 86 if err != nil { 87 return false 88 } 89 90 /* 91 quorum := big.NewInt(0) 92 quorum.Mul(valSet.totalVotingPower, big.NewInt(2)) 93 quorum.Div(quorum, big.NewInt(3)) 94 quorum.Add(quorum, big.NewInt(1)) 95 */ 96 //quorum := Loose23MajorThreshold(valSet.TotalVotingPower(), sa.Round) 97 quorum := Loose23MajorThreshold(totalVotes, sa.Round) 98 99 //return talliedVotingPower.Cmp(quorum) >= 0 100 return votesSum.Cmp(quorum) >= 0 101 } 102 103 func (sa *SignAggr) SetMaj23(blockID BlockID) { 104 if sa == nil { 105 sa.Maj23 = blockID 106 } 107 } 108 109 func (sa *SignAggr) Size() int { 110 if sa == nil { 111 return 0 112 } 113 return (int)(sa.NumValidators) 114 } 115 116 func (sa *SignAggr) SetBitArray(newBitArray *BitArray) { 117 if sa != nil { 118 sa.BitArray.Update(newBitArray) 119 } 120 } 121 122 func (sa *SignAggr) IsCommit() bool { 123 if sa == nil { 124 return false 125 } 126 if sa.Type != VoteTypePrecommit { 127 return false 128 } 129 return sa.Maj23.IsZero() != false 130 } 131 132 func (sa *SignAggr) MakeCommit() *Commit { 133 // if sa.Type != types.VoteTypePrecommit { 134 // PanicSanity("Cannot MakeCommit() unless SignAggr.Type is VoteTypePrecommit") 135 // } 136 137 // Make sure we have a 2/3 majority 138 /* if sa.HasTwoThirdsMajority()== false { 139 PanicSanity("Cannot MakeCommit() unless a blockhash has +2/3") 140 } 141 */ 142 return &Commit{ 143 BlockID: sa.Maj23, 144 Height: sa.Height, 145 Round: sa.Round, 146 BitArray: sa.BitArray.Copy(), 147 SignAggr: sa.SignAggr(), 148 } 149 } 150 151 func (sa *SignAggr) SignAggrVerify(msg []byte, valSet *ValidatorSet) bool { 152 if msg == nil || valSet == nil { 153 return false 154 } 155 if (int)(sa.BitArray.Size()) != len(valSet.Validators) { 156 return false 157 } 158 pubKey := valSet.AggrPubKey(sa.BitArray) 159 return pubKey.VerifyBytes(msg, sa.SignatureAggr) && sa.HasTwoThirdsMajority(valSet) 160 } 161 162 //func (sa *SignAggr) HasTwoThirdsAny(valSet *ValidatorSet) bool { 163 // if sa == nil { 164 // return false 165 // } 166 // 167 // /* 168 // twoThird := new(big.Int).Mul(voteSet.valSet.TotalVotingPower(), big.NewInt(2)) 169 // twoThird.Div(twoThird, big.NewInt(3))sa 170 // */ 171 // twoThirdPlus1 := Loose23MajorThreshold(valSet.TotalVotingPower(), sa.Round) 172 // twoThird := twoThirdPlus1.Sub(twoThirdPlus1, big.NewInt(1)) 173 // 174 // return big.NewInt(sa.Sum).Cmp(twoThird) == 1 175 //} 176 177 func (sa *SignAggr) HasAll(valSet *ValidatorSet) bool { 178 return big.NewInt(sa.Sum).Cmp(valSet.TotalVotingPower()) == 0 179 } 180 181 // Returns either a blockhash (or nil) that received +2/3 majority. 182 // If there exists no such majority, returns (nil, PartSetHeader{}, false). 183 func (sa *SignAggr) TwoThirdsMajority() (blockID BlockID, ok bool) { 184 if sa == nil { 185 return BlockID{}, false 186 } 187 if sa.Maj23.IsZero() == true { 188 return BlockID{}, false 189 } else { 190 return sa.Maj23, true 191 } 192 } 193 194 func (va *SignAggr) StringShort() string { 195 return va.StringIndented("") 196 } 197 198 func (va *SignAggr) String() string { 199 return va.StringIndented("") 200 } 201 202 func (va *SignAggr) StringIndented(indent string) string { 203 if va == nil { 204 return "nil-SignAggr" 205 } 206 return fmt.Sprintf(`SignAggr{ 207 %s %v 208 %s %v 209 %s %v 210 %s %v 211 %s %v 212 }`, 213 indent, va.Height, 214 indent, va.Round, 215 indent, va.Type, 216 indent, va.NumValidators, 217 indent, va.BlockID) 218 }