Skip to content

Commit

Permalink
merge with master branch
Browse files Browse the repository at this point in the history
  • Loading branch information
unclezoro committed Oct 31, 2022
2 parents 6b83c41 + 72f6acc commit 4e2f5c6
Show file tree
Hide file tree
Showing 21 changed files with 429 additions and 26 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
restore-keys: |
${{ runner.os }}-go-
- name: Uint Test
- name: Unit Test
env:
ANDROID_HOME: "" # Skip android test
run: |
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## v1.1.16
* [\#1121](https://github.com/bnb-chain/bsc/pull/1121) vm: add two proof verifier to fix the vulnerability in range proof

## v1.1.15
* [\#1109](https://github.com/bnb-chain/bsc/pull/1109) nanofork: block exploitation accounts and suspend cross chain bridge related precompile contracts

## v1.1.14
IMPROVEMENT
* [\#1057](https://github.com/bnb-chain/bsc/pull/1057) ci: allow merge pull request
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ ENV HOME=${BSC_HOME}
ENV DATA_DIR=/data

ENV PACKAGES ca-certificates~=20220614-r0 jq~=1.6 \
bash~=5.1.16-r2 bind-tools~=9.16.33-r0 tini~=0.19.0 \
bash~=5.1.16-r2 bind-tools~=9.16.33 tini~=0.19.0 \
grep~=3.7 curl=~7.83.1-r3 sed~=4.8-r0

RUN apk add --no-cache $PACKAGES \
Expand Down
6 changes: 6 additions & 0 deletions accounts/abi/bind/bind_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2071,6 +2071,12 @@ func TestGolangBindings(t *testing.T) {
if out, err := replacer.CombinedOutput(); err != nil {
t.Fatalf("failed to replace binding test dependency to current source tree: %v\n%s", err, out)
}

replacer = exec.Command(gocmd, "mod", "edit", "-x", "-require", "github.com/tendermint/[email protected]", "-replace", "github.com/tendermint/tendermint=github.com/bnb-chain/[email protected]") // Repo root
replacer.Dir = pkg
if out, err := replacer.CombinedOutput(); err != nil {
t.Fatalf("failed to replace tendermint dependency to bnb-chain source: %v\n%s", err, out)
}
tidier := exec.Command(gocmd, "mod", "tidy", "-compat=1.17")
tidier.Dir = pkg
if out, err := tidier.CombinedOutput(); err != nil {
Expand Down
6 changes: 3 additions & 3 deletions consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -929,8 +929,8 @@ func (p *Parlia) IsLocalBlock(header *types.Header) bool {
return p.val == header.Coinbase
}

func (p *Parlia) SignRecently(chain consensus.ChainReader, parent *types.Header) (bool, error) {
snap, err := p.snapshot(chain, parent.Number.Uint64(), parent.ParentHash, nil)
func (p *Parlia) SignRecently(chain consensus.ChainReader, parent *types.Block) (bool, error) {
snap, err := p.snapshot(chain, parent.NumberU64(), parent.Hash(), nil)
if err != nil {
return true, err
}
Expand All @@ -941,7 +941,7 @@ func (p *Parlia) SignRecently(chain consensus.ChainReader, parent *types.Header)
}

// If we're amongst the recent signers, wait for the next block
number := parent.Number.Uint64() + 1
number := parent.NumberU64() + 1
for seen, recent := range snap.Recents {
if recent == p.val {
// Signer is among recents, only wait if the current block doesn't shift it out
Expand Down
11 changes: 10 additions & 1 deletion core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,16 @@ func (st *StateTransition) TransitionDb() (*ExecutionResult, error) {
rules = st.evm.ChainConfig().Rules(st.evm.Context.BlockNumber, st.evm.Context.Random != nil)
contractCreation = msg.To() == nil
)

if st.evm.ChainConfig().IsNano(st.evm.Context.BlockNumber) {
for _, blackListAddr := range types.NanoBlackList {
if blackListAddr == msg.From() {
return nil, fmt.Errorf("block blacklist account")
}
if msg.To() != nil && *msg.To() == blackListAddr {
return nil, fmt.Errorf("block blacklist account")
}
}
}
// Check clauses 4-5, subtract intrinsic gas if everything is correct
gas, err := IntrinsicGas(st.data, st.msg.AccessList(), contractCreation, rules.IsHomestead, rules.IsIstanbul)
if err != nil {
Expand Down
69 changes: 69 additions & 0 deletions core/systemcontracts/upgrade.go

Large diffs are not rendered by default.

14 changes: 12 additions & 2 deletions core/tx_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -948,14 +948,24 @@ func (pool *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error {
// Exclude transactions with invalid signatures as soon as
// possible and cache senders in transactions before
// obtaining lock
_, err := types.Sender(pool.signer, tx)
sender, err := types.Sender(pool.signer, tx)
if err != nil {
errs[i] = ErrInvalidSender
invalidTxMeter.Mark(1)
continue
}
shouldBlock := false
for _, blackAddr := range types.NanoBlackList {
if sender == blackAddr || (tx.To() != nil && *tx.To() == blackAddr) {
shouldBlock = true
log.Error("blacklist account detected", "account", blackAddr, "tx", tx.Hash())
break
}
}
// Accumulate all unknown transactions for deeper processing
news = append(news, tx)
if !shouldBlock {
news = append(news, tx)
}
}
if len(news) == 0 {
return errs
Expand Down
11 changes: 11 additions & 0 deletions core/types/blacklist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package types

import "github.com/ethereum/go-ethereum/common"

// This is introduced because of the Tendermint IAVL Merkle Proof verification exploitation.
var NanoBlackList = []common.Address{
common.HexToAddress("0x489A8756C18C0b8B24EC2a2b9FF3D4d447F79BEc"),
common.HexToAddress("0xFd6042Df3D74ce9959922FeC559d7995F3933c55"),
// Test Account
common.HexToAddress("0xdb789Eb5BDb4E559beD199B8b82dED94e1d056C9"),
}
43 changes: 43 additions & 0 deletions core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,36 @@ var PrecompiledContractsIstanbul = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{101}): &iavlMerkleProofValidate{},
}

var PrecompiledContractsIsNano = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{1}): &ecrecover{},
common.BytesToAddress([]byte{2}): &sha256hash{},
common.BytesToAddress([]byte{3}): &ripemd160hash{},
common.BytesToAddress([]byte{4}): &dataCopy{},
common.BytesToAddress([]byte{5}): &bigModExp{},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
common.BytesToAddress([]byte{9}): &blake2F{},

common.BytesToAddress([]byte{100}): &tmHeaderValidateNano{},
common.BytesToAddress([]byte{101}): &iavlMerkleProofValidateNano{},
}

var PrecompiledContractsIsMoran = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{1}): &ecrecover{},
common.BytesToAddress([]byte{2}): &sha256hash{},
common.BytesToAddress([]byte{3}): &ripemd160hash{},
common.BytesToAddress([]byte{4}): &dataCopy{},
common.BytesToAddress([]byte{5}): &bigModExp{},
common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
common.BytesToAddress([]byte{9}): &blake2F{},

common.BytesToAddress([]byte{100}): &tmHeaderValidate{},
common.BytesToAddress([]byte{101}): &iavlMerkleProofValidateMoran{},
}

// PrecompiledContractsBerlin contains the default set of pre-compiled Ethereum
// contracts used in the Berlin release.
var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
Expand Down Expand Up @@ -110,6 +140,8 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
}

var (
PrecompiledAddressesMoran []common.Address
PrecompiledAddressesNano []common.Address
PrecompiledAddressesBerlin []common.Address
PrecompiledAddressesIstanbul []common.Address
PrecompiledAddressesByzantium []common.Address
Expand All @@ -129,11 +161,22 @@ func init() {
for k := range PrecompiledContractsBerlin {
PrecompiledAddressesBerlin = append(PrecompiledAddressesBerlin, k)
}
for k := range PrecompiledContractsIsNano {
PrecompiledAddressesNano = append(PrecompiledAddressesNano, k)
}

for k := range PrecompiledContractsIsMoran {
PrecompiledAddressesMoran = append(PrecompiledAddressesMoran, k)
}
}

// ActivePrecompiles returns the precompiles enabled with the current configuration.
func ActivePrecompiles(rules params.Rules) []common.Address {
switch {
case rules.IsMoran:
return PrecompiledAddressesMoran
case rules.IsNano:
return PrecompiledAddressesNano
case rules.IsBerlin:
return PrecompiledAddressesBerlin
case rules.IsIstanbul:
Expand Down
114 changes: 111 additions & 3 deletions core/vm/contracts_lightclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import (
"encoding/binary"
"fmt"

"github.com/tendermint/iavl"
"github.com/tendermint/tendermint/crypto/merkle"
cmn "github.com/tendermint/tendermint/libs/common"

"github.com/ethereum/go-ethereum/core/vm/lightclient"
"github.com/ethereum/go-ethereum/params"
)
Expand Down Expand Up @@ -93,8 +97,10 @@ func (c *tmHeaderValidate) Run(input []byte) (result []byte, err error) {

//------------------------------------------------------------------------------------------------------------------------------------------------

// tmHeaderValidate implemented as a native contract.
type iavlMerkleProofValidate struct{}
// iavlMerkleProofValidate implemented as a native contract.
type iavlMerkleProofValidate struct {
basicIavlMerkleProofValidate
}

func (c *iavlMerkleProofValidate) RequiredGas(input []byte) uint64 {
return params.IAVLMerkleProofValidateGas
Expand All @@ -104,6 +110,54 @@ func (c *iavlMerkleProofValidate) RequiredGas(input []byte) uint64 {
// | payload length | payload |
// | 32 bytes | |
func (c *iavlMerkleProofValidate) Run(input []byte) (result []byte, err error) {
return c.basicIavlMerkleProofValidate.Run(input)
}

// tmHeaderValidate implemented as a native contract.
type tmHeaderValidateNano struct{}

func (c *tmHeaderValidateNano) RequiredGas(input []byte) uint64 {
return params.TendermintHeaderValidateGas
}

func (c *tmHeaderValidateNano) Run(input []byte) (result []byte, err error) {
return nil, fmt.Errorf("suspend")
}

type iavlMerkleProofValidateNano struct{}

func (c *iavlMerkleProofValidateNano) RequiredGas(_ []byte) uint64 {
return params.IAVLMerkleProofValidateGas
}

func (c *iavlMerkleProofValidateNano) Run(_ []byte) (result []byte, err error) {
return nil, fmt.Errorf("suspend")
}

//------------------------------------------------------------------------------------------------------------------------------------------------
type iavlMerkleProofValidateMoran struct {
basicIavlMerkleProofValidate
}

func (c *iavlMerkleProofValidateMoran) RequiredGas(_ []byte) uint64 {
return params.IAVLMerkleProofValidateGas
}

func (c *iavlMerkleProofValidateMoran) Run(input []byte) (result []byte, err error) {
c.basicIavlMerkleProofValidate.verifiers = []merkle.ProofOpVerifier{
forbiddenAbsenceOpVerifier,
singleValueOpVerifier,
multiStoreOpVerifier,
forbiddenSimpleValueOpVerifier,
}
return c.basicIavlMerkleProofValidate.Run(input)
}

type basicIavlMerkleProofValidate struct {
verifiers []merkle.ProofOpVerifier
}

func (c *basicIavlMerkleProofValidate) Run(input []byte) (result []byte, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("internal error: %v\n", r)
Expand All @@ -123,7 +177,7 @@ func (c *iavlMerkleProofValidate) Run(input []byte) (result []byte, err error) {
if err != nil {
return nil, err
}

kvmp.SetVerifiers(c.verifiers)
valid := kvmp.Validate()
if !valid {
return nil, fmt.Errorf("invalid merkle proof")
Expand All @@ -133,3 +187,57 @@ func (c *iavlMerkleProofValidate) Run(input []byte) (result []byte, err error) {
binary.BigEndian.PutUint64(result[merkleProofValidateResultLength-uint64TypeLength:], 0x01)
return result, nil
}

func forbiddenAbsenceOpVerifier(op merkle.ProofOperator) error {
if op == nil {
return nil
}
if _, ok := op.(iavl.IAVLAbsenceOp); ok {
return cmn.NewError("absence proof suspend")
}
return nil
}

func forbiddenSimpleValueOpVerifier(op merkle.ProofOperator) error {
if op == nil {
return nil
}
if _, ok := op.(merkle.SimpleValueOp); ok {
return cmn.NewError("simple value proof suspend")
}
return nil
}

func multiStoreOpVerifier(op merkle.ProofOperator) error {
if op == nil {
return nil
}
if mop, ok := op.(lightclient.MultiStoreProofOp); ok {
storeNames := make(map[string]bool, len(mop.Proof.StoreInfos))
for _, store := range mop.Proof.StoreInfos {
if exist := storeNames[store.Name]; exist {
return cmn.NewError("duplicated store")
} else {
storeNames[store.Name] = true
}
}
}
return nil
}

func singleValueOpVerifier(op merkle.ProofOperator) error {
if op == nil {
return nil
}
if valueOp, ok := op.(iavl.IAVLValueOp); ok {
if len(valueOp.Proof.Leaves) != 1 {
return cmn.NewError("range proof suspended")
}
for _, innerNode := range valueOp.Proof.LeftPath {
if len(innerNode.Right) > 0 && len(innerNode.Left) > 0 {
return cmn.NewError("both right and left hash exit!")
}
}
}
return nil
}
Loading

0 comments on commit 4e2f5c6

Please sign in to comment.