aboutsummaryrefslogtreecommitdiffstats
path: root/consensus
diff options
context:
space:
mode:
authorMartin Holst Swende <martin@swende.se>2019-02-05 18:23:57 +0800
committerGitHub <noreply@github.com>2019-02-05 18:23:57 +0800
commit43e8efe8955b8bb1fab7bfced33a6302fb69e48e (patch)
tree3db96494c913b31be950f5580bf49a82141b9255 /consensus
parent520024dfd689d264807b7fe1fc28deba51d6ab20 (diff)
downloadgo-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.go88
-rw-r--r--consensus/clique/snapshot_test.go2
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)
}