github.com/bloxroute-labs/bor@v0.1.4/consensus/bor/bor.go (about) 1 package bor 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/hex" 7 "encoding/json" 8 "errors" 9 "fmt" 10 "io" 11 "math" 12 "math/big" 13 "net/http" 14 "sort" 15 "strconv" 16 "strings" 17 "sync" 18 "time" 19 20 ethereum "github.com/maticnetwork/bor" 21 "github.com/maticnetwork/bor/accounts" 22 "github.com/maticnetwork/bor/accounts/abi" 23 "github.com/maticnetwork/bor/common" 24 "github.com/maticnetwork/bor/common/hexutil" 25 "github.com/maticnetwork/bor/consensus" 26 "github.com/maticnetwork/bor/consensus/misc" 27 "github.com/maticnetwork/bor/core" 28 "github.com/maticnetwork/bor/core/state" 29 "github.com/maticnetwork/bor/core/types" 30 "github.com/maticnetwork/bor/core/vm" 31 "github.com/maticnetwork/bor/crypto" 32 "github.com/maticnetwork/bor/ethdb" 33 "github.com/maticnetwork/bor/internal/ethapi" 34 "github.com/maticnetwork/bor/log" 35 "github.com/maticnetwork/bor/params" 36 "github.com/maticnetwork/bor/rlp" 37 "github.com/maticnetwork/bor/rpc" 38 39 lru "github.com/hashicorp/golang-lru" 40 "golang.org/x/crypto/sha3" 41 ) 42 43 const validatorsetABI = `[{"constant":true,"inputs":[{"name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"name":"number","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"name":"","type":"address[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"span","type":"uint256"},{"name":"signer","type":"address"}],"name":"isProducer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newSpan","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"endBlock","type":"uint256"},{"name":"validatorBytes","type":"bytes"},{"name":"producerBytes","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"span","type":"uint256"},{"name":"signer","type":"address"}],"name":"isValidator","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"proposeSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"name":"number","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"name":"","type":"address[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"spanProposalPending","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"name":"number","type":"uint256"},{"name":"startBlock","type":"uint256"},{"name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"name":"","type":"address[]"},{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"vote","type":"bytes"},{"name":"sigs","type":"bytes"},{"name":"txBytes","type":"bytes"},{"name":"proof","type":"bytes"}],"name":"validateValidatorSet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]` 44 const stateReceiverABI = `[{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"states","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"recordBytes","type":"bytes"}],"name":"commitState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getPendingStates","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"validatorSet","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"vote","type":"bytes"},{"name":"sigs","type":"bytes"},{"name":"txBytes","type":"bytes"},{"name":"proof","type":"bytes"}],"name":"validateValidatorSet","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isValidatorSetContract","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"stateId","type":"uint256"}],"name":"proposeState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"signer","type":"address"}],"name":"isProducer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"signer","type":"address"}],"name":"isValidator","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}]` 45 46 const ( 47 checkpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database 48 inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory 49 inmemorySignatures = 4096 // Number of recent block signatures to keep in memory 50 51 wiggleTime = 5000 * time.Millisecond // Random delay (per signer) to allow concurrent signers 52 ) 53 54 // Bor protocol constants. 55 var ( 56 defaultSprintLength = uint64(64) // Default number of blocks after which to checkpoint and reset the pending votes 57 58 extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity 59 extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal 60 61 uncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW. 62 63 diffInTurn = big.NewInt(2) // Block difficulty for in-turn signatures 64 diffNoTurn = big.NewInt(1) // Block difficulty for out-of-turn signatures 65 66 validatorHeaderBytesLength = common.AddressLength + 20 // address + power 67 systemAddress = common.HexToAddress("0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE") 68 ) 69 70 // Various error messages to mark blocks invalid. These should be private to 71 // prevent engine specific errors from being referenced in the remainder of the 72 // codebase, inherently breaking if the engine is swapped out. Please put common 73 // error types into the consensus package. 74 var ( 75 // errUnknownBlock is returned when the list of signers is requested for a block 76 // that is not part of the local blockchain. 77 errUnknownBlock = errors.New("unknown block") 78 79 // errInvalidCheckpointBeneficiary is returned if a checkpoint/epoch transition 80 // block has a beneficiary set to non-zeroes. 81 errInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero") 82 83 // errInvalidVote is returned if a nonce value is something else that the two 84 // allowed constants of 0x00..0 or 0xff..f. 85 errInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f") 86 87 // errInvalidCheckpointVote is returned if a checkpoint/epoch transition block 88 // has a vote nonce set to non-zeroes. 89 errInvalidCheckpointVote = errors.New("vote nonce in checkpoint block non-zero") 90 91 // errMissingVanity is returned if a block's extra-data section is shorter than 92 // 32 bytes, which is required to store the signer vanity. 93 errMissingVanity = errors.New("extra-data 32 byte vanity prefix missing") 94 95 // errMissingSignature is returned if a block's extra-data section doesn't seem 96 // to contain a 65 byte secp256k1 signature. 97 errMissingSignature = errors.New("extra-data 65 byte signature suffix missing") 98 99 // errExtraValidators is returned if non-sprint-end block contain validator data in 100 // their extra-data fields. 101 errExtraValidators = errors.New("non-sprint-end block contains extra validator list") 102 103 // errInvalidSpanValidators is returned if a block contains an 104 // invalid list of validators (i.e. non divisible by 40 bytes). 105 errInvalidSpanValidators = errors.New("invalid validator list on sprint end block") 106 107 // errMismatchingSprintValidators is returned if a sprint block contains a 108 // list of validators different than the one the local node calculated. 109 errMismatchingSprintValidators = errors.New("mismatching validator list on sprint block") 110 111 // errInvalidMixDigest is returned if a block's mix digest is non-zero. 112 errInvalidMixDigest = errors.New("non-zero mix digest") 113 114 // errInvalidUncleHash is returned if a block contains an non-empty uncle list. 115 errInvalidUncleHash = errors.New("non empty uncle hash") 116 117 // errInvalidDifficulty is returned if the difficulty of a block neither 1 or 2. 118 errInvalidDifficulty = errors.New("invalid difficulty") 119 120 // errWrongDifficulty is returned if the difficulty of a block doesn't match the 121 // turn of the signer. 122 errWrongDifficulty = errors.New("wrong difficulty") 123 124 // ErrInvalidTimestamp is returned if the timestamp of a block is lower than 125 // the previous block's timestamp + the minimum block period. 126 ErrInvalidTimestamp = errors.New("invalid timestamp") 127 128 // errOutOfRangeChain is returned if an authorization list is attempted to 129 // be modified via out-of-range or non-contiguous headers. 130 errOutOfRangeChain = errors.New("out of range or non-contiguous chain") 131 132 // errUnauthorizedSigner is returned if a header is signed by a non-authorized entity. 133 errUnauthorizedSigner = errors.New("unauthorized signer") 134 135 // errRecentlySigned is returned if a header is signed by an authorized entity 136 // that already signed a header recently, thus is temporarily not allowed to. 137 errRecentlySigned = errors.New("recently signed") 138 ) 139 140 // SignerFn is a signer callback function to request a header to be signed by a 141 // backing account. 142 type SignerFn func(accounts.Account, string, []byte) ([]byte, error) 143 144 // ecrecover extracts the Ethereum account address from a signed header. 145 func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { 146 // If the signature's already cached, return that 147 hash := header.Hash() 148 if address, known := sigcache.Get(hash); known { 149 return address.(common.Address), nil 150 } 151 // Retrieve the signature from the header extra-data 152 if len(header.Extra) < extraSeal { 153 return common.Address{}, errMissingSignature 154 } 155 signature := header.Extra[len(header.Extra)-extraSeal:] 156 157 // Recover the public key and the Ethereum address 158 pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature) 159 if err != nil { 160 return common.Address{}, err 161 } 162 var signer common.Address 163 copy(signer[:], crypto.Keccak256(pubkey[1:])[12:]) 164 165 sigcache.Add(hash, signer) 166 return signer, nil 167 } 168 169 // SealHash returns the hash of a block prior to it being sealed. 170 func SealHash(header *types.Header) (hash common.Hash) { 171 hasher := sha3.NewLegacyKeccak256() 172 encodeSigHeader(hasher, header) 173 hasher.Sum(hash[:0]) 174 return hash 175 } 176 177 func encodeSigHeader(w io.Writer, header *types.Header) { 178 err := rlp.Encode(w, []interface{}{ 179 header.ParentHash, 180 header.UncleHash, 181 header.Coinbase, 182 header.Root, 183 header.TxHash, 184 header.ReceiptHash, 185 header.Bloom, 186 header.Difficulty, 187 header.Number, 188 header.GasLimit, 189 header.GasUsed, 190 header.Time, 191 header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short 192 header.MixDigest, 193 header.Nonce, 194 }) 195 if err != nil { 196 panic("can't encode: " + err.Error()) 197 } 198 } 199 200 // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty 201 // that a new block should have based on the previous blocks in the chain and the 202 // current signer. 203 func CalcDifficulty(snap *Snapshot, signer common.Address, epoch uint64) *big.Int { 204 return big.NewInt(0).SetUint64(snap.inturn(snap.Number+1, signer, epoch)) 205 } 206 207 // CalcProducerDelay is the producer delay algorithm based on block time. 208 func CalcProducerDelay(snap *Snapshot, signer common.Address, period uint64, epoch uint64, producerDelay uint64) uint64 { 209 // if block is epoch start block, proposer will be inturn signer 210 if (snap.Number+1)%epoch == 0 { 211 return producerDelay 212 } 213 214 return period 215 } 216 217 // BorRLP returns the rlp bytes which needs to be signed for the bor 218 // sealing. The RLP to sign consists of the entire header apart from the 65 byte signature 219 // contained at the end of the extra data. 220 // 221 // Note, the method requires the extra data to be at least 65 bytes, otherwise it 222 // panics. This is done to avoid accidentally using both forms (signature present 223 // or not), which could be abused to produce different hashes for the same header. 224 func BorRLP(header *types.Header) []byte { 225 b := new(bytes.Buffer) 226 encodeSigHeader(b, header) 227 return b.Bytes() 228 } 229 230 // Bor is the matic-bor consensus engine 231 type Bor struct { 232 chainConfig *params.ChainConfig // Chain config 233 config *params.BorConfig // Consensus engine configuration parameters for bor consensus 234 db ethdb.Database // Database to store and retrieve snapshot checkpoints 235 236 recents *lru.ARCCache // Snapshots for recent block to speed up reorgs 237 signatures *lru.ARCCache // Signatures of recent blocks to speed up mining 238 239 signer common.Address // Ethereum address of the signing key 240 signFn SignerFn // Signer function to authorize hashes with 241 lock sync.RWMutex // Protects the signer fields 242 243 ethAPI *ethapi.PublicBlockChainAPI 244 validatorSetABI abi.ABI 245 stateReceiverABI abi.ABI 246 httpClient http.Client 247 248 // The fields below are for testing only 249 fakeDiff bool // Skip difficulty verifications 250 } 251 252 // New creates a Matic Bor consensus engine. 253 func New( 254 chainConfig *params.ChainConfig, 255 db ethdb.Database, 256 ethAPI *ethapi.PublicBlockChainAPI, 257 ) *Bor { 258 // get bor config 259 borConfig := chainConfig.Bor 260 261 // Set any missing consensus parameters to their defaults 262 if borConfig != nil && borConfig.Sprint == 0 { 263 borConfig.Sprint = defaultSprintLength 264 } 265 266 // Allocate the snapshot caches and create the engine 267 recents, _ := lru.NewARC(inmemorySnapshots) 268 signatures, _ := lru.NewARC(inmemorySignatures) 269 vABI, _ := abi.JSON(strings.NewReader(validatorsetABI)) 270 sABI, _ := abi.JSON(strings.NewReader(stateReceiverABI)) 271 c := &Bor{ 272 chainConfig: chainConfig, 273 config: borConfig, 274 db: db, 275 ethAPI: ethAPI, 276 recents: recents, 277 signatures: signatures, 278 validatorSetABI: vABI, 279 stateReceiverABI: sABI, 280 httpClient: http.Client{ 281 Timeout: time.Duration(5 * time.Second), 282 }, 283 } 284 285 return c 286 } 287 288 // Author implements consensus.Engine, returning the Ethereum address recovered 289 // from the signature in the header's extra-data section. 290 func (c *Bor) Author(header *types.Header) (common.Address, error) { 291 return ecrecover(header, c.signatures) 292 } 293 294 // VerifyHeader checks whether a header conforms to the consensus rules. 295 func (c *Bor) VerifyHeader(chain consensus.ChainReader, header *types.Header, seal bool) error { 296 return c.verifyHeader(chain, header, nil) 297 } 298 299 // VerifyHeaders is similar to VerifyHeader, but verifies a batch of headers. The 300 // method returns a quit channel to abort the operations and a results channel to 301 // retrieve the async verifications (the order is that of the input slice). 302 func (c *Bor) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, seals []bool) (chan<- struct{}, <-chan error) { 303 abort := make(chan struct{}) 304 results := make(chan error, len(headers)) 305 306 go func() { 307 for i, header := range headers { 308 err := c.verifyHeader(chain, header, headers[:i]) 309 310 select { 311 case <-abort: 312 return 313 case results <- err: 314 } 315 } 316 }() 317 return abort, results 318 } 319 320 // verifyHeader checks whether a header conforms to the consensus rules.The 321 // caller may optionally pass in a batch of parents (ascending order) to avoid 322 // looking those up from the database. This is useful for concurrently verifying 323 // a batch of new headers. 324 func (c *Bor) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 325 if header.Number == nil { 326 return errUnknownBlock 327 } 328 number := header.Number.Uint64() 329 330 // Don't waste time checking blocks from the future 331 if header.Time > uint64(time.Now().Unix()) { 332 return consensus.ErrFutureBlock 333 } 334 // Check that the extra-data contains both the vanity and signature 335 if len(header.Extra) < extraVanity { 336 return errMissingVanity 337 } 338 if len(header.Extra) < extraVanity+extraSeal { 339 return errMissingSignature 340 } 341 342 // check extr adata 343 isSprintEnd := (number+1)%c.config.Sprint == 0 344 345 // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise 346 signersBytes := len(header.Extra) - extraVanity - extraSeal 347 if !isSprintEnd && signersBytes != 0 { 348 return errExtraValidators 349 } 350 if isSprintEnd && signersBytes%validatorHeaderBytesLength != 0 { 351 return errInvalidSpanValidators 352 } 353 // Ensure that the mix digest is zero as we don't have fork protection currently 354 if header.MixDigest != (common.Hash{}) { 355 return errInvalidMixDigest 356 } 357 // Ensure that the block doesn't contain any uncles which are meaningless in PoA 358 if header.UncleHash != uncleHash { 359 return errInvalidUncleHash 360 } 361 // Ensure that the block's difficulty is meaningful (may not be correct at this point) 362 if number > 0 { 363 if header.Difficulty == nil { 364 return errInvalidDifficulty 365 } 366 } 367 // If all checks passed, validate any special fields for hard forks 368 if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil { 369 return err 370 } 371 // All basic checks passed, verify cascading fields 372 return c.verifyCascadingFields(chain, header, parents) 373 } 374 375 // verifyCascadingFields verifies all the header fields that are not standalone, 376 // rather depend on a batch of previous headers. The caller may optionally pass 377 // in a batch of parents (ascending order) to avoid looking those up from the 378 // database. This is useful for concurrently verifying a batch of new headers. 379 func (c *Bor) verifyCascadingFields(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 380 // The genesis block is the always valid dead-end 381 number := header.Number.Uint64() 382 if number == 0 { 383 return nil 384 } 385 386 // Ensure that the block's timestamp isn't too close to it's parent 387 var parent *types.Header 388 if len(parents) > 0 { 389 parent = parents[len(parents)-1] 390 } else { 391 parent = chain.GetHeader(header.ParentHash, number-1) 392 } 393 394 if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash { 395 return consensus.ErrUnknownAncestor 396 } 397 398 if parent.Time+c.config.Period > header.Time { 399 return ErrInvalidTimestamp 400 } 401 402 // Retrieve the snapshot needed to verify this header and cache it 403 snap, err := c.snapshot(chain, number-1, header.ParentHash, parents) 404 if err != nil { 405 return err 406 } 407 408 // If the block is a sprint end block, verify the validator list 409 if number%c.config.Sprint == 0 { 410 validatorsBytes := make([]byte, len(snap.ValidatorSet.Validators)*validatorHeaderBytesLength) 411 412 currentValidators := snap.ValidatorSet.Copy().Validators 413 // sort validator by address 414 sort.Sort(ValidatorsByAddress(currentValidators)) 415 for i, validator := range currentValidators { 416 copy(validatorsBytes[i*validatorHeaderBytesLength:], validator.HeaderBytes()) 417 } 418 419 extraSuffix := len(header.Extra) - extraSeal 420 421 // fmt.Println("validatorsBytes ==> verify seal ==> ", hex.EncodeToString(validatorsBytes)) 422 // fmt.Println("header.Extra ==> verify seal ==> ", hex.EncodeToString(header.Extra[extraVanity:extraSuffix])) 423 424 if !bytes.Equal(header.Extra[extraVanity:extraSuffix], validatorsBytes) { 425 // return errMismatchingSprintValidators 426 } 427 } 428 429 // All basic checks passed, verify the seal and return 430 return c.verifySeal(chain, header, parents) 431 } 432 433 // snapshot retrieves the authorization snapshot at a given point in time. 434 func (c *Bor) snapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { 435 // Search for a snapshot in memory or on disk for checkpoints 436 var ( 437 headers []*types.Header 438 snap *Snapshot 439 ) 440 441 for snap == nil { 442 // If an in-memory snapshot was found, use that 443 if s, ok := c.recents.Get(hash); ok { 444 snap = s.(*Snapshot) 445 break 446 } 447 448 // If an on-disk checkpoint snapshot can be found, use that 449 if number%checkpointInterval == 0 { 450 if s, err := loadSnapshot(c.config, c.signatures, c.db, hash, c.ethAPI); err == nil { 451 log.Trace("Loaded snapshot from disk", "number", number, "hash", hash) 452 snap = s 453 break 454 } 455 } 456 457 // If we're at the genesis, snapshot the initial state. Alternatively if we're 458 // at a checkpoint block without a parent (light client CHT), or we have piled 459 // up more headers than allowed to be reorged (chain reinit from a freezer), 460 // consider the checkpoint trusted and snapshot it. 461 // TODO fix this 462 if number == 0 /* || (number%c.config.Sprint == 0 && (len(headers) > params.ImmutabilityThreshold || chain.GetHeaderByNumber(number-1) == nil)) */ { 463 checkpoint := chain.GetHeaderByNumber(number) 464 if checkpoint != nil { 465 // get checkpoint data 466 hash := checkpoint.Hash() 467 468 // get validators and current span 469 validators, err := c.GetCurrentValidators(number, number+1) 470 if err != nil { 471 return nil, err 472 } 473 474 // new snap shot 475 snap = newSnapshot(c.config, c.signatures, number, hash, validators, c.ethAPI) 476 if err := snap.store(c.db); err != nil { 477 return nil, err 478 } 479 log.Info("Stored checkpoint snapshot to disk", "number", number, "hash", hash) 480 break 481 } 482 } 483 484 // No snapshot for this header, gather the header and move backward 485 var header *types.Header 486 if len(parents) > 0 { 487 // If we have explicit parents, pick from there (enforced) 488 header = parents[len(parents)-1] 489 if header.Hash() != hash || header.Number.Uint64() != number { 490 return nil, consensus.ErrUnknownAncestor 491 } 492 parents = parents[:len(parents)-1] 493 } else { 494 // No explicit parents (or no more left), reach out to the database 495 header = chain.GetHeader(hash, number) 496 if header == nil { 497 return nil, consensus.ErrUnknownAncestor 498 } 499 } 500 headers = append(headers, header) 501 number, hash = number-1, header.ParentHash 502 } 503 504 // check if snapshot is nil 505 if snap == nil { 506 return nil, fmt.Errorf("Unknown error while retrieving snapshot at block number %v", number) 507 } 508 509 // Previous snapshot found, apply any pending headers on top of it 510 for i := 0; i < len(headers)/2; i++ { 511 headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i] 512 } 513 514 snap, err := snap.apply(headers) 515 if err != nil { 516 return nil, err 517 } 518 c.recents.Add(snap.Hash, snap) 519 520 // If we've generated a new checkpoint snapshot, save to disk 521 if snap.Number%checkpointInterval == 0 && len(headers) > 0 { 522 if err = snap.store(c.db); err != nil { 523 return nil, err 524 } 525 log.Trace("Stored snapshot to disk", "number", snap.Number, "hash", snap.Hash) 526 } 527 return snap, err 528 } 529 530 // VerifyUncles implements consensus.Engine, always returning an error for any 531 // uncles as this consensus mechanism doesn't permit uncles. 532 func (c *Bor) VerifyUncles(chain consensus.ChainReader, block *types.Block) error { 533 if len(block.Uncles()) > 0 { 534 return errors.New("uncles not allowed") 535 } 536 return nil 537 } 538 539 // VerifySeal implements consensus.Engine, checking whether the signature contained 540 // in the header satisfies the consensus protocol requirements. 541 func (c *Bor) VerifySeal(chain consensus.ChainReader, header *types.Header) error { 542 return c.verifySeal(chain, header, nil) 543 } 544 545 // verifySeal checks whether the signature contained in the header satisfies the 546 // consensus protocol requirements. The method accepts an optional list of parent 547 // headers that aren't yet part of the local blockchain to generate the snapshots 548 // from. 549 func (c *Bor) verifySeal(chain consensus.ChainReader, header *types.Header, parents []*types.Header) error { 550 // Verifying the genesis block is not supported 551 number := header.Number.Uint64() 552 if number == 0 { 553 return errUnknownBlock 554 } 555 // Retrieve the snapshot needed to verify this header and cache it 556 snap, err := c.snapshot(chain, number-1, header.ParentHash, parents) 557 if err != nil { 558 return err 559 } 560 561 // Resolve the authorization key and check against signers 562 signer, err := ecrecover(header, c.signatures) 563 if err != nil { 564 return err 565 } 566 567 if !snap.ValidatorSet.HasAddress(signer.Bytes()) { 568 return errUnauthorizedSigner 569 } 570 571 // check if signer is correct 572 validators := snap.ValidatorSet.Validators 573 // proposer will be the last signer if block is not epoch block 574 proposer := snap.ValidatorSet.GetProposer().Address 575 if number%c.config.Sprint != 0 { 576 // proposer = snap.Recents[number-1] 577 } 578 proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer) 579 signerIndex, _ := snap.ValidatorSet.GetByAddress(signer) 580 limit := len(validators)/2 + 1 581 582 // temp index 583 tempIndex := signerIndex 584 if proposerIndex != tempIndex && limit > 0 { 585 if tempIndex < proposerIndex { 586 tempIndex = tempIndex + len(validators) 587 } 588 589 if tempIndex-proposerIndex > limit { 590 return errRecentlySigned 591 } 592 } 593 594 // Ensure that the difficulty corresponds to the turn-ness of the signer 595 if !c.fakeDiff { 596 difficulty := snap.inturn(header.Number.Uint64(), signer, c.config.Sprint) 597 if header.Difficulty.Uint64() != difficulty { 598 return errWrongDifficulty 599 } 600 } 601 602 return nil 603 } 604 605 // Prepare implements consensus.Engine, preparing all the consensus fields of the 606 // header for running the transactions on top. 607 func (c *Bor) Prepare(chain consensus.ChainReader, header *types.Header) error { 608 // If the block isn't a checkpoint, cast a random vote (good enough for now) 609 header.Coinbase = common.Address{} 610 header.Nonce = types.BlockNonce{} 611 612 number := header.Number.Uint64() 613 // Assemble the validator snapshot to check which votes make sense 614 snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) 615 if err != nil { 616 return err 617 } 618 619 // Set the correct difficulty 620 header.Difficulty = CalcDifficulty(snap, c.signer, c.config.Sprint) 621 622 // Ensure the extra data has all it's components 623 if len(header.Extra) < extraVanity { 624 header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...) 625 } 626 header.Extra = header.Extra[:extraVanity] 627 628 // get validator set if number 629 if (number+1)%c.config.Sprint == 0 { 630 newValidators, err := c.GetCurrentValidators(snap.Number, number+1) 631 if err != nil { 632 return errors.New("unknown validators") 633 } 634 635 // sort validator by address 636 sort.Sort(ValidatorsByAddress(newValidators)) 637 for _, validator := range newValidators { 638 header.Extra = append(header.Extra, validator.HeaderBytes()...) 639 } 640 } 641 642 // add extra seal space 643 header.Extra = append(header.Extra, make([]byte, extraSeal)...) 644 645 // Mix digest is reserved for now, set to empty 646 header.MixDigest = common.Hash{} 647 648 // Ensure the timestamp has the correct delay 649 parent := chain.GetHeader(header.ParentHash, number-1) 650 if parent == nil { 651 return consensus.ErrUnknownAncestor 652 } 653 654 header.Time = parent.Time + CalcProducerDelay(snap, c.signer, c.config.Period, c.config.Sprint, c.config.ProducerDelay) 655 if header.Time < uint64(time.Now().Unix()) { 656 header.Time = uint64(time.Now().Unix()) 657 } 658 return nil 659 } 660 661 // Finalize implements consensus.Engine, ensuring no uncles are set, nor block 662 // rewards given. 663 func (c *Bor) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header) { 664 // commit span 665 if header.Number.Uint64()%c.config.Sprint == 0 { 666 cx := chainContext{Chain: chain, Bor: c} 667 668 // check and commit span 669 if err := c.checkAndCommitSpan(state, header, cx); err != nil { 670 log.Error("Error while committing span", "error", err) 671 return 672 } 673 674 // commit statees 675 if err := c.CommitStates(state, header, cx); err != nil { 676 log.Error("Error while committing states", "error", err) 677 return 678 } 679 } 680 681 // No block rewards in PoA, so the state remains as is and uncles are dropped 682 header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 683 header.UncleHash = types.CalcUncleHash(nil) 684 } 685 686 // FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, 687 // nor block rewards given, and returns the final block. 688 func (c *Bor) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) { 689 // commit span 690 if header.Number.Uint64()%c.config.Sprint == 0 { 691 cx := chainContext{Chain: chain, Bor: c} 692 693 // check and commit span 694 err := c.checkAndCommitSpan(state, header, cx) 695 if err != nil { 696 log.Error("Error while committing span", "error", err) 697 return nil, err 698 } 699 700 // commit statees 701 if err := c.CommitStates(state, header, cx); err != nil { 702 log.Error("Error while committing states", "error", err) 703 // return nil, err 704 } 705 } 706 707 // No block rewards in PoA, so the state remains as is and uncles are dropped 708 header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) 709 header.UncleHash = types.CalcUncleHash(nil) 710 711 // Assemble and return the final block for sealing 712 return types.NewBlock(header, txs, nil, receipts), nil 713 } 714 715 // Authorize injects a private key into the consensus engine to mint new blocks 716 // with. 717 func (c *Bor) Authorize(signer common.Address, signFn SignerFn) { 718 c.lock.Lock() 719 defer c.lock.Unlock() 720 721 c.signer = signer 722 c.signFn = signFn 723 } 724 725 // Seal implements consensus.Engine, attempting to create a sealed block using 726 // the local signing credentials. 727 func (c *Bor) Seal(chain consensus.ChainReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { 728 header := block.Header() 729 730 // Sealing the genesis block is not supported 731 number := header.Number.Uint64() 732 if number == 0 { 733 return errUnknownBlock 734 } 735 // For 0-period chains, refuse to seal empty blocks (no reward but would spin sealing) 736 if c.config.Period == 0 && len(block.Transactions()) == 0 { 737 log.Info("Sealing paused, waiting for transactions") 738 return nil 739 } 740 // Don't hold the signer fields for the entire sealing procedure 741 c.lock.RLock() 742 signer, signFn := c.signer, c.signFn 743 c.lock.RUnlock() 744 745 snap, err := c.snapshot(chain, number-1, header.ParentHash, nil) 746 if err != nil { 747 return err 748 } 749 750 // Bail out if we're unauthorized to sign a block 751 if !snap.ValidatorSet.HasAddress(signer.Bytes()) { 752 return errUnauthorizedSigner 753 } 754 755 validators := snap.ValidatorSet.Validators 756 // proposer will be the last signer if block is not epoch block 757 proposer := snap.ValidatorSet.GetProposer().Address 758 if number%c.config.Sprint != 0 { 759 // proposer = snap.Recents[number-1] 760 } 761 762 proposerIndex, _ := snap.ValidatorSet.GetByAddress(proposer) 763 signerIndex, _ := snap.ValidatorSet.GetByAddress(signer) 764 limit := len(validators)/2 + 1 765 766 // temp index 767 tempIndex := signerIndex 768 if tempIndex < proposerIndex { 769 tempIndex = tempIndex + len(validators) 770 } 771 772 if limit > 0 && tempIndex-proposerIndex > limit { 773 log.Info("Signed recently, must wait for others") 774 return nil 775 } 776 777 // Sweet, the protocol permits us to sign the block, wait for our time 778 delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple 779 wiggle := time.Duration(2*c.config.Period) * time.Second * time.Duration(tempIndex-proposerIndex) 780 delay += wiggle 781 782 log.Info("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) 783 log.Info("Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "signer", signer.Hex(), "proposer", proposer.Hex()) 784 785 // Sign all the things! 786 sighash, err := signFn(accounts.Account{Address: signer}, accounts.MimetypeBor, BorRLP(header)) 787 if err != nil { 788 return err 789 } 790 copy(header.Extra[len(header.Extra)-extraSeal:], sighash) 791 792 // Wait until sealing is terminated or delay timeout. 793 log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay)) 794 go func() { 795 select { 796 case <-stop: 797 return 798 case <-time.After(delay): 799 } 800 801 select { 802 case results <- block.WithSeal(header): 803 default: 804 log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header)) 805 } 806 }() 807 808 return nil 809 } 810 811 // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty 812 // that a new block should have based on the previous blocks in the chain and the 813 // current signer. 814 func (c *Bor) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { 815 snap, err := c.snapshot(chain, parent.Number.Uint64(), parent.Hash(), nil) 816 if err != nil { 817 return nil 818 } 819 return CalcDifficulty(snap, c.signer, c.config.Sprint) 820 } 821 822 // SealHash returns the hash of a block prior to it being sealed. 823 func (c *Bor) SealHash(header *types.Header) common.Hash { 824 return SealHash(header) 825 } 826 827 // APIs implements consensus.Engine, returning the user facing RPC API to allow 828 // controlling the signer voting. 829 func (c *Bor) APIs(chain consensus.ChainReader) []rpc.API { 830 return []rpc.API{{ 831 Namespace: "bor", 832 Version: "1.0", 833 Service: &API{chain: chain, bor: c}, 834 Public: false, 835 }} 836 } 837 838 // Close implements consensus.Engine. It's a noop for bor as there are no background threads. 839 func (c *Bor) Close() error { 840 return nil 841 } 842 843 // Checks if new span is pending 844 func (c *Bor) isSpanPending(snapshotNumber uint64) (bool, error) { 845 blockNr := rpc.BlockNumber(snapshotNumber) 846 method := "spanProposalPending" 847 848 // get packed data 849 data, err := c.validatorSetABI.Pack(method) 850 if err != nil { 851 log.Error("Unable to pack tx for spanProposalPending", "error", err) 852 return false, err 853 } 854 855 ctx, cancel := context.WithCancel(context.Background()) 856 defer cancel() // cancel when we are finished consuming integers 857 858 // call 859 msgData := (hexutil.Bytes)(data) 860 toAddress := common.HexToAddress(c.config.ValidatorContract) 861 gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) 862 result, err := c.ethAPI.Call(ctx, ethapi.CallArgs{ 863 Gas: &gas, 864 To: &toAddress, 865 Data: &msgData, 866 }, blockNr) 867 if err != nil { 868 return false, err 869 } 870 871 var ret0 = new(bool) 872 if err := c.validatorSetABI.Unpack(ret0, method, result); err != nil { 873 return false, err 874 } 875 876 return *ret0, nil 877 } 878 879 // GetCurrentSpan get current span from contract 880 func (c *Bor) GetCurrentSpan(snapshotNumber uint64) (*Span, error) { 881 // block 882 blockNr := rpc.BlockNumber(snapshotNumber) 883 884 // method 885 method := "getCurrentSpan" 886 887 data, err := c.validatorSetABI.Pack(method) 888 if err != nil { 889 log.Error("Unable to pack tx for getCurrentSpan", "error", err) 890 return nil, err 891 } 892 893 ctx, cancel := context.WithCancel(context.Background()) 894 defer cancel() // cancel when we are finished consuming integers 895 896 // call 897 msgData := (hexutil.Bytes)(data) 898 toAddress := common.HexToAddress(c.config.ValidatorContract) 899 gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) 900 result, err := c.ethAPI.Call(ctx, ethapi.CallArgs{ 901 Gas: &gas, 902 To: &toAddress, 903 Data: &msgData, 904 }, blockNr) 905 if err != nil { 906 return nil, err 907 } 908 909 // span result 910 ret := new(struct { 911 Number *big.Int 912 StartBlock *big.Int 913 EndBlock *big.Int 914 }) 915 if err := c.validatorSetABI.Unpack(ret, method, result); err != nil { 916 return nil, err 917 } 918 919 // create new span 920 span := Span{ 921 ID: ret.Number.Uint64(), 922 StartBlock: ret.StartBlock.Uint64(), 923 EndBlock: ret.EndBlock.Uint64(), 924 } 925 926 return &span, nil 927 } 928 929 // GetCurrentValidators get current validators 930 func (c *Bor) GetCurrentValidators(snapshotNumber uint64, blockNumber uint64) ([]*Validator, error) { 931 // block 932 blockNr := rpc.BlockNumber(snapshotNumber) 933 934 // method 935 method := "getBorValidators" 936 937 data, err := c.validatorSetABI.Pack(method, big.NewInt(0).SetUint64(blockNumber)) 938 if err != nil { 939 log.Error("Unable to pack tx for getValidator", "error", err) 940 return nil, err 941 } 942 943 ctx, cancel := context.WithCancel(context.Background()) 944 defer cancel() // cancel when we are finished consuming integers 945 946 // call 947 msgData := (hexutil.Bytes)(data) 948 toAddress := common.HexToAddress(c.config.ValidatorContract) 949 gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) 950 result, err := c.ethAPI.Call(ctx, ethapi.CallArgs{ 951 Gas: &gas, 952 To: &toAddress, 953 Data: &msgData, 954 }, blockNr) 955 if err != nil { 956 panic(err) 957 // return nil, err 958 } 959 960 var ( 961 ret0 = new([]common.Address) 962 ret1 = new([]*big.Int) 963 ) 964 out := &[]interface{}{ 965 ret0, 966 ret1, 967 } 968 969 if err := c.validatorSetABI.Unpack(out, method, result); err != nil { 970 return nil, err 971 } 972 973 valz := make([]*Validator, len(*ret0)) 974 for i, a := range *ret0 { 975 valz[i] = &Validator{ 976 Address: a, 977 VotingPower: (*ret1)[i].Int64(), 978 } 979 } 980 981 return valz, nil 982 } 983 984 func (c *Bor) checkAndCommitSpan( 985 state *state.StateDB, 986 header *types.Header, 987 chain core.ChainContext, 988 ) error { 989 pending := false 990 var span *Span = nil 991 var wg sync.WaitGroup 992 wg.Add(1) 993 go func() { 994 pending, _ = c.isSpanPending(header.Number.Uint64()) 995 wg.Done() 996 }() 997 998 wg.Add(1) 999 go func() { 1000 span, _ = c.GetCurrentSpan(header.Number.Uint64() - 1) 1001 wg.Done() 1002 }() 1003 1004 wg.Wait() 1005 1006 // commit span if there is new span pending or span is ending or end block is not set 1007 if pending || c.needToCommitSpan(span, header) { 1008 err := c.commitSpan(span, state, header, chain) 1009 return err 1010 } 1011 1012 return nil 1013 } 1014 1015 func (c *Bor) needToCommitSpan(span *Span, header *types.Header) bool { 1016 // if span is nil 1017 if span == nil { 1018 return false 1019 } 1020 1021 // check span is not set initially 1022 if span.EndBlock == 0 { 1023 return true 1024 } 1025 1026 // if current block is first block of last sprint in current span 1027 h := header.Number.Uint64() 1028 if span.EndBlock > c.config.Sprint && span.EndBlock-c.config.Sprint+1 == h { 1029 return true 1030 } 1031 1032 return false 1033 } 1034 1035 func (c *Bor) commitSpan( 1036 span *Span, 1037 state *state.StateDB, 1038 header *types.Header, 1039 chain core.ChainContext, 1040 ) error { 1041 response, err := FetchFromHeimdallWithRetry(c.httpClient, c.chainConfig.Bor.Heimdall, "bor", "span", strconv.FormatUint(span.ID+1, 10)) 1042 if err != nil { 1043 return err 1044 } 1045 1046 var heimdallSpan HeimdallSpan 1047 if err := json.Unmarshal(response.Result, &heimdallSpan); err != nil { 1048 return err 1049 } 1050 1051 // check if chain id matches with heimdall span 1052 if heimdallSpan.ChainID != c.chainConfig.ChainID.String() { 1053 return fmt.Errorf( 1054 "Chain id proposed span, %s, and bor chain id, %s, doesn't match", 1055 heimdallSpan.ChainID, 1056 c.chainConfig.ChainID, 1057 ) 1058 } 1059 1060 // get validators bytes 1061 var validators []MinimalVal 1062 for _, val := range heimdallSpan.ValidatorSet.Validators { 1063 validators = append(validators, val.MinimalVal()) 1064 } 1065 validatorBytes, err := rlp.EncodeToBytes(validators) 1066 if err != nil { 1067 return err 1068 } 1069 1070 // get producers bytes 1071 var producers []MinimalVal 1072 for _, val := range heimdallSpan.SelectedProducers { 1073 producers = append(producers, val.MinimalVal()) 1074 } 1075 producerBytes, err := rlp.EncodeToBytes(producers) 1076 if err != nil { 1077 return err 1078 } 1079 1080 // method 1081 method := "commitSpan" 1082 log.Info("✅ Committing new span", 1083 "id", heimdallSpan.ID, 1084 "startBlock", heimdallSpan.StartBlock, 1085 "endBlock", heimdallSpan.EndBlock, 1086 "validatorBytes", hex.EncodeToString(validatorBytes), 1087 "producerBytes", hex.EncodeToString(producerBytes), 1088 ) 1089 1090 // get packed data 1091 data, err := c.validatorSetABI.Pack(method, 1092 big.NewInt(0).SetUint64(heimdallSpan.ID), 1093 big.NewInt(0).SetUint64(heimdallSpan.StartBlock), 1094 big.NewInt(0).SetUint64(heimdallSpan.EndBlock), 1095 validatorBytes, 1096 producerBytes, 1097 ) 1098 if err != nil { 1099 log.Error("Unable to pack tx for commitSpan", "error", err) 1100 return err 1101 } 1102 1103 // get system message 1104 msg := getSystemMessage(common.HexToAddress(c.config.ValidatorContract), data) 1105 1106 // apply message 1107 return applyMessage(msg, state, header, c.chainConfig, chain) 1108 } 1109 1110 // GetPendingStateProposals get pending state proposals 1111 func (c *Bor) GetPendingStateProposals(snapshotNumber uint64) ([]*big.Int, error) { 1112 // block 1113 blockNr := rpc.BlockNumber(snapshotNumber) 1114 1115 // method 1116 method := "getPendingStates" 1117 1118 data, err := c.stateReceiverABI.Pack(method) 1119 if err != nil { 1120 log.Error("Unable to pack tx for getPendingStates", "error", err) 1121 return nil, err 1122 } 1123 1124 ctx, cancel := context.WithCancel(context.Background()) 1125 defer cancel() // cancel when we are finished consuming integers 1126 1127 msgData := (hexutil.Bytes)(data) 1128 toAddress := common.HexToAddress(c.config.StateReceiverContract) 1129 gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2)) 1130 result, err := c.ethAPI.Call(ctx, ethapi.CallArgs{ 1131 Gas: &gas, 1132 To: &toAddress, 1133 Data: &msgData, 1134 }, blockNr) 1135 if err != nil { 1136 return nil, err 1137 } 1138 1139 var ret = new([]*big.Int) 1140 if err := c.stateReceiverABI.Unpack(ret, method, result); err != nil { 1141 return nil, err 1142 } 1143 1144 return *ret, nil 1145 } 1146 1147 // CommitStates commit states 1148 func (c *Bor) CommitStates( 1149 state *state.StateDB, 1150 header *types.Header, 1151 chain core.ChainContext, 1152 ) error { 1153 // get pending state proposals 1154 stateIds, err := c.GetPendingStateProposals(header.Number.Uint64() - 1) 1155 if err != nil { 1156 return err 1157 } 1158 1159 // state ids 1160 if len(stateIds) > 0 { 1161 log.Debug("Found new proposed states", "numberOfStates", len(stateIds)) 1162 } 1163 1164 method := "commitState" 1165 1166 // itereate through state ids 1167 for _, stateID := range stateIds { 1168 // fetch from heimdall 1169 response, err := FetchFromHeimdallWithRetry(c.httpClient, c.chainConfig.Bor.Heimdall, "clerk", "event-record", strconv.FormatUint(stateID.Uint64(), 10)) 1170 if err != nil { 1171 return err 1172 } 1173 1174 // get event record 1175 var eventRecord EventRecord 1176 if err := json.Unmarshal(response.Result, &eventRecord); err != nil { 1177 return err 1178 } 1179 1180 // check if chain id matches with event record 1181 if eventRecord.ChainID != "" && eventRecord.ChainID != c.chainConfig.ChainID.String() { 1182 return fmt.Errorf( 1183 "Chain id proposed state in span, %s, and bor chain id, %s, doesn't match", 1184 eventRecord.ChainID, 1185 c.chainConfig.ChainID, 1186 ) 1187 } 1188 1189 log.Info("→ committing new state", 1190 "id", eventRecord.ID, 1191 "contract", eventRecord.Contract, 1192 "data", hex.EncodeToString(eventRecord.Data), 1193 "txHash", eventRecord.TxHash, 1194 "chainID", eventRecord.ChainID, 1195 ) 1196 1197 recordBytes, err := rlp.EncodeToBytes(eventRecord) 1198 if err != nil { 1199 return err 1200 } 1201 1202 // get packed data for commit state 1203 data, err := c.stateReceiverABI.Pack(method, recordBytes) 1204 if err != nil { 1205 log.Error("Unable to pack tx for commitState", "error", err) 1206 return err 1207 } 1208 1209 // get system message 1210 msg := getSystemMessage(common.HexToAddress(c.config.StateReceiverContract), data) 1211 1212 // apply message 1213 if err := applyMessage(msg, state, header, c.chainConfig, chain); err != nil { 1214 return err 1215 } 1216 } 1217 1218 return nil 1219 } 1220 1221 // 1222 // Private methods 1223 // 1224 1225 // 1226 // Chain context 1227 // 1228 1229 // chain context 1230 type chainContext struct { 1231 Chain consensus.ChainReader 1232 Bor consensus.Engine 1233 } 1234 1235 func (c chainContext) Engine() consensus.Engine { 1236 return c.Bor 1237 } 1238 1239 func (c chainContext) GetHeader(hash common.Hash, number uint64) *types.Header { 1240 return c.Chain.GetHeader(hash, number) 1241 } 1242 1243 // callmsg implements core.Message to allow passing it as a transaction simulator. 1244 type callmsg struct { 1245 ethereum.CallMsg 1246 } 1247 1248 func (m callmsg) From() common.Address { return m.CallMsg.From } 1249 func (m callmsg) Nonce() uint64 { return 0 } 1250 func (m callmsg) CheckNonce() bool { return false } 1251 func (m callmsg) To() *common.Address { return m.CallMsg.To } 1252 func (m callmsg) GasPrice() *big.Int { return m.CallMsg.GasPrice } 1253 func (m callmsg) Gas() uint64 { return m.CallMsg.Gas } 1254 func (m callmsg) Value() *big.Int { return m.CallMsg.Value } 1255 func (m callmsg) Data() []byte { return m.CallMsg.Data } 1256 1257 // get system message 1258 func getSystemMessage(toAddress common.Address, data []byte) callmsg { 1259 return callmsg{ 1260 ethereum.CallMsg{ 1261 From: systemAddress, 1262 Gas: math.MaxUint64 / 2, 1263 GasPrice: big.NewInt(0), 1264 Value: big.NewInt(0), 1265 To: &toAddress, 1266 Data: data, 1267 }, 1268 } 1269 } 1270 1271 // apply message 1272 func applyMessage( 1273 msg callmsg, 1274 state *state.StateDB, 1275 header *types.Header, 1276 chainConfig *params.ChainConfig, 1277 chainContext core.ChainContext, 1278 ) error { 1279 // Create a new context to be used in the EVM environment 1280 context := core.NewEVMContext(msg, header, chainContext, &header.Coinbase) 1281 // Create a new environment which holds all relevant information 1282 // about the transaction and calling mechanisms. 1283 vmenv := vm.NewEVM(context, state, chainConfig, vm.Config{}) 1284 // Apply the transaction to the current state (included in the env) 1285 _, _, err := vmenv.Call( 1286 vm.AccountRef(msg.From()), 1287 *msg.To(), 1288 msg.Data(), 1289 msg.Gas(), 1290 msg.Value(), 1291 ) 1292 // Update the state with pending changes 1293 if err != nil { 1294 state.Finalise(true) 1295 } 1296 1297 return nil 1298 } 1299 1300 func validatorContains(a []*Validator, x *Validator) (*Validator, bool) { 1301 for _, n := range a { 1302 if bytes.Compare(n.Address.Bytes(), x.Address.Bytes()) == 0 { 1303 return n, true 1304 } 1305 } 1306 return nil, false 1307 } 1308 1309 func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*Validator) *ValidatorSet { 1310 v := oldValidatorSet 1311 oldVals := v.Validators 1312 1313 var changes []*Validator 1314 for _, ov := range oldVals { 1315 if f, ok := validatorContains(newVals, ov); ok { 1316 ov.VotingPower = f.VotingPower 1317 } else { 1318 ov.VotingPower = 0 1319 } 1320 1321 changes = append(changes, ov) 1322 } 1323 1324 for _, nv := range newVals { 1325 if _, ok := validatorContains(changes, nv); !ok { 1326 changes = append(changes, nv) 1327 } 1328 } 1329 1330 v.UpdateWithChangeSet(changes) 1331 return v 1332 }