Skip to content

Commit

Permalink
Merge 359e9dd into 151895d
Browse files Browse the repository at this point in the history
  • Loading branch information
erickyan86 committed Aug 2, 2019
2 parents 151895d + 359e9dd commit 08f553b
Show file tree
Hide file tree
Showing 6 changed files with 91 additions and 85 deletions.
18 changes: 9 additions & 9 deletions ftservice/apibackend.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,24 +196,24 @@ func (b *APIBackend) GetTd(blockHash common.Hash) *big.Int {
return b.ftservice.blockchain.GetTdByHash(blockHash)
}

func (b *APIBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {
func (b *APIBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) *types.Header {
if blockNr == rpc.LatestBlockNumber {
return b.ftservice.blockchain.CurrentBlock().Header(), nil
return b.ftservice.blockchain.CurrentBlock().Header()
}
return b.ftservice.blockchain.GetHeaderByNumber(uint64(blockNr)), nil
return b.ftservice.blockchain.GetHeaderByNumber(uint64(blockNr))
}

func (b *APIBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) {
func (b *APIBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) *types.Block {
if blockNr == rpc.LatestBlockNumber {
return b.ftservice.blockchain.CurrentBlock(), nil
return b.ftservice.blockchain.CurrentBlock()
}
return b.ftservice.blockchain.GetBlockByNumber(uint64(blockNr)), nil
return b.ftservice.blockchain.GetBlockByNumber(uint64(blockNr))
}

func (b *APIBackend) StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
header, err := b.HeaderByNumber(ctx, blockNr)
if header == nil || err != nil {
return nil, nil, err
header := b.HeaderByNumber(ctx, blockNr)
if header == nil {
return nil, nil, nil
}
stateDb, err := b.ftservice.blockchain.StateAt(b.ftservice.blockchain.CurrentBlock().Root())
return stateDb, header, err
Expand Down
64 changes: 24 additions & 40 deletions ftservice/gasprice/gasprice.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package gasprice

import (
"context"
"fmt"
"math/big"
"sort"
"sync"
Expand All @@ -28,8 +29,8 @@ import (
)

type backend interface {
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error)
BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error)
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) *types.Header
BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) *types.Block
}

//Config gas price oracle config
Expand All @@ -41,13 +42,14 @@ type Config struct {
// Oracle recommends gas prices based on the content of recent
// blocks.
type Oracle struct {
backend backend
lastHead common.Hash
lastPrice *big.Int
cacheLock sync.RWMutex
fetchLock sync.Mutex

checkBlocks, maxEmpty, maxBlocks int
backend backend
defaultPrice *big.Int
lastHead common.Hash
lastPrice *big.Int
cacheLock sync.RWMutex
fetchLock sync.Mutex

checkBlocks int
}

// NewOracle returns a new oracle.
Expand All @@ -57,11 +59,10 @@ func NewOracle(backend backend, params Config) *Oracle {
blocks = 1
}
return &Oracle{
backend: backend,
lastPrice: params.Default,
checkBlocks: blocks,
maxEmpty: blocks / 2,
maxBlocks: blocks * 5,
defaultPrice: params.Default,
backend: backend,
lastPrice: params.Default,
checkBlocks: blocks,
}
}

Expand All @@ -72,10 +73,7 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
lastPrice := gpo.lastPrice
gpo.cacheLock.RUnlock()

head, err := gpo.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)
if err != nil {
return lastPrice, nil
}
head := gpo.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber)

headHash := head.Hash()
if headHash == lastHead {
Expand Down Expand Up @@ -107,29 +105,15 @@ func (gpo *Oracle) SuggestPrice(ctx context.Context) (*big.Int, error) {
exp++
blockNum--
}
maxEmpty := gpo.maxEmpty
for exp > 0 {
res := <-ch
if res.err != nil {
return lastPrice, res.err
}
exp--
if res.price != nil {
prices = new(big.Int).Add(prices, new(big.Int).Mul(res.price, res.weight))
weights = new(big.Int).Add(weights, res.weight)
continue
}
if maxEmpty > 0 {
maxEmpty--
continue
}

if blockNum > 0 && sent < gpo.maxBlocks {
go gpo.getBlockPrices(ctx, blockNum, ch)
sent++
exp++
blockNum--
}
fmt.Println("------->", res.price, res.weight)
prices = new(big.Int).Add(prices, new(big.Int).Mul(res.price, res.weight))
weights = new(big.Int).Add(weights, res.weight)
}

price := lastPrice
Expand Down Expand Up @@ -159,26 +143,26 @@ func (t transactionsByGasPrice) Less(i, j int) bool { return t[i].GasPrice().Cmp
// getBlockPrices calculates the lowest transaction gas price in a given block
// and sends it to the result channel. If the block is empty, price is nil.
func (gpo *Oracle) getBlockPrices(ctx context.Context, blockNum uint64, ch chan getBlockPricesResult) {
block, err := gpo.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNum))
block := gpo.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNum))
if block == nil {
ch <- getBlockPricesResult{nil, nil, err}
ch <- getBlockPricesResult{nil, nil, fmt.Errorf("not found block %v", blockNum)}
return
}

blockTxs := block.Transactions()
txs := make([]*types.Transaction, len(blockTxs))

copy(txs, blockTxs)
sort.Sort(transactionsByGasPrice(txs))
for _, tx := range txs {
sender := tx.GetActions()[0].Sender()
if err == nil && sender != block.Coinbase() {
if sender != block.Coinbase() {
ch <- getBlockPricesResult{
new(big.Int).Div(big.NewInt(int64(block.GasUsed()*1000)),
big.NewInt(int64(block.GasLimit()))),
tx.GasPrice(), nil}
return
}
}
ch <- getBlockPricesResult{nil, nil, nil}
// if block no transaction the weight is the biggest,price is default price
ch <- getBlockPricesResult{big.NewInt(1 * 1000), gpo.defaultPrice, nil}
}
23 changes: 13 additions & 10 deletions ftservice/gasprice/gasprice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,29 +33,32 @@ type testBlockChain struct {

func newTestBlockChain(price *big.Int) *testBlockChain {
blocks := make(map[int]*types.Block)
for i := 0; i < 5; i++ {
for i := 0; i < 6; i++ {
if i%2 == 0 {
price = new(big.Int).Mul(price, big.NewInt(2))
}
block := &types.Block{Head: &types.Header{Number: big.NewInt(int64(i)), GasLimit: params.BlockGasLimit, GasUsed: uint64((i + 1) * 100000)}}
action := types.NewAction(types.CreateContract, "gpotestname", "", 1,
10, 10, nil, nil, nil)
block.Txs = []*types.Transaction{types.NewTransaction(1, price, action)}
if i < 5 { // blocks[5] no transaction
action := types.NewAction(types.CreateContract, "gpotestname", "", 1,
10, 10, nil, nil, nil)
block.Txs = []*types.Transaction{types.NewTransaction(1, price, action)}
}
blocks[i] = block
}

return &testBlockChain{
blocks: blocks,
}
}
func (b *testBlockChain) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) {
func (b *testBlockChain) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) *types.Header {
if blockNr == rpc.LatestBlockNumber {
return b.blocks[len(b.blocks)-1].Header(), nil
return b.blocks[len(b.blocks)-1].Header()
}
return b.blocks[int(blockNr)].Header(), nil
return b.blocks[int(blockNr)].Header()
}

func (b *testBlockChain) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) {
return b.blocks[int(blockNr)], nil
func (b *testBlockChain) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) *types.Block {
return b.blocks[int(blockNr)]
}

func TestSuggestPrice(t *testing.T) {
Expand All @@ -70,5 +73,5 @@ func TestSuggestPrice(t *testing.T) {
if err != nil {
t.Fatal(err)
}
assert.Equal(t, big.NewInt(5), gasPrice)
assert.Equal(t, price, gasPrice)
}
4 changes: 2 additions & 2 deletions rpcapi/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ type Backend interface {

// BlockChain API
CurrentBlock() *types.Block
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error)
BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error)
HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) *types.Header
BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) *types.Block
StateAndHeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*state.StateDB, *types.Header, error)
GetBlock(ctx context.Context, blockHash common.Hash) (*types.Block, error)
GetReceipts(ctx context.Context, blockHash common.Hash) ([]*types.Receipt, error)
Expand Down
30 changes: 12 additions & 18 deletions rpcapi/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash comm

// GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all
// transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
block, err := s.b.BlockByNumber(ctx, blockNr)
func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) map[string]interface{} {
block := s.b.BlockByNumber(ctx, blockNr)
if block != nil {
response := s.rpcOutputBlock(s.b.ChainConfig().ChainID, block, true, fullTx)
return response, err
return response
}
return nil, err
return nil
}

// rpcOutputBlock uses the generalized output filler, then adds the total difficulty field, which requires
Expand Down Expand Up @@ -113,14 +113,14 @@ func (s *PublicBlockChainAPI) GetTransactionReceipt(ctx context.Context, hash co
return receipt.NewRPCReceipt(blockHash, blockNumber, index, tx), nil
}

func (s *PublicBlockChainAPI) GetBlockAndResultByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.BlockAndResult, error) {
func (s *PublicBlockChainAPI) GetBlockAndResultByNumber(ctx context.Context, blockNr rpc.BlockNumber) *types.BlockAndResult {
r := s.b.GetBlockDetailLog(ctx, blockNr)
if r == nil {
return nil, nil
return nil
}
block, err := s.GetBlockByNumber(ctx, blockNr, true)
block := s.GetBlockByNumber(ctx, blockNr, true)
r.Block = block
return r, err
return r
}

// checkRangeInputArgs checks the input arguments of
Expand Down Expand Up @@ -313,10 +313,7 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (h
hi = uint64(args.Gas)
} else {
// Retrieve the current pending block to act as the gas ceiling
block, err := s.b.BlockByNumber(ctx, rpc.LatestBlockNumber)
if err != nil {
return 0, err
}
block := s.b.BlockByNumber(ctx, rpc.LatestBlockNumber)
hi = block.GasLimit()
}
cap = hi
Expand Down Expand Up @@ -349,12 +346,9 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (h
}

// GetChainConfig returns chain config.
func (s *PublicBlockChainAPI) GetChainConfig(ctx context.Context) (*params.ChainConfig, error) {
g, err := s.b.BlockByNumber(ctx, 0)
if err != nil {
return nil, err
}
return rawdb.ReadChainConfig(s.b.ChainDb(), g.Hash()), nil
func (s *PublicBlockChainAPI) GetChainConfig(ctx context.Context) *params.ChainConfig {
g := s.b.BlockByNumber(ctx, 0)
return rawdb.ReadChainConfig(s.b.ChainDb(), g.Hash())
}

// PrivateBlockChainAPI provides an API to access the blockchain.
Expand Down
37 changes: 31 additions & 6 deletions txpool/txpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ var (
evictionInterval = 15 * time.Minute // Time interval to check for evictable transactions
statsReportInterval = 10 * time.Second // Time interval to report transaction pool stats
resendTxInterval = 10 * time.Minute // Time interval to resend transaction

maxResendTxs = 256
)

const (
Expand Down Expand Up @@ -294,17 +296,19 @@ func (tp *TxPool) loop() {
// Handle inactive account transaction resend
case <-resend.C:
tp.mu.Lock()

var resendTxsCount int

for name := range tp.pending {
if time.Since(tp.beats[name]) > tp.config.ResendTime {
if txs := tp.pending[name].Flatten(); len(txs) != 0 {
events := []*event.Event{
{Typecode: event.NewTxs, Data: txs},
}
go event.SendEvents(events)
log.Debug("resend account transactions", "name", name, "txlen", len(txs))
resendTxsFunc(txs)
resendTxsCount = resendTxsCount + len(txs)
}
}
}

log.Debug("resend account transactions", "txlen", resendTxsCount)
tp.mu.Unlock()
// Handle local transaction journal rotation
case <-journal.C:
Expand All @@ -319,6 +323,27 @@ func (tp *TxPool) loop() {
}
}

func resendTxsFunc(txs []*types.Transaction) {
sendFunc := func(sendTxs []*types.Transaction) {
events := []*event.Event{
{Typecode: event.NewTxs, Data: sendTxs},
}
go event.SendEvents(events)

}

if len(txs) > maxResendTxs {
sendFunc(txs[:maxResendTxs])
if len(txs[maxResendTxs:]) > maxResendTxs {
resendTxsFunc(txs[maxResendTxs:])
} else {
sendFunc(txs[maxResendTxs:])
}
} else {
sendFunc(txs)
}
}

// requestPromoteExecutables requests a pool reset to the new head block.
// The returned channel is closed when the reset has occurred.
func (tp *TxPool) requestReset(oldHead *types.Header, newHead *types.Header) chan struct{} {
Expand Down Expand Up @@ -904,7 +929,7 @@ func (tp *TxPool) addTxs(txs []*types.Transaction, local, sync bool) []error {
}

tp.mu.Lock()
errs, dirtyNames := tp.addTxsLocked(txs, local)
errs, dirtyNames := tp.addTxsLocked(addedTxs, local)
tp.mu.Unlock()

done := tp.requestPromoteExecutables(dirtyNames)
Expand Down

0 comments on commit 08f553b

Please sign in to comment.