Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[R4R]: resolve best practice advice #22

Merged
merged 5 commits into from
Aug 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 19 additions & 18 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func isToSystemContract(to common.Address) bool {
}

// ecrecover extracts the Ethereum account address from a signed header.
func ecrecover(header *types.Header, sigCache *lru.ARCCache) (common.Address, error) {
func ecrecover(header *types.Header, sigCache *lru.ARCCache, chainId *big.Int) (common.Address, error) {
// If the signature's already cached, return that
hash := header.Hash()
if address, known := sigCache.Get(hash); known {
Expand All @@ -169,7 +169,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(SealHash(header).Bytes(), signature)
pubkey, err := crypto.Ecrecover(SealHash(header, chainId).Bytes(), signature)
if err != nil {
return common.Address{}, err
}
Expand All @@ -187,9 +187,9 @@ func ecrecover(header *types.Header, sigCache *lru.ARCCache) (common.Address, er
// 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 ParliaRLP(header *types.Header) []byte {
func ParliaRLP(header *types.Header, chainId *big.Int) []byte {
b := new(bytes.Buffer)
encodeSigHeader(b, header)
encodeSigHeader(b, header, chainId)
return b.Bytes()
}

Expand Down Expand Up @@ -396,9 +396,9 @@ func (p *Parlia) verifyCascadingFields(chain consensus.ChainReader, header *type
}

// Verify that the gas limit is <= 2^63-1
cap := uint64(0x7fffffffffffffff)
if header.GasLimit > cap {
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
capacity := uint64(0x7fffffffffffffff)
if header.GasLimit > capacity {
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, capacity)
}
// Verify that the gasUsed is <= gasLimit
if header.GasUsed > header.GasLimit {
Expand Down Expand Up @@ -498,7 +498,7 @@ func (p *Parlia) snapshot(chain consensus.ChainReader, number uint64, hash commo
headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i]
}

snap, err := snap.apply(headers, chain, parents)
snap, err := snap.apply(headers, chain, parents, p.chainConfig.ChainID)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -546,7 +546,7 @@ func (p *Parlia) verifySeal(chain consensus.ChainReader, header *types.Header, p
}

// Resolve the authorization key and check against validators
signer, err := ecrecover(header, p.signatures)
signer, err := ecrecover(header, p.signatures, p.chainConfig.ChainID)
if err != nil {
return err
}
Expand Down Expand Up @@ -809,7 +809,7 @@ func (p *Parlia) Seal(chain consensus.ChainReader, block *types.Block, results c
}

// Sweet, the protocol permits us to sign the block, wait for our time
delay := time.Unix(int64(header.Time), 0).Sub(time.Now()) // nolint: gosimple
delay := time.Until(time.Unix(int64(header.Time), 0)) // nolint: gosimple
if header.Difficulty.Cmp(diffNoTurn) == 0 {
// It's not our turn explicitly to sign, delay it a bit
wiggle := time.Duration(len(snap.Validators)/2+1) * wiggleTime
Expand All @@ -821,7 +821,7 @@ func (p *Parlia) Seal(chain consensus.ChainReader, block *types.Block, results c
log.Info("Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "val", val.Hex())

// Sign all the things!
sig, err := signFn(accounts.Account{Address: val}, accounts.MimetypeParlia, ParliaRLP(header))
sig, err := signFn(accounts.Account{Address: val}, accounts.MimetypeParlia, ParliaRLP(header, p.chainConfig.ChainID))
if err != nil {
return err
}
Expand All @@ -839,7 +839,7 @@ func (p *Parlia) 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", SealHash(header))
log.Warn("Sealing result is not read by miner", "sealhash", SealHash(header, p.chainConfig.ChainID))
}
}()

Expand Down Expand Up @@ -869,7 +869,7 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int {

// SealHash returns the hash of a block prior to it being sealed.
func (p *Parlia) SealHash(header *types.Header) common.Hash {
return SealHash(header)
return SealHash(header, p.chainConfig.ChainID)
}

// APIs implements consensus.Engine, returning the user facing RPC API to query snapshot.
Expand Down Expand Up @@ -1072,8 +1072,8 @@ func (p *Parlia) applyTransaction(
return errors.New("supposed to get a actual transaction, but get none")
}
actualTx := (*receivedTxs)[0]
if bytes.Compare(p.signer.Hash(actualTx).Bytes(), expectedHash.Bytes()) != 0 {
return errors.New(fmt.Sprintf("expected tx hash %v, get %v", expectedHash.String(), actualTx.Hash().String()))
if !bytes.Equal(p.signer.Hash(actualTx).Bytes(), expectedHash.Bytes()) {
return fmt.Errorf("expected tx hash %v, get %v", expectedHash.String(), actualTx.Hash().String())
}
expectedTx = actualTx
// move to next
Expand Down Expand Up @@ -1109,15 +1109,16 @@ func (p *Parlia) applyTransaction(

// =========================== utility function ==========================
// SealHash returns the hash of a block prior to it being sealed.
func SealHash(header *types.Header) (hash common.Hash) {
func SealHash(header *types.Header, chainId *big.Int) (hash common.Hash) {
hasher := sha3.NewLegacyKeccak256()
encodeSigHeader(hasher, header)
encodeSigHeader(hasher, header, chainId)
hasher.Sum(hash[:0])
return hash
}

func encodeSigHeader(w io.Writer, header *types.Header) {
func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) {
err := rlp.Encode(w, []interface{}{
chainId,
header.ParentHash,
header.UncleHash,
header.Coinbase,
Expand Down
5 changes: 3 additions & 2 deletions consensus/parlia/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"bytes"
"encoding/json"
"errors"
"math/big"
"sort"

"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -123,7 +124,7 @@ func (s *Snapshot) copy() *Snapshot {
return cpy
}

func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainReader, parents []*types.Header) (*Snapshot, error) {
func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainReader, parents []*types.Header, chainId *big.Int) (*Snapshot, error) {
// Allow passing in no headers for cleaner code
if len(headers) == 0 {
return s, nil
Expand Down Expand Up @@ -153,7 +154,7 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainReader, p
delete(snap.Recents, number-limit)
}
// Resolve the authorization key and check against signers
validator, err := ecrecover(header, s.sigCache)
validator, err := ecrecover(header, s.sigCache, chainId)
if err != nil {
return nil, err
}
Expand Down
11 changes: 6 additions & 5 deletions core/vm/contracts_lightclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
)

const (
uint64TypeLength uint64 = 8
precompileContractInputMetaDataLength uint64 = 32
consensusStateLengthBytesLength uint64 = 32

Expand All @@ -20,7 +21,7 @@ const (
// consensus state length | consensus state | tendermint header |
// 32 bytes | | |
func decodeTendermintHeaderValidationInput(input []byte) (*lightclient.ConsensusState, *lightclient.Header, error) {
csLen := binary.BigEndian.Uint64(input[consensusStateLengthBytesLength-8 : consensusStateLengthBytesLength])
csLen := binary.BigEndian.Uint64(input[consensusStateLengthBytesLength-uint64TypeLength : consensusStateLengthBytesLength])
if uint64(len(input)) <= consensusStateLengthBytesLength+csLen {
return nil, nil, fmt.Errorf("expected payload size %d, actual size: %d", consensusStateLengthBytesLength+csLen, len(input))
}
Expand Down Expand Up @@ -55,7 +56,7 @@ func (c *tmHeaderValidate) Run(input []byte) (result []byte, err error) {
return nil, fmt.Errorf("invalid input")
}

payloadLength := binary.BigEndian.Uint64(input[precompileContractInputMetaDataLength-8 : precompileContractInputMetaDataLength])
payloadLength := binary.BigEndian.Uint64(input[precompileContractInputMetaDataLength-uint64TypeLength : precompileContractInputMetaDataLength])
if uint64(len(input)) != payloadLength+precompileContractInputMetaDataLength {
return nil, fmt.Errorf("invalid input: input size should be %d, actual the size is %d", payloadLength+precompileContractInputMetaDataLength, len(input))
}
Expand Down Expand Up @@ -83,7 +84,7 @@ func (c *tmHeaderValidate) Run(input []byte) (result []byte, err error) {
copy(lengthBytes[:1], []byte{0x01})
}
consensusStateBytesLength := uint64(len(consensusStateBytes))
binary.BigEndian.PutUint64(lengthBytes[tmHeaderValidateResultMetaDataLength-8:], consensusStateBytesLength)
binary.BigEndian.PutUint64(lengthBytes[tmHeaderValidateResultMetaDataLength-uint64TypeLength:], consensusStateBytesLength)

result = append(lengthBytes, consensusStateBytes...)

Expand Down Expand Up @@ -113,7 +114,7 @@ func (c *iavlMerkleProofValidate) Run(input []byte) (result []byte, err error) {
return nil, fmt.Errorf("invalid input: input should include %d bytes payload length and payload", precompileContractInputMetaDataLength)
}

payloadLength := binary.BigEndian.Uint64(input[precompileContractInputMetaDataLength-8 : precompileContractInputMetaDataLength])
payloadLength := binary.BigEndian.Uint64(input[precompileContractInputMetaDataLength-uint64TypeLength : precompileContractInputMetaDataLength])
if uint64(len(input)) != payloadLength+precompileContractInputMetaDataLength {
return nil, fmt.Errorf("invalid input: input size should be %d, actual the size is %d", payloadLength+precompileContractInputMetaDataLength, len(input))
}
Expand All @@ -129,6 +130,6 @@ func (c *iavlMerkleProofValidate) Run(input []byte) (result []byte, err error) {
}

result = make([]byte, merkleProofValidateResultLength)
binary.BigEndian.PutUint64(result[merkleProofValidateResultLength-8:], 0x01)
binary.BigEndian.PutUint64(result[merkleProofValidateResultLength-uint64TypeLength:], 0x01)
return result, nil
}
1 change: 1 addition & 0 deletions core/vm/contracts_lightclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func TestTmHeaderValidateAndMerkleProofValidate(t *testing.T) {
"cc05d26c7b0be0c8b46418294171730e079f384fde2fa50bafc000000174876e80049b288e4ebbb3a281c2d546fc30253d5baf08993b6e5d295fb7" +
"87a5b314a298e000000174876e80004224339688f012e649de48e241880092eaa8f6aa0f4f14bfcf9e0c76917c0b6000000174876e8004034b37ce" +
"da8a0bf13b1abaeee7a8f9383542099a554d219b93d0ce69e3970e8000000174876e800")
require.NoError(t, err)

cs, err := lightclient.DecodeConsensusState(consensusStateBytes)
require.NoError(t, err)
Expand Down
10 changes: 2 additions & 8 deletions core/vm/lightclient/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,17 +226,11 @@ func (kvmp *KeyValueMerkleProof) Validate() bool {

if len(kvmp.Value) == 0 {
err := prt.VerifyAbsence(kvmp.Proof, kvmp.AppHash, kp.String())
if err != nil {
return false
}
return true
return err == nil
}

err := prt.VerifyValue(kvmp.Proof, kvmp.AppHash, kp.String(), kvmp.Value)
if err != nil {
return false
}
return true
return err == nil
}

// input:
Expand Down
2 changes: 1 addition & 1 deletion params/protocol_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const (
CallValueTransferGas uint64 = 9000 // Paid for CALL when the value transfer is non-zero.
CallNewAccountGas uint64 = 25000 // Paid for CALL when the destination address didn't exist prior.
TxGas uint64 = 21000 // Per transaction not creating a contract. NOTE: Not payable on data of calls between transactions.
SystemTxsGas uint64 = 100000 // The gas reserved for system txs; only for parlia consensus
SystemTxsGas uint64 = 500000 // The gas reserved for system txs; only for parlia consensus
TxGasContractCreation uint64 = 53000 // Per transaction that creates a contract. NOTE: Not payable on data of calls between transactions.
TxDataZeroGas uint64 = 4 // Per byte of data attached to a transaction that equals zero. NOTE: Not payable on data of calls between transactions.
QuadCoeffDiv uint64 = 512 // Divisor for the quadratic particle of the memory cost equation.
Expand Down
2 changes: 1 addition & 1 deletion params/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const (
VersionMajor = 1 // Major version component of the current release
VersionMinor = 0 // Minor version component of the current release
VersionPatch = 0 // Patch version component of the current release
VersionMeta = "beta.0" // Version metadata to append to the version string
VersionMeta = "beta.1" // Version metadata to append to the version string
)

// Version holds the textual version string.
Expand Down
8 changes: 4 additions & 4 deletions signer/core/signed_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ func (api *SignerAPI) determineSignatureFormat(ctx context.Context, contentType
header.Extra = newExtra
}
// Get back the rlp data, encoded by us
sighash, parliaRlp, err := parliaHeaderHashAndRlp(header)
sighash, parliaRlp, err := parliaHeaderHashAndRlp(header, api.chainID)
if err != nil {
return nil, useEthereumV, err
}
Expand Down Expand Up @@ -351,13 +351,13 @@ func cliqueHeaderHashAndRlp(header *types.Header) (hash, rlp []byte, err error)
return hash, rlp, err
}

func parliaHeaderHashAndRlp(header *types.Header) (hash, rlp []byte, err error) {
func parliaHeaderHashAndRlp(header *types.Header, chainId *big.Int) (hash, rlp []byte, err error) {
if len(header.Extra) < 65 {
err = fmt.Errorf("clique header extradata too short, %d < 65", len(header.Extra))
return
}
rlp = parlia.ParliaRLP(header)
hash = parlia.SealHash(header).Bytes()
rlp = parlia.ParliaRLP(header, chainId)
hash = parlia.SealHash(header, chainId).Bytes()
return hash, rlp, err
}

Expand Down