diff options
author | Martin Holst Swende <martin@swende.se> | 2019-02-05 18:23:57 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-05 18:23:57 +0800 |
commit | 43e8efe8955b8bb1fab7bfced33a6302fb69e48e (patch) | |
tree | 3db96494c913b31be950f5580bf49a82141b9255 /consensus | |
parent | 520024dfd689d264807b7fe1fc28deba51d6ab20 (diff) | |
download | go-tangerine-43e8efe8955b8bb1fab7bfced33a6302fb69e48e.tar go-tangerine-43e8efe8955b8bb1fab7bfced33a6302fb69e48e.tar.gz go-tangerine-43e8efe8955b8bb1fab7bfced33a6302fb69e48e.tar.bz2 go-tangerine-43e8efe8955b8bb1fab7bfced33a6302fb69e48e.tar.lz go-tangerine-43e8efe8955b8bb1fab7bfced33a6302fb69e48e.tar.xz go-tangerine-43e8efe8955b8bb1fab7bfced33a6302fb69e48e.tar.zst go-tangerine-43e8efe8955b8bb1fab7bfced33a6302fb69e48e.zip |
accounts, eth, clique, signer: support for external signer API (#18079)
* accounts, eth, clique: implement external backend + move sighash calc to backend
* signer: implement account_Version on external API
* accounts/external: enable ipc, add copyright
* accounts, internal, signer: formatting
* node: go fmt
* flags: disallow --dev in combo with --externalsigner
* accounts: remove clique-specific signing method, replace with more generic
* accounts, consensus: formatting + fix error in tests
* signer/core: remove (test-) import cycle
* clique: remove unused import
* accounts: remove CliqueHash and avoid dependency on package crypto
* consensus/clique: unduplicate header encoding
Diffstat (limited to 'consensus')
-rw-r--r-- | consensus/clique/clique.go | 88 | ||||
-rw-r--r-- | consensus/clique/snapshot_test.go | 2 |
2 files changed, 52 insertions, 38 deletions
diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index c79c30cae..c0f78ce65 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -20,6 +20,7 @@ package clique import ( "bytes" "errors" + "io" "math/big" "math/rand" "sync" @@ -136,40 +137,9 @@ var ( errRecentlySigned = errors.New("recently signed") ) -// SignerFn is a signer callback function to request a hash to be signed by a +// SignerFn is a signer callback function to request a header to be signed by a // backing account. -type SignerFn func(accounts.Account, []byte) ([]byte, error) - -// sigHash returns the hash which is used as input for the proof-of-authority -// signing. It is the hash of the entire header apart from the 65 byte signature -// contained at the end of the extra data. -// -// Note, the method requires the extra data to be at least 65 bytes, otherwise it -// panics. This is done to avoid accidentally using both forms (signature present -// or not), which could be abused to produce different hashes for the same header. -func sigHash(header *types.Header) (hash common.Hash) { - hasher := sha3.NewLegacyKeccak256() - - rlp.Encode(hasher, []interface{}{ - header.ParentHash, - header.UncleHash, - header.Coinbase, - header.Root, - header.TxHash, - header.ReceiptHash, - header.Bloom, - header.Difficulty, - header.Number, - header.GasLimit, - header.GasUsed, - header.Time, - header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short - header.MixDigest, - header.Nonce, - }) - hasher.Sum(hash[:0]) - return hash -} +type SignerFn func(accounts.Account, string, []byte) ([]byte, error) // ecrecover extracts the Ethereum account address from a signed header. func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) { @@ -185,7 +155,7 @@ func ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, er signature := header.Extra[len(header.Extra)-extraSeal:] // Recover the public key and the Ethereum address - pubkey, err := crypto.Ecrecover(sigHash(header).Bytes(), signature) + pubkey, err := crypto.Ecrecover(SealHash(header).Bytes(), signature) if err != nil { return common.Address{}, err } @@ -646,7 +616,7 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, results c log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) } // Sign all the things! - sighash, err := signFn(accounts.Account{Address: signer}, sigHash(header).Bytes()) + sighash, err := signFn(accounts.Account{Address: signer}, "application/x-clique-header", CliqueRLP(header)) if err != nil { return err } @@ -663,7 +633,7 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, results c select { case results <- block.WithSeal(header): default: - log.Warn("Sealing result is not read by miner", "sealhash", c.SealHash(header)) + log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header)) } }() @@ -693,7 +663,7 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { // SealHash returns the hash of a block prior to it being sealed. func (c *Clique) SealHash(header *types.Header) common.Hash { - return sigHash(header) + return SealHash(header) } // Close implements consensus.Engine. It's a noop for clique as there are no background threads. @@ -711,3 +681,47 @@ func (c *Clique) APIs(chain consensus.ChainReader) []rpc.API { Public: false, }} } + +// SealHash returns the hash of a block prior to it being sealed. +func SealHash(header *types.Header) (hash common.Hash) { + hasher := sha3.NewLegacyKeccak256() + encodeSigHeader(hasher, header) + hasher.Sum(hash[:0]) + return hash +} + +// CliqueRLP returns the rlp bytes which needs to be signed for the proof-of-authority +// sealing. The RLP to sign consists of the entire header apart from the 65 byte signature +// contained at the end of the extra data. +// +// Note, the method requires the extra data to be at least 65 bytes, otherwise it +// panics. This is done to avoid accidentally using both forms (signature present +// or not), which could be abused to produce different hashes for the same header. +func CliqueRLP(header *types.Header) []byte { + b := new(bytes.Buffer) + encodeSigHeader(b, header) + return b.Bytes() +} + +func encodeSigHeader(w io.Writer, header *types.Header) { + err := rlp.Encode(w, []interface{}{ + header.ParentHash, + header.UncleHash, + header.Coinbase, + header.Root, + header.TxHash, + header.ReceiptHash, + header.Bloom, + header.Difficulty, + header.Number, + header.GasLimit, + header.GasUsed, + header.Time, + header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short + header.MixDigest, + header.Nonce, + }) + if err != nil { + panic("can't encode: " + err.Error()) + } +} diff --git a/consensus/clique/snapshot_test.go b/consensus/clique/snapshot_test.go index 41dae1426..b920312a8 100644 --- a/consensus/clique/snapshot_test.go +++ b/consensus/clique/snapshot_test.go @@ -80,7 +80,7 @@ func (ap *testerAccountPool) sign(header *types.Header, signer string) { ap.accounts[signer], _ = crypto.GenerateKey() } // Sign the header and embed the signature in extra data - sig, _ := crypto.Sign(sigHash(header).Bytes(), ap.accounts[signer]) + sig, _ := crypto.Sign(SealHash(header).Bytes(), ap.accounts[signer]) copy(header.Extra[len(header.Extra)-extraSeal:], sig) } |