github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/consense/poa/clique.go (about) 1 package poa 2 3 import ( 4 //"bytes" 5 "crypto" 6 "errors" 7 "fmt" 8 "math/big" 9 //"math/rand" 10 "sync" 11 "time" 12 13 lru "github.com/hashicorp/golang-lru" 14 "github.com/sixexorg/magnetic-ring/account" 15 "github.com/sixexorg/magnetic-ring/common" 16 "github.com/sixexorg/magnetic-ring/config" 17 "github.com/sixexorg/magnetic-ring/core/orgchain/types" 18 mycrypte "github.com/sixexorg/magnetic-ring/crypto" 19 "github.com/sixexorg/magnetic-ring/log" 20 "github.com/sixexorg/magnetic-ring/orgcontainer" 21 "github.com/sixexorg/magnetic-ring/rlp" 22 "github.com/sixexorg/magnetic-ring/store/orgchain/storages" 23 "github.com/sixexorg/magnetic-ring/store/storelaw" 24 _ "golang.org/x/crypto/sha3" 25 ) 26 27 const ( 28 inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory 29 inmemorySignatures = 4096 // Number of recent block signatures to keep in memory 30 31 wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers 32 ) 33 34 var ( 35 epochLength = uint64(30000) // Default number of blocks after which to checkpoint and reset the pending votes 36 diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures 37 diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures 38 ) 39 40 var ( 41 errUnknownBlock = errors.New("unknown block") 42 errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero") 43 errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f") 44 errInvalidCheckpointVote = errors.New("vote nonce in checkpoint block non-zero") 45 errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing") 46 errMissingSignature = errors.New("extra-data 65 byte suffix signature missing") 47 errExtraSigners = errors.New("non-checkpoint block contains extra signer list") 48 errInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block") 49 errInvalidMixDigest = errors.New("non-zero mix digest") 50 errInvalidUncleHash = errors.New("non empty uncle hash") 51 errInvalidDifficulty = errors.New("invalid difficulty") 52 ErrInvalidTimestamp = errors.New("invalid timestamp") 53 errInvalidVotingChain = errors.New("invalid voting chain") 54 errUnauthorized = errors.New("unauthorized") 55 errWaitTransactions = errors.New("waiting for transactions") 56 ) 57 58 func sigHash(header *types.Header) (hash common.Hash) { 59 sha3256 := crypto.SHA3_256.New() 60 rlp.Encode(sha3256, []interface{}{ 61 header.PrevBlockHash, 62 header.Coinbase, 63 header.BlockRoot, 64 header.TxRoot, 65 header.ReceiptsRoot, 66 header.Difficulty, 67 header.Height, 68 uint64(header.Timestamp), 69 header.Extra, // Yes, this will panic if extra is too short 70 }) 71 sha3256.Sum(hash[:0]) 72 return hash 73 } 74 75 func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { 76 hash := header.Hash() 77 if address, known := sigcache.Get(hash); known { 78 return address.(common.Address), nil 79 } 80 signature := header.Extra 81 82 pubkey, _ := mycrypte.UnmarshalPubkey([]byte(header.Coinbase[:])) 83 if fg, err := pubkey.Verify(hash[:], signature); !fg && err != nil { 84 return common.Address{}, err 85 } 86 87 sigcache.Add(hash, header.Coinbase) 88 return header.Coinbase, nil 89 } 90 91 type Clique struct { 92 config *config.CliqueConfig 93 ledger *storages.LedgerStoreImp 94 95 recents *lru.ARCCache 96 signatures *lru.ARCCache 97 98 account account.Account 99 signer common.Address 100 //txpool *common2.SubTxPool 101 orgContent *orgcontainer.Container 102 lock sync.RWMutex 103 } 104 105 func New(config *config.CliqueConfig, account account.Account, orgCtx *orgcontainer.Container, ledger *storages.LedgerStoreImp) *Clique { 106 conf := *config 107 if conf.Epoch == 0 { 108 conf.Epoch = epochLength 109 } 110 recents, _ := lru.NewARC(inmemorySnapshots) 111 signatures, _ := lru.NewARC(inmemorySignatures) 112 113 return &Clique{ 114 config: &conf, 115 account: account, 116 recents: recents, 117 signatures: signatures, 118 //txpool: txpool, 119 orgContent: orgCtx, 120 ledger: ledger, 121 } 122 } 123 124 func (c *Clique) Author(header *types.Header) (common.Address, error) { 125 return ecrecover(header, c.signatures) 126 } 127 128 func (c *Clique) VerifyHeader(header *types.Header, seal bool) error { 129 return c.verifyHeader(header) 130 } 131 132 func (c *Clique) verifyHeader(header *types.Header) error { 133 number := header.Height 134 135 if header.Timestamp > uint64(time.Now().Unix()) { 136 return ErrFutureBlock 137 } 138 139 checkpoint := (number % c.config.Epoch) == 0 140 if checkpoint && header.Coinbase != (common.Address{}) { 141 return errInvalidCheckpointBeneficiary 142 } 143 144 if number > 0 { 145 if header.Difficulty == nil || (header.Difficulty.Cmp(diffInTurn) != 0 && header.Difficulty.Cmp(diffNoTurn) != 0) { 146 return errInvalidDifficulty 147 } 148 } 149 150 return c.verifySeal(header) 151 } 152 153 func (c *Clique) snapshot(number uint64, hash common.Hash) (*Snapshot, error) { 154 var ( 155 headers []*types.Header 156 snap *Snapshot 157 ) 158 for snap == nil { 159 // If an in-memory snapshot was found, use that 160 if s, ok := c.recents.Get(hash); ok { 161 snap = s.(*Snapshot) 162 break 163 } 164 165 if number == 1 { 166 genesis, _ := c.ledger.GetBlockByHeight(1) 167 //if err := c.VerifyHeader(genesis.Header, false); err != nil { 168 // return nil, err 169 //} 170 var signers []common.Address 171 signers = append(signers, c.account.Address()) 172 snap = newSnapshot(c.config, c.signatures, 1, genesis.Hash(), signers) 173 log.Trace("Stored genesis voting snapshot to disk") 174 break 175 } 176 177 var header *types.Header 178 blk, _ := c.ledger.GetBlockByHeight(number) 179 //fmt.Println("øøøøøøøøøøøøøø", blk.Header.Coinbase.ToString(), blk.Header.Height) 180 header = blk.Header 181 if header == nil { 182 return nil, ErrUnknownAncestor 183 } 184 headers = append(headers, header) 185 number, hash = number-1, header.PrevBlockHash 186 } 187 188 snap, err := snap.apply(headers) 189 if err != nil { 190 return nil, err 191 } 192 c.recents.Add(snap.Hash, snap) 193 194 return snap, err 195 } 196 197 func (c *Clique) VerifySeal(header *types.Header) error { 198 return c.verifySeal(header) 199 } 200 201 func (c *Clique) verifySeal(header *types.Header) error { 202 // Verifying the genesis block is not supported 203 number := header.Height 204 if number == 0 { 205 return errUnknownBlock 206 } 207 // Retrieve the snapshot needed to verify this header and cache it 208 snap, err := c.snapshot(number-1, header.PrevBlockHash) 209 if err != nil { 210 return err 211 } 212 213 // Resolve the authorization key and check against signers 214 //signer, err := ecrecover(header, c.signatures) 215 //if err != nil { 216 // return err 217 //} 218 signer := header.Coinbase 219 if _, ok := snap.Signers[signer]; !ok { 220 return errUnauthorized 221 } 222 for seen, recent := range snap.Recents { 223 if recent == signer { 224 // Signer is among recents, only fail if the current block doesn't shift it out 225 if limit := uint64(len(snap.Signers)/2 + 1); seen > number-limit { 226 return errUnauthorized 227 } 228 } 229 } 230 // Ensure that the difficulty corresponds to the turn-ness of the signer 231 inturn := snap.inturn(header.Height, signer) 232 if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { 233 return errInvalidDifficulty 234 } 235 if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 { 236 return errInvalidDifficulty 237 } 238 return nil 239 } 240 241 func (c *Clique) Prepare(header *types.Header) error { 242 //header.Coinbase = common.Address{} 243 number := header.Height 244 245 // Assemble the voting snapshot to check which votes make sense 246 snap, err := c.snapshot(number-1, header.PrevBlockHash) 247 if err != nil { 248 return err 249 } 250 // Set the correct difficulty 251 header.Difficulty = diffNoTurn 252 if snap.inturn(header.Height, c.signer) { 253 header.Difficulty = diffInTurn 254 } 255 //parent, _ := c.ledger.GetBlockByHeight(number - 1) 256 //if parent == nil { 257 // return ErrUnknownAncestor 258 //} 259 //header.Timestamp = uint64(time.Unix(int64(header.Timestamp), 0).Add(time.Millisecond *500).Unix()) 260 //timeNow := uint64(time.Now().Unix()) 261 //if header.Timestamp < timeNow { 262 // header.Timestamp = timeNow 263 //} 264 //if time.Now().After(t1) { 265 // header.Timestamp = uint64(time.Now().Unix()) 266 //} 267 //fmt.Println("++++++++++++++++++++++++++++++++++++",// t.Format("15:04:05.000"), "t1:", t1.Format("15:04:05.000"), 268 // "height:", header.Height, "timestamp:", time.Unix(0, int64(header.Timestamp)).Format("15:04:05.000")) 269 return nil 270 } 271 272 func (c *Clique) Finalize(blkInfo *storelaw.OrgBlockInfo) (*types.Block, error) { 273 // save all 274 275 //txpool := common2.SubTxPool{} 276 // 277 ////block := txpool.GenerateBlock(common.Address{},2,true) 278 //blk,_,acctstate,_ := txpool.Execute(common.Address{}) 279 280 //if err := c.ledger.SaveAll(blkInfo); err != nil{ 281 // 282 //} 283 284 return blkInfo.Block, nil 285 } 286 287 func (c *Clique) Seal(block *types.Block, stop <-chan struct{}) (*types.Block, error) { 288 header := block.Header 289 number := header.Height 290 if number == 0 { 291 return nil, errUnknownBlock 292 } 293 294 if c.config.Period == 0 || len(block.Transactions) == 0 { //if c.config.Period == 0 && len(block.Transactions) == 0 { 295 return nil, errWaitTransactions 296 } 297 298 c.lock.RLock() 299 defer c.lock.RUnlock() 300 301 snap, err := c.snapshot(number-1, header.PrevBlockHash) 302 if err != nil { 303 return nil, err 304 } 305 306 if _, authorized := snap.Signers[c.account.Address()]; !authorized { 307 return nil, errUnauthorized 308 } 309 for seen, recent := range snap.Recents { 310 if recent == c.account.Address() { 311 if limit := uint64(len(snap.Signers)/2 + 1); number < limit || seen > number-limit { 312 log.Info("Signed recently, must wait for others") 313 <-stop 314 return nil, nil 315 } 316 } 317 } 318 delay := time.Unix(0, int64(header.Timestamp)).Sub(time.Now()) 319 //if header.Difficulty.Cmp(diffNoTurn) == 0 { 320 // wiggle := time.Duration(len(snap.Signers)/2+1) * wiggleTime 321 // delay += time.Duration(rand.Int63n(int64(wiggle))) 322 // 323 // log.Trace("Out-of-turn signing requested", "wiggle", wiggle) 324 //} 325 log.Info("Waiting for slot to sign and propagate", "delay", delay) 326 select { 327 case <-stop: 328 return nil, nil 329 case <-time.After(delay): 330 } 331 //time.Sleep(time.Duration(rand.Int63n(int64(10)))) 332 aa := sigHash(header) 333 sighash, err := c.account.Sign(aa[:]) 334 if err != nil { 335 fmt.Println(">>>sigFn err", err, time.Now().String()) 336 return nil, err 337 } 338 copy(header.Extra, sighash) 339 return block, nil 340 }