-
Notifications
You must be signed in to change notification settings - Fork 145
/
Copy pathsign.go
73 lines (65 loc) · 2.29 KB
/
sign.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package consensus
import (
"errors"
"github.com/PlatONnetwork/PlatON-Go/common"
"github.com/PlatONnetwork/PlatON-Go/core/types"
"github.com/PlatONnetwork/PlatON-Go/crypto"
"github.com/PlatONnetwork/PlatON-Go/crypto/sha3"
"github.com/PlatONnetwork/PlatON-Go/rlp"
lru "github.com/hashicorp/golang-lru"
)
var (
// ExtraSeal fixed number of extra-data suffix bytes reserved for signer seal
ExtraSeal = 65
// ErrMissingSignature is returned if a block's extra-data section doesn't seem
// to contain a 65 byte secp256k1 signature.
ErrMissingSignature = errors.New("extra-data 65 byte signature suffix missing")
)
// 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.NewKeccak256()
rlp.Encode(hasher, []interface{}{
header.ParentHash,
header.Coinbase,
header.Root,
header.TxHash,
header.ReceiptHash,
header.Bloom,
header.Number,
header.GasLimit,
header.GasUsed,
header.Time,
header.Extra[:len(header.Extra)-65], // Yes, this will panic if extra is too short
header.Nonce,
})
hasher.Sum(hash[:0])
return hash
}
// Ecrecover extracts the Ethereum account address from a signed header.
func Ecrecover(header *types.Header, sigcache *lru.ARCCache) (common.Address, error) {
// If the signature's already cached, return that
hash := header.Hash()
if address, known := sigcache.Get(hash); known {
return address.(common.Address), nil
}
// Retrieve the signature from the header extra-data
if len(header.Extra) < ExtraSeal {
return common.Address{}, ErrMissingSignature
}
signature := header.Extra[len(header.Extra)-ExtraSeal:]
// Recover the public key and the Ethereum address
pubkey, err := crypto.Ecrecover(SigHash(header).Bytes(), signature)
if err != nil {
return common.Address{}, err
}
var signer common.Address
copy(signer[:], crypto.Keccak256(pubkey[1:])[12:])
sigcache.Add(hash, signer)
return signer, nil
}