mirror of https://github.com/poanetwork/quorum.git
merge 1.8.18 with quorum/master
refactor raft & istanbul based on upstream changes fix unit test cases
This commit is contained in:
parent
4dbd95947d
commit
73667e7942
159
.travis.yml
159
.travis.yml
|
@ -1,32 +1,104 @@
|
|||
# simplifed version of the upstream travis configuration
|
||||
# simplified version of the upstream travis configuration.
|
||||
# automated acceptance test is run[in linux box] for raft, istanbul and clique consensus in parallel as part of every build
|
||||
# unit test is run in linux and macOS boxes as part of every build
|
||||
|
||||
language: go
|
||||
go_import_path: github.com/ethereum/go-ethereum
|
||||
go: 1.9.x
|
||||
sudo: true
|
||||
branches:
|
||||
only:
|
||||
- /.*/ # everything including tags
|
||||
sudo: false
|
||||
|
||||
env:
|
||||
global:
|
||||
- BINTRAY_ORGANIZATION=quorumengineering
|
||||
- BINTRAY_USER=quorumbot
|
||||
# Bintray API Key
|
||||
- secure: "QHiPcd3zQoJEsT3VSpxoLVTYwbiYzS8H18EpY7Tk0EqCIfswS2AvRlyRXUxNvCf9ktzpaeXV4b5cPYJ67dwdp5V/O/ARaK5AL6ZjjrTPR1avPnmz/X2VeQEP0aWk1UGMs1nBUj5rzMbIIxlVhpbiITTLAI4Ao0+xRcBi215mDbv271Z7mACEZfXxjaoJA0/3IkbKz9pu1nC7bTjaaExCDAeLp2p8fHi2YQPnBll/7dkn/m1rnsIY9M3KWNCx6xBmQOr1hulrrB6tZoHwFBoDsVTFJFLckPfrWUZsYUgtfWJMQWc6ntv1gFl0f9x6s5fYEphCU2m1JYjEczlQ03B5ro9EyPGKjO7vQxAaFd5nVd2Xf34ZbssEIyXxlSnP/4Gv1GXl9L9aU1Hth9ckYvT5gYP5t/Nw3CDbKD0HelPBvkf8jZwfdlotzFPS2bOZNdl/rJLWgQrX18a/mC3BH9l4TSRz13tbRfo6YcC3Y/uOvG1n4GxzcVaWojAxn86SkknOczPTf2pk9F3JOcGVSYA2R4kGQAe+ErJH2X5g2sh1D5cCYDjQyl5rzWg6P3eK//HYW+mg2+TQ8k2iQVVSwFwrR0Yn4P+5cRDCW9mjtktgq1rTtslj41gSH49Avqr9oXGM2rqdcJPdN8dnmLMrAtmeSUNMMoexiRMmlF2OQKLrW3k="
|
||||
- TESSERA_JAR="$HOME/tessera.jar"
|
||||
|
||||
addons:
|
||||
apt:
|
||||
update: true
|
||||
sources:
|
||||
- sourceline: ppa:ethereum/ethereum
|
||||
- sourceline: ppa:openjdk-r/ppa
|
||||
packages:
|
||||
- openjdk-8-jdk
|
||||
- dpkg # fixes issue with dpkg-deb error due to travis image
|
||||
- openssh-client
|
||||
- dnsutils
|
||||
- maven
|
||||
- solc
|
||||
- jq
|
||||
- curl
|
||||
|
||||
before_install:
|
||||
- if [ $TRAVIS_OS_NAME = linux ]; then git clone https://github.com/amalrajmani/quorum-acceptance-tests.git $TRAVIS_HOME/quorum-acceptance-tests; fi;
|
||||
- if [ $TRAVIS_OS_NAME = linux ]; then sudo chmod 755 $TRAVIS_HOME/quorum-acceptance-tests/src/travis/install-linux.sh; fi;
|
||||
- if [ $TRAVIS_OS_NAME = linux ]; then sudo chmod 755 $TRAVIS_HOME/quorum-acceptance-tests/src/travis/script-linux.sh; fi;
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- if: tag IS blank
|
||||
- name: linux-raft
|
||||
os: linux
|
||||
dist: xenial
|
||||
dist: trusty
|
||||
sudo: true
|
||||
go: 1.10.x
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.m2
|
||||
|
||||
env:
|
||||
- TF_VAR_consensus_mechanism=raft
|
||||
|
||||
install: $TRAVIS_HOME/quorum-acceptance-tests/src/travis/install-linux.sh
|
||||
|
||||
script: $TRAVIS_HOME/quorum-acceptance-tests/src/travis/script-linux.sh
|
||||
|
||||
|
||||
- name: linux-istanbul
|
||||
os: linux
|
||||
dist: trusty
|
||||
sudo: true
|
||||
go: 1.10.x
|
||||
|
||||
directories:
|
||||
- $HOME/.m2
|
||||
|
||||
env:
|
||||
- TF_VAR_consensus_mechanism=istanbul
|
||||
|
||||
install: $TRAVIS_HOME/quorum-acceptance-tests/src/travis/install-linux.sh
|
||||
|
||||
script: $TRAVIS_HOME/quorum-acceptance-tests/src/travis/script-linux.sh
|
||||
|
||||
- name: linux-clique
|
||||
os: linux
|
||||
dist: trusty
|
||||
sudo: true
|
||||
go: 1.10.x
|
||||
|
||||
directories:
|
||||
- $HOME/.m2
|
||||
|
||||
env:
|
||||
- TF_VAR_consensus_mechanism=clique
|
||||
|
||||
install: $TRAVIS_HOME/quorum-acceptance-tests/src/travis/install-linux.sh
|
||||
|
||||
script: $TRAVIS_HOME/quorum-acceptance-tests/src/travis/script-linux.sh
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
sudo: required
|
||||
go: 1.10.x
|
||||
script:
|
||||
- sudo modprobe fuse
|
||||
- sudo chmod 666 /dev/fuse
|
||||
- sudo chown root:$USER /etc/fuse.conf
|
||||
- go run build/ci.go install
|
||||
- go run build/ci.go test -coverage $TEST_PACKAGES
|
||||
- if: tag IS blank
|
||||
os: osx
|
||||
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.2 # so we don't have to deal with Kernel Extension Consent UI which is never possible in CI
|
||||
go: 1.10.x
|
||||
sudo: required
|
||||
script:
|
||||
- brew update
|
||||
- brew install caskroom/cask/brew-cask
|
||||
|
@ -34,62 +106,3 @@ matrix:
|
|||
- go run build/ci.go install
|
||||
- go run build/ci.go test -coverage $TEST_PACKAGES
|
||||
|
||||
- if: tag IS present
|
||||
os: linux
|
||||
dist: xenial
|
||||
env: OUTPUT_FILE=geth_${TRAVIS_TAG}_linux_amd64.tar.gz
|
||||
script:
|
||||
- build/env.sh go run build/ci.go install ./cmd/geth
|
||||
- sudo mkdir -p /dist
|
||||
- cd build/bin
|
||||
- sudo tar cfvz /dist/${OUTPUT_FILE} geth
|
||||
- if: tag IS present
|
||||
os: osx
|
||||
osx_image: xcode9.2
|
||||
env: OUTPUT_FILE=geth_${TRAVIS_TAG}_darwin_amd64.tar.gz
|
||||
script:
|
||||
- build/env.sh go run build/ci.go install ./cmd/geth
|
||||
- sudo mkdir -p /dist
|
||||
- cd build/bin
|
||||
- sudo tar cfvz /dist/${OUTPUT_FILE} geth
|
||||
|
||||
before_deploy:
|
||||
- |
|
||||
echo "Prepare Bintray descriptor"
|
||||
export GETH_VERSION=$(cat ${TRAVIS_BUILD_DIR}/VERSION)
|
||||
export RELEASED_DATE=$(date +'%Y-%m-%d')
|
||||
sed -e "s/_TRAVIS_TAG_/${TRAVIS_TAG}/g" \
|
||||
-e "s/_TRAVIS_BUILD_NUMBER_/${TRAVIS_BUILD_NUMBER}/g" \
|
||||
-e "s/_GETH_VERSION_/${GETH_VERSION}/g" \
|
||||
-e "s/_RELEASED_DATE_/${RELEASED_DATE}/g" \
|
||||
-e "s/_TRAVIS_COMMIT_/${TRAVIS_COMMIT}/g" \
|
||||
-e "s/_TRAVIS_JOB_WEB_URL_/${TRAVIS_JOB_WEB_URL//\//\\/}/g" \
|
||||
-e "s/_ORGANIZATION_/${BINTRAY_ORGANIZATION}/g" \
|
||||
${TRAVIS_BUILD_DIR}/.bintray.json > /tmp/bintray.json
|
||||
after_deploy:
|
||||
- |
|
||||
published=""
|
||||
while [ "$published" == "" ]; do
|
||||
echo "Sleep 5s to wait until ${OUTPUT_FILE} is published"
|
||||
sleep 5
|
||||
result=$(curl -u ${BINTRAY_USER}:${BINTRAY_API_KEY} "https://api.bintray.com/packages/${BINTRAY_ORGANIZATION}/quorum/geth/versions/${TRAVIS_TAG}/files")
|
||||
echo "$result"
|
||||
if [[ "$result" == *"${OUTPUT_FILE}"* ]]; then
|
||||
published="done"
|
||||
fi
|
||||
done
|
||||
- |
|
||||
echo "Add ${OUTPUT_FILE} to Download List"
|
||||
curl -u ${BINTRAY_USER}:${BINTRAY_API_KEY} \
|
||||
-H "Content-type: application/json" \
|
||||
-X PUT \
|
||||
--data "{\"list_in_downloads\": true}" \
|
||||
https://api.bintray.com/file_metadata/${BINTRAY_ORGANIZATION}/quorum/${TRAVIS_TAG}/${OUTPUT_FILE}
|
||||
deploy:
|
||||
provider: bintray
|
||||
file: /tmp/bintray.json
|
||||
user: ${BINTRAY_USER}
|
||||
key: ${BINTRAY_API_KEY}
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
|
@ -23,9 +23,10 @@ import (
|
|||
|
||||
const (
|
||||
testSource = `
|
||||
pragma solidity ^0.5.0;
|
||||
contract test {
|
||||
/// @notice Will multiply ` + "`a`" + ` by 7.
|
||||
function multiply(uint a) returns(uint d) {
|
||||
function multiply(uint a) public returns(uint d) {
|
||||
return a * 7;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ func newBlockChain(n int) (*core.BlockChain, *backend) {
|
|||
// Use the first key as private key
|
||||
b, _ := New(config, nodeKeys[0], memDB).(*backend)
|
||||
genesis.MustCommit(memDB)
|
||||
blockchain, err := core.NewBlockChain(memDB, nil, genesis.Config, b, vm.Config{})
|
||||
blockchain, err := core.NewBlockChain(memDB, nil, genesis.Config, b, vm.Config{}, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ func makeHeader(parent *types.Block, config *istanbul.Config) *types.Header {
|
|||
header := &types.Header{
|
||||
ParentHash: parent.Hash(),
|
||||
Number: parent.Number().Add(parent.Number(), common.Big1),
|
||||
GasLimit: core.CalcGasLimit(parent),
|
||||
GasLimit: core.CalcGasLimit(parent, parent.GasLimit(), parent.GasLimit()),
|
||||
GasUsed: 0,
|
||||
Extra: parent.Extra(),
|
||||
Time: new(big.Int).Add(parent.Time(), new(big.Int).SetUint64(config.BlockPeriod)),
|
||||
|
@ -131,8 +131,11 @@ func makeHeader(parent *types.Block, config *istanbul.Config) *types.Header {
|
|||
|
||||
func makeBlock(chain *core.BlockChain, engine *backend, parent *types.Block) *types.Block {
|
||||
block := makeBlockWithoutSeal(chain, engine, parent)
|
||||
block, _ = engine.Seal(chain, block, nil)
|
||||
return block
|
||||
stopCh := make(chan struct{})
|
||||
resultCh := make(chan *types.Block, 10)
|
||||
go engine.Seal(chain, block, resultCh, stopCh)
|
||||
blk := <-resultCh
|
||||
return blk
|
||||
}
|
||||
|
||||
func makeBlockWithoutSeal(chain *core.BlockChain, engine *backend, parent *types.Block) *types.Block {
|
||||
|
@ -174,10 +177,15 @@ func TestSealStopChannel(t *testing.T) {
|
|||
eventSub.Unsubscribe()
|
||||
}
|
||||
go eventLoop()
|
||||
finalBlock, err := engine.Seal(chain, block, stop)
|
||||
resultCh := make(chan *types.Block, 10)
|
||||
go func() {
|
||||
err := engine.Seal(chain, block, resultCh, stop)
|
||||
if err != nil {
|
||||
t.Errorf("error mismatch: have %v, want nil", err)
|
||||
}
|
||||
}()
|
||||
|
||||
finalBlock := <-resultCh
|
||||
if finalBlock != nil {
|
||||
t.Errorf("block mismatch: have %v, want nil", finalBlock)
|
||||
}
|
||||
|
@ -201,7 +209,7 @@ func TestSealCommittedOtherHash(t *testing.T) {
|
|||
}
|
||||
go eventLoop()
|
||||
seal := func() {
|
||||
engine.Seal(chain, block, nil)
|
||||
engine.Seal(chain, block, nil, make(chan struct{}))
|
||||
t.Error("seal should not be completed")
|
||||
}
|
||||
go seal()
|
||||
|
@ -218,11 +226,16 @@ func TestSealCommitted(t *testing.T) {
|
|||
chain, engine := newBlockChain(1)
|
||||
block := makeBlockWithoutSeal(chain, engine, chain.Genesis())
|
||||
expectedBlock, _ := engine.updateBlock(engine.chain.GetHeader(block.ParentHash(), block.NumberU64()-1), block)
|
||||
resultCh := make(chan *types.Block, 10)
|
||||
go func() {
|
||||
err := engine.Seal(chain, block, resultCh, make(chan struct{}))
|
||||
|
||||
finalBlock, err := engine.Seal(chain, block, nil)
|
||||
if err != nil {
|
||||
t.Errorf("error mismatch: have %v, want nil", err)
|
||||
t.Errorf("error mismatch: have %v, want %v", err, expectedBlock)
|
||||
}
|
||||
}()
|
||||
|
||||
finalBlock := <-resultCh
|
||||
if finalBlock.Hash() != expectedBlock.Hash() {
|
||||
t.Errorf("hash mismatch: have %v, want %v", finalBlock.Hash(), expectedBlock.Hash())
|
||||
}
|
||||
|
|
|
@ -347,7 +347,7 @@ func TestVoting(t *testing.T) {
|
|||
config.Epoch = tt.epoch
|
||||
}
|
||||
engine := New(config, accounts.accounts[tt.validators[0]], db).(*backend)
|
||||
chain, err := core.NewBlockChain(db, nil, genesis.Config, engine, vm.Config{})
|
||||
chain, err := core.NewBlockChain(db, nil, genesis.Config, engine, vm.Config{}, nil)
|
||||
|
||||
// Assemble a chain of headers from the cast votes
|
||||
headers := make([]*types.Header, len(tt.votes))
|
||||
|
|
|
@ -156,6 +156,10 @@ func (self *testSystemBackend) ParentValidators(proposal istanbul.Proposal) ista
|
|||
return self.peers
|
||||
}
|
||||
|
||||
func (sb *testSystemBackend) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ==============================================
|
||||
//
|
||||
// define the struct that need to be provided for integration tests.
|
||||
|
|
|
@ -103,8 +103,10 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat
|
|||
return nil
|
||||
}
|
||||
|
||||
// CalcGasLimit computes the gas limit of the next block after parent.
|
||||
// This is miner strategy, not consensus protocol.
|
||||
// CalcGasLimit computes the gas limit of the next block after parent. It aims
|
||||
// to keep the baseline gas above the provided floor, and increase it towards the
|
||||
// ceil if the blocks are full. If the ceil is exceeded, it will always decrease
|
||||
// the gas allowance.
|
||||
func CalcGasLimit(parent *types.Block, gasFloor, gasCeil uint64) uint64 {
|
||||
// contrib = (parentGasUsed * 3 / 2) / 4096
|
||||
contrib := (parent.GasUsed() + parent.GasUsed()/2) / params.GasLimitBoundDivisor
|
||||
|
@ -123,8 +125,7 @@ func CalcGasLimit(parent *types.Block, gasFloor, gasCeil uint64) uint64 {
|
|||
if limit < params.MinGasLimit {
|
||||
limit = params.MinGasLimit
|
||||
}
|
||||
// however, if we're now below the target (TargetGasLimit) we increase the
|
||||
// limit as much as we can (parentGasLimit / 4096 -1)
|
||||
// If we're outside our allowed gas range, we try to hone towards them
|
||||
if limit < gasFloor {
|
||||
limit = parent.GasLimit() + decay
|
||||
if limit > gasFloor {
|
||||
|
|
|
@ -119,23 +119,68 @@ func gasSStore(gt params.GasTable, evm *EVM, contract *Contract, stack *Stack, m
|
|||
var (
|
||||
db = getDualState(evm, contract.Address())
|
||||
y, x = stack.Back(1), stack.Back(0)
|
||||
val = db.GetState(contract.Address(), common.BigToHash(x))
|
||||
current = db.GetState(contract.Address(), common.BigToHash(x))
|
||||
)
|
||||
// This checks for 3 scenario's and calculates gas accordingly
|
||||
// The legacy gas metering only takes into consideration the current state
|
||||
if !evm.chainRules.IsConstantinople {
|
||||
// This checks for 3 scenario's and calculates gas accordingly:
|
||||
//
|
||||
// 1. From a zero-value address to a non-zero value (NEW VALUE)
|
||||
// 2. From a non-zero value address to a zero-value address (DELETE)
|
||||
// 3. From a non-zero to a non-zero (CHANGE)
|
||||
if val == (common.Hash{}) && y.Sign() != 0 {
|
||||
// 0 => non 0
|
||||
switch {
|
||||
case current == (common.Hash{}) && y.Sign() != 0: // 0 => non 0
|
||||
return params.SstoreSetGas, nil
|
||||
} else if val != (common.Hash{}) && y.Sign() == 0 {
|
||||
// non 0 => 0
|
||||
db.AddRefund(params.SstoreRefundGas)
|
||||
case current != (common.Hash{}) && y.Sign() == 0: // non 0 => 0
|
||||
evm.StateDB.AddRefund(params.SstoreRefundGas)
|
||||
return params.SstoreClearGas, nil
|
||||
} else {
|
||||
// non 0 => non 0 (or 0 => 0)
|
||||
default: // non 0 => non 0 (or 0 => 0)
|
||||
return params.SstoreResetGas, nil
|
||||
}
|
||||
}
|
||||
// The new gas metering is based on net gas costs (EIP-1283):
|
||||
//
|
||||
// 1. If current value equals new value (this is a no-op), 200 gas is deducted.
|
||||
// 2. If current value does not equal new value
|
||||
// 2.1. If original value equals current value (this storage slot has not been changed by the current execution context)
|
||||
// 2.1.1. If original value is 0, 20000 gas is deducted.
|
||||
// 2.1.2. Otherwise, 5000 gas is deducted. If new value is 0, add 15000 gas to refund counter.
|
||||
// 2.2. If original value does not equal current value (this storage slot is dirty), 200 gas is deducted. Apply both of the following clauses.
|
||||
// 2.2.1. If original value is not 0
|
||||
// 2.2.1.1. If current value is 0 (also means that new value is not 0), remove 15000 gas from refund counter. We can prove that refund counter will never go below 0.
|
||||
// 2.2.1.2. If new value is 0 (also means that current value is not 0), add 15000 gas to refund counter.
|
||||
// 2.2.2. If original value equals new value (this storage slot is reset)
|
||||
// 2.2.2.1. If original value is 0, add 19800 gas to refund counter.
|
||||
// 2.2.2.2. Otherwise, add 4800 gas to refund counter.
|
||||
value := common.BigToHash(y)
|
||||
if current == value { // noop (1)
|
||||
return params.NetSstoreNoopGas, nil
|
||||
}
|
||||
original := evm.StateDB.GetCommittedState(contract.Address(), common.BigToHash(x))
|
||||
if original == current {
|
||||
if original == (common.Hash{}) { // create slot (2.1.1)
|
||||
return params.NetSstoreInitGas, nil
|
||||
}
|
||||
if value == (common.Hash{}) { // delete slot (2.1.2b)
|
||||
evm.StateDB.AddRefund(params.NetSstoreClearRefund)
|
||||
}
|
||||
return params.NetSstoreCleanGas, nil // write existing slot (2.1.2)
|
||||
}
|
||||
if original != (common.Hash{}) {
|
||||
if current == (common.Hash{}) { // recreate slot (2.2.1.1)
|
||||
evm.StateDB.SubRefund(params.NetSstoreClearRefund)
|
||||
} else if value == (common.Hash{}) { // delete slot (2.2.1.2)
|
||||
evm.StateDB.AddRefund(params.NetSstoreClearRefund)
|
||||
}
|
||||
}
|
||||
if original == value {
|
||||
if original == (common.Hash{}) { // reset to original inexistent slot (2.2.2.1)
|
||||
evm.StateDB.AddRefund(params.NetSstoreResetClearRefund)
|
||||
} else { // reset to original existing slot (2.2.2.2)
|
||||
evm.StateDB.AddRefund(params.NetSstoreResetRefund)
|
||||
}
|
||||
}
|
||||
return params.NetSstoreDirtyGas, nil
|
||||
}
|
||||
|
||||
func makeGasLog(n uint64) gasFunc {
|
||||
|
|
|
@ -494,7 +494,7 @@ func BenchmarkOpMstore(bench *testing.B) {
|
|||
|
||||
func BenchmarkOpSHA3(bench *testing.B) {
|
||||
var (
|
||||
env = NewEVM(Context{}, nil, params.TestChainConfig, Config{})
|
||||
env = NewEVM(Context{}, nil, nil, params.TestChainConfig, Config{})
|
||||
stack = newstack()
|
||||
mem = NewMemory()
|
||||
evmInterpreter = NewEVMInterpreter(env, env.vmConfig)
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
|
||||
// Quorum uses a cut-down StateDB, MinimalApiState. We leave the methods in StateDB commented out so they'll produce a
|
||||
// conflict when upstream changes.
|
||||
//TODO(Amal): to be reviewed
|
||||
type MinimalApiState interface {
|
||||
GetBalance(addr common.Address) *big.Int
|
||||
GetCode(addr common.Address) []byte
|
||||
|
|
|
@ -50,7 +50,8 @@ func (*dummyStatedb) GetRefund() uint64 { return 1337 }
|
|||
|
||||
func TestStoreCapture(t *testing.T) {
|
||||
var (
|
||||
env = NewEVM(Context{}, &dummyStatedb{}, nil, params.TestChainConfig, Config{})
|
||||
db = &dummyStatedb{}
|
||||
env = NewEVM(Context{}, db, db, params.TestChainConfig, Config{})
|
||||
logger = NewStructLogger(nil)
|
||||
mem = NewMemory()
|
||||
stack = newstack()
|
||||
|
|
|
@ -288,7 +288,7 @@ func (s EthAPIState) GetNonce(addr common.Address) uint64 {
|
|||
return s.state.GetNonce(addr)
|
||||
}
|
||||
|
||||
// TODO: implement the following methods for Quorum
|
||||
// TODO(Amal): implement the following methods for Quorum
|
||||
func (s EthAPIState) GetProof(common.Address) ([][]byte, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
@ -562,7 +562,7 @@ func testBroadcastBlock(t *testing.T, totalPeers, broadcastExpected int) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to create new blockchain: %v", err)
|
||||
}
|
||||
pm, err := NewProtocolManager(config, downloader.FullSync, DefaultConfig.NetworkId, evmux, new(testTxPool), pow, blockchain, db)
|
||||
pm, err := NewProtocolManager(config, downloader.FullSync, DefaultConfig.NetworkId, evmux, new(testTxPool), pow, blockchain, db, false)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to start test protocol manager: %v", err)
|
||||
}
|
||||
|
|
|
@ -51,7 +51,8 @@ type dummyStatedb struct {
|
|||
func (*dummyStatedb) GetRefund() uint64 { return 1337 }
|
||||
|
||||
func runTrace(tracer *Tracer) (json.RawMessage, error) {
|
||||
env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
||||
db := &dummyStatedb{}
|
||||
env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, db, db, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
||||
|
||||
contract := vm.NewContract(account{}, account{}, big.NewInt(0), 10000)
|
||||
contract.Code = []byte{byte(vm.PUSH1), 0x1, byte(vm.PUSH1), 0x1, 0x0}
|
||||
|
@ -132,8 +133,8 @@ func TestHaltBetweenSteps(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, &dummyStatedb{}, nil, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
||||
db := &dummyStatedb{}
|
||||
env := vm.NewEVM(vm.Context{BlockNumber: big.NewInt(1)}, db, db, params.TestChainConfig, vm.Config{Debug: true, Tracer: tracer})
|
||||
contract := vm.NewContract(&account{}, &account{}, big.NewInt(0), 0)
|
||||
|
||||
tracer.CaptureState(env, 0, 0, 0, 0, nil, nil, contract, 0, nil)
|
||||
|
|
|
@ -124,6 +124,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
|
|||
}
|
||||
}
|
||||
|
||||
func (b *testWorkerBackend) ChainDb() ethdb.Database { return b.db }
|
||||
func (b *testWorkerBackend) BlockChain() *core.BlockChain { return b.chain }
|
||||
func (b *testWorkerBackend) TxPool() *core.TxPool { return b.txPool }
|
||||
func (b *testWorkerBackend) PostChainEvents(events []interface{}) {
|
||||
|
@ -153,7 +154,7 @@ func testPendingStateAndBlock(t *testing.T, chainConfig *params.ChainConfig, eng
|
|||
|
||||
// Ensure snapshot has been updated.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
block, state := w.pending()
|
||||
block, state, _ := w.pending()
|
||||
if block.NumberU64() != 1 {
|
||||
t.Errorf("block number mismatch: have %d, want %d", block.NumberU64(), 1)
|
||||
}
|
||||
|
@ -164,7 +165,7 @@ func testPendingStateAndBlock(t *testing.T, chainConfig *params.ChainConfig, eng
|
|||
|
||||
// Ensure the new tx events has been processed
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
block, state = w.pending()
|
||||
block, state, _ = w.pending()
|
||||
if balance := state.GetBalance(testUserAddress); balance.Cmp(big.NewInt(2000)) != 0 {
|
||||
t.Errorf("account balance mismatch: have %d, want %d", balance, 2000)
|
||||
}
|
||||
|
|
|
@ -368,9 +368,7 @@ func (c *Config) parsePersistentNodes(path string) []*enode.Node {
|
|||
if url == "" {
|
||||
continue
|
||||
}
|
||||
log.Info("AJ-parsePersistentNodes1", "url", url)
|
||||
node, err := enode.ParseV4(url)
|
||||
log.Info("AJ-parsePersistentNodes2", "url", url, "ID", node.ID().String(), "EnodeID", node.EnodeID())
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("Node URL %s: %v\n", url, err))
|
||||
continue
|
||||
|
|
|
@ -86,7 +86,8 @@ func (V4ID) NodeAddr(r *enr.Record) []byte {
|
|||
buf := make([]byte, 64)
|
||||
math.ReadBits(pubkey.X, buf[:32])
|
||||
math.ReadBits(pubkey.Y, buf[32:])
|
||||
return crypto.Keccak256(buf)
|
||||
b := crypto.Keccak256(buf)
|
||||
return b
|
||||
}
|
||||
|
||||
// Secp256k1 is the "secp256k1" key, which holds a public key.
|
||||
|
|
|
@ -82,6 +82,7 @@ func (n *Node) UDP() int {
|
|||
return int(port)
|
||||
}
|
||||
|
||||
//TODO: Amal to review
|
||||
// RAFTPORT returns the RAFT PORT of the node
|
||||
func (n *Node) RAFTPORT() int {
|
||||
var port enr.RAFTPORT
|
||||
|
@ -194,6 +195,34 @@ func (n *ID) UnmarshalText(text []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ID is a unique identifier for each node used by RAFT
|
||||
type EnodeID [64]byte
|
||||
|
||||
// ID prints as a long hexadecimal number.
|
||||
func (n EnodeID) String() string {
|
||||
return fmt.Sprintf("%x", n[:])
|
||||
}
|
||||
|
||||
// The Go syntax representation of a ID is a call to HexID.
|
||||
func (n EnodeID) GoString() string {
|
||||
return fmt.Sprintf("enode.HexID(\"%x\")", n[:])
|
||||
}
|
||||
|
||||
// MarshalText implements the encoding.TextMarshaler interface.
|
||||
func (n EnodeID) MarshalText() ([]byte, error) {
|
||||
return []byte(hex.EncodeToString(n[:])), nil
|
||||
}
|
||||
|
||||
// UnmarshalText implements the encoding.TextUnmarshaler interface.
|
||||
func (n *EnodeID) UnmarshalText(text []byte) error {
|
||||
id, err := RaftHexID(string(text))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*n = id
|
||||
return nil
|
||||
}
|
||||
|
||||
// HexID converts a hex string to an ID.
|
||||
// The string may be prefixed with 0x.
|
||||
// It panics if the string is not a valid ID.
|
||||
|
@ -205,6 +234,20 @@ func HexID(in string) ID {
|
|||
return id
|
||||
}
|
||||
|
||||
//TODO(Amal): to review
|
||||
func RaftHexID(in string) (EnodeID, error) {
|
||||
var id EnodeID
|
||||
b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
|
||||
if err != nil {
|
||||
return id, err
|
||||
} else if len(b) != len(id) {
|
||||
return id, fmt.Errorf("wrong length, want %d hex chars", len(id)*2)
|
||||
}
|
||||
|
||||
copy(id[:], b)
|
||||
return id, nil
|
||||
}
|
||||
|
||||
func parseID(in string) (ID, error) {
|
||||
var id ID
|
||||
b, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
|
||||
|
|
|
@ -28,7 +28,6 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/common/math"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||
)
|
||||
|
||||
|
@ -93,7 +92,7 @@ func NewV4(pubkey *ecdsa.PublicKey, ip net.IP, tcp, udp, raftPort int) *Node {
|
|||
}
|
||||
|
||||
if raftPort != 0 {
|
||||
r.Set(enr.RAFTPORT(tcp))
|
||||
r.Set(enr.RAFTPORT(raftPort))
|
||||
}
|
||||
|
||||
signV4Compat(&r, pubkey)
|
||||
|
@ -101,7 +100,6 @@ func NewV4(pubkey *ecdsa.PublicKey, ip net.IP, tcp, udp, raftPort int) *Node {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Info("NewV4", "raftPort", raftPort, "nodeId", n.ID().String(), "NodeId.bytes", n.ID().Bytes())
|
||||
return n
|
||||
}
|
||||
|
||||
|
@ -122,11 +120,9 @@ func parseComplete(rawurl string) (*Node, error) {
|
|||
if u.User == nil {
|
||||
return nil, errors.New("does not contain node ID")
|
||||
}
|
||||
log.Info("AJ-parseComplete1", "u.User", u.User.String())
|
||||
if id, err = parsePubkey(u.User.String()); err != nil {
|
||||
return nil, fmt.Errorf("invalid node ID (%v)", err)
|
||||
}
|
||||
log.Info("AJ-parseComplete2", "id", id)
|
||||
// Parse the IP address.
|
||||
host, port, err := net.SplitHostPort(u.Host)
|
||||
if err != nil {
|
||||
|
@ -187,7 +183,7 @@ func parsePubkey(in string) (*ecdsa.PublicKey, error) {
|
|||
return crypto.UnmarshalPubkey(b)
|
||||
}
|
||||
|
||||
// TODO: Amal to review it - added for RAFT
|
||||
// TODO(Amal): to review it - added for RAFT
|
||||
func (n *Node) EnodeID() string {
|
||||
var (
|
||||
scheme enr.ID
|
||||
|
@ -215,10 +211,8 @@ func (n *Node) v4URL() string {
|
|||
n.Load((*Secp256k1)(&key))
|
||||
switch {
|
||||
case scheme == "v4" || key != ecdsa.PublicKey{}:
|
||||
log.Info("AJ-schemeV4")
|
||||
nodeid = fmt.Sprintf("%x", crypto.FromECDSAPub(&key)[1:])
|
||||
default:
|
||||
log.Info("AJ-NOT schemeV4")
|
||||
nodeid = fmt.Sprintf("%s.%x", scheme, n.id[:])
|
||||
}
|
||||
u := url.URL{Scheme: "enode"}
|
||||
|
|
|
@ -40,7 +40,6 @@ import (
|
|||
"io"
|
||||
"sort"
|
||||
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
|
@ -121,7 +120,6 @@ func (r *Record) Load(e Entry) error {
|
|||
if err := rlp.DecodeBytes(r.pairs[i].v, e); err != nil {
|
||||
return &KeyError{Key: e.ENRKey(), Err: err}
|
||||
}
|
||||
log.Info("AJ-Load", "key", e.ENRKey(), "value", r.pairs[i].v)
|
||||
return nil
|
||||
}
|
||||
return &KeyError{Key: e.ENRKey(), Err: errNotFound}
|
||||
|
|
|
@ -925,8 +925,6 @@ func (srv *Server) setupConn(c *conn, flags connFlag, dialDest *enode.Node) erro
|
|||
} else {
|
||||
c.node = nodeFromConn(remotePubkey, c.fd)
|
||||
}
|
||||
log.Info("AJ-setupConn1", "remotePubkey", remotePubkey)
|
||||
log.Info("AJ-setupConn2", "c.node.ID", c.node.ID(), "c.node.ID.Bytes", c.node.ID().Bytes(), "node", c.node.String())
|
||||
clog := srv.log.New("id", c.node.ID(), "addr", c.fd.RemoteAddr(), "conn", c.flags)
|
||||
|
||||
//START - QUORUM Permissioning
|
||||
|
|
|
@ -131,16 +131,16 @@ var (
|
|||
//
|
||||
// This configuration is intentionally not using keyed fields to force anyone
|
||||
// adding flags to the config to also have to set these fields.
|
||||
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil, nil, false}
|
||||
AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil, false}
|
||||
|
||||
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
|
||||
// and accepted by the Ethereum core developers into the Clique consensus.
|
||||
//
|
||||
// This configuration is intentionally not using keyed fields to force anyone
|
||||
// adding flags to the config to also have to set these fields.
|
||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil, false}
|
||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil, false}
|
||||
|
||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil, nil, false}
|
||||
TestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil, false}
|
||||
TestRules = TestChainConfig.Rules(new(big.Int))
|
||||
|
||||
QuorumTestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, nil, common.Hash{}, nil, nil, nil, nil, nil, new(EthashConfig), nil, nil, true}
|
||||
|
|
|
@ -31,6 +31,7 @@ func (s *PublicRaftAPI) RemovePeer(raftId uint16) {
|
|||
}
|
||||
|
||||
func (s *PublicRaftAPI) Leader() (string, error) {
|
||||
|
||||
addr, err := s.raftService.raftProtocolManager.LeaderAddress()
|
||||
if nil != err {
|
||||
return "", err
|
||||
|
|
|
@ -23,17 +23,16 @@ import (
|
|||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
|
||||
"crypto/ecdsa"
|
||||
"github.com/coreos/etcd/etcdserver/stats"
|
||||
raftTypes "github.com/coreos/etcd/pkg/types"
|
||||
etcdRaft "github.com/coreos/etcd/raft"
|
||||
"github.com/coreos/etcd/raft/raftpb"
|
||||
"github.com/coreos/etcd/rafthttp"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
"gopkg.in/fatih/set.v0"
|
||||
|
||||
"github.com/deckarep/golang-set"
|
||||
)
|
||||
|
||||
type ProtocolManager struct {
|
||||
|
@ -56,7 +55,7 @@ type ProtocolManager struct {
|
|||
// Remote peer state (protected by mu vs concurrent access via JS)
|
||||
leader uint16
|
||||
peers map[uint16]*Peer
|
||||
removedPeers *set.Set // *Permanently removed* peers
|
||||
removedPeers mapset.Set // *Permanently removed* peers
|
||||
|
||||
// P2P transport
|
||||
p2pServer *p2p.Server // Initialized in start()
|
||||
|
@ -107,7 +106,7 @@ func NewProtocolManager(raftId uint16, raftPort uint16, blockchain *core.BlockCh
|
|||
bootstrapNodes: bootstrapNodes,
|
||||
peers: make(map[uint16]*Peer),
|
||||
leader: uint16(etcdRaft.None),
|
||||
removedPeers: set.New(set.ThreadSafe).(*set.Set),
|
||||
removedPeers: mapset.NewSet(),
|
||||
joinExisting: joinExisting,
|
||||
blockchain: blockchain,
|
||||
eventMux: mux,
|
||||
|
@ -201,10 +200,12 @@ func (pm *ProtocolManager) NodeInfo() *RaftNodeInfo {
|
|||
peerIdx += 1
|
||||
}
|
||||
|
||||
removedPeerIfaces := pm.removedPeers.List()
|
||||
removedPeerIds := make([]uint16, len(removedPeerIfaces))
|
||||
for i, removedIface := range removedPeerIfaces {
|
||||
removedPeerIfaces := pm.removedPeers
|
||||
removedPeerIds := make([]uint16, removedPeerIfaces.Cardinality())
|
||||
i := 0
|
||||
for removedIface := range removedPeerIfaces.Iterator().C {
|
||||
removedPeerIds[i] = removedIface.(uint16)
|
||||
i++
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -247,8 +248,8 @@ func (pm *ProtocolManager) nextRaftId() uint16 {
|
|||
}
|
||||
}
|
||||
|
||||
removedPeerIfaces := pm.removedPeers.List()
|
||||
for _, removedIface := range removedPeerIfaces {
|
||||
removedPeerIfaces := pm.removedPeers
|
||||
for removedIface := range removedPeerIfaces.Iterator().C {
|
||||
removedId := removedIface.(uint16)
|
||||
|
||||
if maxId < removedId {
|
||||
|
@ -263,7 +264,7 @@ func (pm *ProtocolManager) isRaftIdRemoved(id uint16) bool {
|
|||
pm.mu.RLock()
|
||||
defer pm.mu.RUnlock()
|
||||
|
||||
return pm.removedPeers.Has(id)
|
||||
return pm.removedPeers.Contains(id)
|
||||
}
|
||||
|
||||
func (pm *ProtocolManager) isRaftIdUsed(raftId uint16) bool {
|
||||
|
@ -286,14 +287,14 @@ func (pm *ProtocolManager) isNodeAlreadyInCluster(node *enode.Node) error {
|
|||
peerNode := peer.p2pNode
|
||||
|
||||
if peerNode.ID() == node.ID() {
|
||||
return fmt.Errorf("node with this enode has already been added to the cluster: %v", node.ID)
|
||||
return fmt.Errorf("node with this enode has already been added to the cluster: %s", node.ID())
|
||||
}
|
||||
|
||||
if peerNode.IP().Equal(node.IP()) {
|
||||
if peerNode.TCP() == node.TCP() {
|
||||
return fmt.Errorf("existing node %v with raft ID %v is already using eth p2p at %v:%v", peerNode.ID, peerRaftId, node.IP, node.TCP)
|
||||
return fmt.Errorf("existing node %v with raft ID %v is already using eth p2p at %v:%v", peerNode.ID(), peerRaftId, node.IP(), node.TCP())
|
||||
} else if peer.address.RaftPort == enr.RAFTPORT(node.RAFTPORT()) {
|
||||
return fmt.Errorf("existing node %v with raft ID %v is already using raft at %v:%v", peerNode.ID, peerRaftId, node.IP, node.RAFTPORT())
|
||||
return fmt.Errorf("existing node %v with raft ID %v is already using raft at %v:%v", peerNode.ID(), peerRaftId, node.IP(), node.RAFTPORT())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -641,31 +642,21 @@ func raftUrl(address *Address) string {
|
|||
return fmt.Sprintf("http://%s:%d", address.Ip, address.RaftPort)
|
||||
}
|
||||
|
||||
func decodePubkey64(b []byte) (*ecdsa.PublicKey, error) {
|
||||
return crypto.UnmarshalPubkey(append([]byte{0x04}, b...))
|
||||
}
|
||||
|
||||
func (pm *ProtocolManager) addPeer(address *Address) {
|
||||
pm.mu.Lock()
|
||||
defer pm.mu.Unlock()
|
||||
|
||||
raftId := address.RaftId
|
||||
|
||||
log.Info("AJ-addPeer:", "raftId", raftId, "nodeId", address.NodeId.String(), "bytes", address.NodeId.Bytes(), "address", address)
|
||||
|
||||
//TODO: Amal to confirm if this decoding is correct
|
||||
//pubKey, err := decodePubkey64(address.NodeId.Bytes())
|
||||
|
||||
/*if err != nil {
|
||||
log.Error("AJ-error decoding pub key", "nodeId", address.NodeId.String(), "err", err)
|
||||
return
|
||||
}*/
|
||||
|
||||
log.Info("addPeer: decoded pub key", "pubKey", address.PubKey)
|
||||
//TODO(Amal): to review
|
||||
pubKey, err := enode.HexPubkey(address.NodeId.String())
|
||||
if err != nil {
|
||||
log.Error("error decoding pub key from enodeId", "enodeId", address.NodeId.String(), "err", err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Add P2P connection:
|
||||
p2pNode := enode.NewV4(address.PubKey, address.Ip, 0, int(address.P2pPort), 0)
|
||||
log.Info("AJ-p2pNode", "ID1", address.NodeId.String(), "ID2", p2pNode.ID().String())
|
||||
p2pNode := enode.NewV4(pubKey, address.Ip, 0, int(address.P2pPort), int(address.RaftPort))
|
||||
pm.p2pServer.AddPeer(p2pNode)
|
||||
|
||||
// Add raft transport connection:
|
||||
|
@ -858,7 +849,6 @@ func (pm *ProtocolManager) makeInitialRaftPeers() (raftPeers []etcdRaft.Peer, pe
|
|||
// requiring the use of static peers for the initial set, and load them from e.g. another JSON file which
|
||||
// contains pairs of enodes and raft ports, or we can get this initial peer list from commandline flags.
|
||||
address := newAddress(raftId, node.RAFTPORT(), node)
|
||||
|
||||
raftPeers[i] = etcdRaft.Peer{
|
||||
ID: uint64(raftId),
|
||||
Context: address.toBytes(),
|
||||
|
|
23
raft/peer.go
23
raft/peer.go
|
@ -5,38 +5,35 @@ import (
|
|||
"net"
|
||||
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"crypto/ecdsa"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/p2p/enr"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"log"
|
||||
)
|
||||
|
||||
const nodeIDBits = 512
|
||||
|
||||
type EnodeID [nodeIDBits / 8]byte
|
||||
|
||||
// Serializable information about a Peer. Sufficient to build `etcdRaft.Peer`
|
||||
// or `discover.Node`.
|
||||
type Address struct {
|
||||
RaftId uint16 `json:"raftId"`
|
||||
NodeId [64]byte `json:"nodeId"`
|
||||
NodeId enode.EnodeID `json:"nodeId"`
|
||||
Ip net.IP `json:"ip"`
|
||||
P2pPort enr.TCP `json:"p2pPort"`
|
||||
RaftPort enr.RAFTPORT `json:"raftPort"`
|
||||
PubKey *ecdsa.PublicKey
|
||||
}
|
||||
|
||||
// TODO(Amal): to review
|
||||
|
||||
func newAddress(raftId uint16, raftPort int, node *enode.Node) *Address {
|
||||
node.ID().Bytes()
|
||||
id, err := enode.RaftHexID(node.EnodeID())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return &Address{
|
||||
RaftId: raftId,
|
||||
NodeId: []byte(node.EnodeID()),
|
||||
NodeId: id,
|
||||
Ip: node.IP(),
|
||||
P2pPort: enr.TCP(node.TCP()),
|
||||
RaftPort: enr.RAFTPORT(raftPort),
|
||||
PubKey: node.Pubkey(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +51,7 @@ func (addr *Address) DecodeRLP(s *rlp.Stream) error {
|
|||
// These fields need to be public:
|
||||
var temp struct {
|
||||
RaftId uint16
|
||||
NodeId enode.ID
|
||||
NodeId enode.EnodeID
|
||||
Ip net.IP
|
||||
P2pPort enr.TCP
|
||||
RaftPort enr.RAFTPORT
|
||||
|
|
|
@ -10,12 +10,12 @@ import (
|
|||
"github.com/coreos/etcd/raft/raftpb"
|
||||
"github.com/coreos/etcd/snap"
|
||||
"github.com/coreos/etcd/wal/walpb"
|
||||
"github.com/deckarep/golang-set"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"gopkg.in/fatih/set.v0"
|
||||
)
|
||||
|
||||
// Snapshot
|
||||
|
@ -37,9 +37,7 @@ func (pm *ProtocolManager) buildSnapshot() *Snapshot {
|
|||
defer pm.mu.RUnlock()
|
||||
|
||||
numNodes := len(pm.confState.Nodes)
|
||||
log.Info("AJ-numNodes", "nodesSize", numNodes, "nodes", pm.confState.Nodes)
|
||||
log.Info("AJ-peers", "pm.peers", pm.peers)
|
||||
numRemovedNodes := pm.removedPeers.Size()
|
||||
numRemovedNodes := pm.removedPeers.Cardinality()
|
||||
|
||||
snapshot := &Snapshot{
|
||||
addresses: make([]Address, numNodes),
|
||||
|
@ -61,9 +59,10 @@ func (pm *ProtocolManager) buildSnapshot() *Snapshot {
|
|||
sort.Sort(ByRaftId(snapshot.addresses))
|
||||
|
||||
// Populate removed IDs
|
||||
|
||||
for i, removedIface := range pm.removedPeers.List() {
|
||||
i := 0
|
||||
for removedIface := range pm.removedPeers.Iterator().C {
|
||||
snapshot.removedRaftIds[i] = removedIface.(uint16)
|
||||
i++
|
||||
}
|
||||
|
||||
return snapshot
|
||||
|
@ -101,8 +100,8 @@ func (pm *ProtocolManager) triggerSnapshot(index uint64) {
|
|||
pm.mu.Unlock()
|
||||
}
|
||||
|
||||
func confStateIdSet(confState raftpb.ConfState) *set.Set {
|
||||
set := set.New(set.ThreadSafe).(*set.Set)
|
||||
func confStateIdSet(confState raftpb.ConfState) mapset.Set {
|
||||
set := mapset.NewSet()
|
||||
for _, rawRaftId := range confState.Nodes {
|
||||
set.Add(uint16(rawRaftId))
|
||||
}
|
||||
|
@ -117,7 +116,7 @@ func (pm *ProtocolManager) updateClusterMembership(newConfState raftpb.ConfState
|
|||
// Update tombstones for permanently removed peers. For simplicity we do not
|
||||
// allow the re-use of peer IDs once a peer is removed.
|
||||
|
||||
removedPeers := set.New(set.ThreadSafe).(*set.Set)
|
||||
removedPeers := mapset.NewSet()
|
||||
for _, removedRaftId := range removedRaftIds {
|
||||
removedPeers.Add(removedRaftId)
|
||||
}
|
||||
|
@ -129,8 +128,8 @@ func (pm *ProtocolManager) updateClusterMembership(newConfState raftpb.ConfState
|
|||
|
||||
prevIds := confStateIdSet(prevConfState)
|
||||
newIds := confStateIdSet(newConfState)
|
||||
idsToRemove := set.Difference(prevIds, newIds)
|
||||
for _, idIfaceToRemove := range idsToRemove.List() {
|
||||
idsToRemove := prevIds.Difference(newIds)
|
||||
for idIfaceToRemove := range idsToRemove.Iterator().C {
|
||||
raftId := idIfaceToRemove.(uint16)
|
||||
log.Info("removing old raft peer", "peer id", raftId)
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
|
||||
"gopkg.in/fatih/set.v0"
|
||||
lane "gopkg.in/oleiade/lane.v1"
|
||||
"github.com/deckarep/golang-set"
|
||||
"gopkg.in/oleiade/lane.v1"
|
||||
)
|
||||
|
||||
// The speculative chain represents blocks that we have minted which haven't been accepted into the chain yet, building
|
||||
|
@ -21,16 +21,16 @@ import (
|
|||
type speculativeChain struct {
|
||||
head *types.Block
|
||||
unappliedBlocks *lane.Deque
|
||||
expectedInvalidBlockHashes *set.Set // This is thread-safe. This set is referred to as our "guard" below.
|
||||
proposedTxes *set.Set // This is thread-safe.
|
||||
expectedInvalidBlockHashes mapset.Set // This is thread-safe. This set is referred to as our "guard" below.
|
||||
proposedTxes mapset.Set // This is thread-safe.
|
||||
}
|
||||
|
||||
func newSpeculativeChain() *speculativeChain {
|
||||
return &speculativeChain{
|
||||
head: nil,
|
||||
unappliedBlocks: lane.NewDeque(),
|
||||
expectedInvalidBlockHashes: set.New(set.ThreadSafe).(*set.Set),
|
||||
proposedTxes: set.New(set.ThreadSafe).(*set.Set),
|
||||
expectedInvalidBlockHashes: mapset.NewSet(),
|
||||
proposedTxes: mapset.NewSet(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ func (chain *speculativeChain) unwindFrom(invalidHash common.Hash, headBlock *ty
|
|||
|
||||
// check our "guard" to see if this is a (descendant) block we're
|
||||
// expected to be ruled invalid. if we find it, remove from the guard
|
||||
if chain.expectedInvalidBlockHashes.Has(invalidHash) {
|
||||
if chain.expectedInvalidBlockHashes.Contains(invalidHash) {
|
||||
log.Info("Removing expected-invalid block from guard.", "block", invalidHash)
|
||||
|
||||
chain.expectedInvalidBlockHashes.Remove(invalidHash)
|
||||
|
@ -140,7 +140,9 @@ func (chain *speculativeChain) recordProposedTransactions(txes types.Transaction
|
|||
for i, tx := range txes {
|
||||
txHashIs[i] = tx.Hash()
|
||||
}
|
||||
chain.proposedTxes.Add(txHashIs...)
|
||||
for _, i := range txHashIs {
|
||||
chain.proposedTxes.Add(i)
|
||||
}
|
||||
}
|
||||
|
||||
// Removes txes in block from our "blacklist" of "proposed tx" hashes. When we
|
||||
|
@ -161,7 +163,9 @@ func (chain *speculativeChain) removeProposedTxes(block *types.Block) {
|
|||
// here and in mintNewBlock concurrently. using a finer-grained set-specific
|
||||
// lock here is preferable, because mintNewBlock holds its locks for a
|
||||
// nontrivial amount of time.
|
||||
chain.proposedTxes.Remove(minedTxInterfaces...)
|
||||
for _, i := range minedTxInterfaces {
|
||||
chain.proposedTxes.Remove(i)
|
||||
}
|
||||
}
|
||||
|
||||
func (chain *speculativeChain) withoutProposedTxes(addrTxes AddressTxes) AddressTxes {
|
||||
|
@ -170,7 +174,7 @@ func (chain *speculativeChain) withoutProposedTxes(addrTxes AddressTxes) Address
|
|||
for addr, txes := range addrTxes {
|
||||
filteredTxes := make(types.Transactions, 0)
|
||||
for _, tx := range txes {
|
||||
if !chain.proposedTxes.Has(tx.Hash()) {
|
||||
if !chain.proposedTxes.Contains(tx.Hash()) {
|
||||
filteredTxes = append(filteredTxes, tx)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue