mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 09:53:48 +00:00
Update Go Callisto master from go-ethereum master
This commit is contained in:
commit
e31a91ce52
16 changed files with 372 additions and 138 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -34,6 +34,9 @@ profile.cov
|
||||||
# IdeaIDE
|
# IdeaIDE
|
||||||
.idea
|
.idea
|
||||||
|
|
||||||
|
# VS Code
|
||||||
|
.vscode
|
||||||
|
|
||||||
# dashboard
|
# dashboard
|
||||||
/dashboard/assets/flow-typed
|
/dashboard/assets/flow-typed
|
||||||
/dashboard/assets/node_modules
|
/dashboard/assets/node_modules
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,6 @@ type parityChainSpec struct {
|
||||||
Params struct {
|
Params struct {
|
||||||
MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
|
MinimumDifficulty *hexutil.Big `json:"minimumDifficulty"`
|
||||||
DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
|
DifficultyBoundDivisor *hexutil.Big `json:"difficultyBoundDivisor"`
|
||||||
GasLimitBoundDivisor hexutil.Uint64 `json:"gasLimitBoundDivisor"`
|
|
||||||
DurationLimit *hexutil.Big `json:"durationLimit"`
|
DurationLimit *hexutil.Big `json:"durationLimit"`
|
||||||
BlockReward *hexutil.Big `json:"blockReward"`
|
BlockReward *hexutil.Big `json:"blockReward"`
|
||||||
HomesteadTransition uint64 `json:"homesteadTransition"`
|
HomesteadTransition uint64 `json:"homesteadTransition"`
|
||||||
|
|
@ -188,6 +187,7 @@ type parityChainSpec struct {
|
||||||
Params struct {
|
Params struct {
|
||||||
MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
|
MaximumExtraDataSize hexutil.Uint64 `json:"maximumExtraDataSize"`
|
||||||
MinGasLimit hexutil.Uint64 `json:"minGasLimit"`
|
MinGasLimit hexutil.Uint64 `json:"minGasLimit"`
|
||||||
|
GasLimitBoundDivisor hexutil.Uint64 `json:"gasLimitBoundDivisor"`
|
||||||
NetworkID hexutil.Uint64 `json:"networkID"`
|
NetworkID hexutil.Uint64 `json:"networkID"`
|
||||||
MaxCodeSize uint64 `json:"maxCodeSize"`
|
MaxCodeSize uint64 `json:"maxCodeSize"`
|
||||||
EIP155Transition uint64 `json:"eip155Transition"`
|
EIP155Transition uint64 `json:"eip155Transition"`
|
||||||
|
|
@ -270,7 +270,6 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
|
||||||
}
|
}
|
||||||
spec.Engine.Ethash.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
|
spec.Engine.Ethash.Params.MinimumDifficulty = (*hexutil.Big)(params.MinimumDifficulty)
|
||||||
spec.Engine.Ethash.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor)
|
spec.Engine.Ethash.Params.DifficultyBoundDivisor = (*hexutil.Big)(params.DifficultyBoundDivisor)
|
||||||
spec.Engine.Ethash.Params.GasLimitBoundDivisor = (hexutil.Uint64)(params.GasLimitBoundDivisor)
|
|
||||||
spec.Engine.Ethash.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit)
|
spec.Engine.Ethash.Params.DurationLimit = (*hexutil.Big)(params.DurationLimit)
|
||||||
spec.Engine.Ethash.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward)
|
spec.Engine.Ethash.Params.BlockReward = (*hexutil.Big)(ethash.FrontierBlockReward)
|
||||||
spec.Engine.Ethash.Params.HomesteadTransition = genesis.Config.HomesteadBlock.Uint64()
|
spec.Engine.Ethash.Params.HomesteadTransition = genesis.Config.HomesteadBlock.Uint64()
|
||||||
|
|
@ -284,6 +283,7 @@ func newParityChainSpec(network string, genesis *core.Genesis, bootnodes []strin
|
||||||
|
|
||||||
spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
|
spec.Params.MaximumExtraDataSize = (hexutil.Uint64)(params.MaximumExtraDataSize)
|
||||||
spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
|
spec.Params.MinGasLimit = (hexutil.Uint64)(params.MinGasLimit)
|
||||||
|
spec.Params.GasLimitBoundDivisor = (hexutil.Uint64)(params.GasLimitBoundDivisor)
|
||||||
spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64())
|
spec.Params.NetworkID = (hexutil.Uint64)(genesis.Config.ChainId.Uint64())
|
||||||
spec.Params.MaxCodeSize = params.MaxCodeSize
|
spec.Params.MaxCodeSize = params.MaxCodeSize
|
||||||
spec.Params.EIP155Transition = genesis.Config.EIP155Block.Uint64()
|
spec.Params.EIP155Transition = genesis.Config.EIP155Block.Uint64()
|
||||||
|
|
|
||||||
|
|
@ -76,14 +76,14 @@ var (
|
||||||
|
|
||||||
// cmd arguments
|
// cmd arguments
|
||||||
var (
|
var (
|
||||||
bootstrapMode = flag.Bool("standalone", false, "boostrap node: don't actively connect to peers, wait for incoming connections")
|
bootstrapMode = flag.Bool("standalone", false, "boostrap node: don't initiate connection to peers, just wait for incoming connections")
|
||||||
forwarderMode = flag.Bool("forwarder", false, "forwarder mode: only forward messages, neither send nor decrypt messages")
|
forwarderMode = flag.Bool("forwarder", false, "forwarder mode: only forward messages, neither encrypt nor decrypt messages")
|
||||||
mailServerMode = flag.Bool("mailserver", false, "mail server mode: delivers expired messages on demand")
|
mailServerMode = flag.Bool("mailserver", false, "mail server mode: delivers expired messages on demand")
|
||||||
requestMail = flag.Bool("mailclient", false, "request expired messages from the bootstrap server")
|
requestMail = flag.Bool("mailclient", false, "request expired messages from the bootstrap server")
|
||||||
asymmetricMode = flag.Bool("asym", false, "use asymmetric encryption")
|
asymmetricMode = flag.Bool("asym", false, "use asymmetric encryption")
|
||||||
generateKey = flag.Bool("generatekey", false, "generate and show the private key")
|
generateKey = flag.Bool("generatekey", false, "generate and show the private key")
|
||||||
fileExMode = flag.Bool("fileexchange", false, "file exchange mode")
|
fileExMode = flag.Bool("fileexchange", false, "file exchange mode")
|
||||||
testMode = flag.Bool("test", false, "use of predefined parameters for diagnostics")
|
testMode = flag.Bool("test", false, "use of predefined parameters for diagnostics (password, etc.)")
|
||||||
echoMode = flag.Bool("echo", false, "echo mode: prints some arguments for diagnostics")
|
echoMode = flag.Bool("echo", false, "echo mode: prints some arguments for diagnostics")
|
||||||
|
|
||||||
argVerbosity = flag.Int("verbosity", int(log.LvlError), "log verbosity level")
|
argVerbosity = flag.Int("verbosity", int(log.LvlError), "log verbosity level")
|
||||||
|
|
@ -99,7 +99,7 @@ var (
|
||||||
argIDFile = flag.String("idfile", "", "file name with node id (private key)")
|
argIDFile = flag.String("idfile", "", "file name with node id (private key)")
|
||||||
argEnode = flag.String("boot", "", "bootstrap node you want to connect to (e.g. enode://e454......08d50@52.176.211.200:16428)")
|
argEnode = flag.String("boot", "", "bootstrap node you want to connect to (e.g. enode://e454......08d50@52.176.211.200:16428)")
|
||||||
argTopic = flag.String("topic", "", "topic in hexadecimal format (e.g. 70a4beef)")
|
argTopic = flag.String("topic", "", "topic in hexadecimal format (e.g. 70a4beef)")
|
||||||
argSaveDir = flag.String("savedir", "", "directory where incoming messages will be saved as files")
|
argSaveDir = flag.String("savedir", "", "directory where all incoming messages will be saved as files")
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -548,20 +548,18 @@ func messageLoop() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ticker.C:
|
case <-ticker.C:
|
||||||
messages := sf.Retrieve()
|
m1 := sf.Retrieve()
|
||||||
|
m2 := af.Retrieve()
|
||||||
|
messages := append(m1, m2...)
|
||||||
for _, msg := range messages {
|
for _, msg := range messages {
|
||||||
if *fileExMode || len(msg.Payload) > 2048 {
|
// All messages are saved upon specifying argSaveDir.
|
||||||
|
// fileExMode only specifies how messages are displayed on the console after they are saved.
|
||||||
|
// if fileExMode == true, only the hashes are displayed, since messages might be too big.
|
||||||
|
if len(*argSaveDir) > 0 {
|
||||||
writeMessageToFile(*argSaveDir, msg)
|
writeMessageToFile(*argSaveDir, msg)
|
||||||
} else {
|
|
||||||
printMessageInfo(msg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
messages = af.Retrieve()
|
if !*fileExMode && len(msg.Payload) <= 2048 {
|
||||||
for _, msg := range messages {
|
|
||||||
if *fileExMode || len(msg.Payload) > 2048 {
|
|
||||||
writeMessageToFile(*argSaveDir, msg)
|
|
||||||
} else {
|
|
||||||
printMessageInfo(msg)
|
printMessageInfo(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -281,8 +281,8 @@ func TestDeposit(t *testing.T) {
|
||||||
t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
|
t.Fatalf("expected balance %v, got %v", exp, chbook.Balance())
|
||||||
}
|
}
|
||||||
|
|
||||||
// autodeposit every 30ms if new cheque issued
|
// autodeposit every 200ms if new cheque issued
|
||||||
interval := 30 * time.Millisecond
|
interval := 200 * time.Millisecond
|
||||||
chbook.AutoDeposit(interval, common.Big1, balance)
|
chbook.AutoDeposit(interval, common.Big1, balance)
|
||||||
_, err = chbook.Issue(addr1, amount)
|
_, err = chbook.Issue(addr1, amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,8 @@ type BlockChain struct {
|
||||||
procmu sync.RWMutex // block processor lock
|
procmu sync.RWMutex // block processor lock
|
||||||
|
|
||||||
checkpoint int // checkpoint counts towards the new checkpoint
|
checkpoint int // checkpoint counts towards the new checkpoint
|
||||||
currentBlock *types.Block // Current head of the block chain
|
currentBlock atomic.Value // Current head of the block chain
|
||||||
currentFastBlock *types.Block // Current head of the fast-sync chain (may be above the block chain!)
|
currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!)
|
||||||
|
|
||||||
stateCache state.Database // State database to reuse between imports (contains state cache)
|
stateCache state.Database // State database to reuse between imports (contains state cache)
|
||||||
bodyCache *lru.Cache // Cache for the most recent block bodies
|
bodyCache *lru.Cache // Cache for the most recent block bodies
|
||||||
|
|
@ -224,10 +224,10 @@ func (bc *BlockChain) loadLastState() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Everything seems to be fine, set as the head block
|
// Everything seems to be fine, set as the head block
|
||||||
bc.currentBlock = currentBlock
|
bc.currentBlock.Store(currentBlock)
|
||||||
|
|
||||||
// Restore the last known head header
|
// Restore the last known head header
|
||||||
currentHeader := bc.currentBlock.Header()
|
currentHeader := currentBlock.Header()
|
||||||
if head := GetHeadHeaderHash(bc.db); head != (common.Hash{}) {
|
if head := GetHeadHeaderHash(bc.db); head != (common.Hash{}) {
|
||||||
if header := bc.GetHeaderByHash(head); header != nil {
|
if header := bc.GetHeaderByHash(head); header != nil {
|
||||||
currentHeader = header
|
currentHeader = header
|
||||||
|
|
@ -236,21 +236,23 @@ func (bc *BlockChain) loadLastState() error {
|
||||||
bc.hc.SetCurrentHeader(currentHeader)
|
bc.hc.SetCurrentHeader(currentHeader)
|
||||||
|
|
||||||
// Restore the last known head fast block
|
// Restore the last known head fast block
|
||||||
bc.currentFastBlock = bc.currentBlock
|
bc.currentFastBlock.Store(currentBlock)
|
||||||
if head := GetHeadFastBlockHash(bc.db); head != (common.Hash{}) {
|
if head := GetHeadFastBlockHash(bc.db); head != (common.Hash{}) {
|
||||||
if block := bc.GetBlockByHash(head); block != nil {
|
if block := bc.GetBlockByHash(head); block != nil {
|
||||||
bc.currentFastBlock = block
|
bc.currentFastBlock.Store(block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue a status log for the user
|
// Issue a status log for the user
|
||||||
|
currentFastBlock := bc.CurrentFastBlock()
|
||||||
|
|
||||||
headerTd := bc.GetTd(currentHeader.Hash(), currentHeader.Number.Uint64())
|
headerTd := bc.GetTd(currentHeader.Hash(), currentHeader.Number.Uint64())
|
||||||
blockTd := bc.GetTd(bc.currentBlock.Hash(), bc.currentBlock.NumberU64())
|
blockTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64())
|
||||||
fastTd := bc.GetTd(bc.currentFastBlock.Hash(), bc.currentFastBlock.NumberU64())
|
fastTd := bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64())
|
||||||
|
|
||||||
log.Info("Loaded most recent local header", "number", currentHeader.Number, "hash", currentHeader.Hash(), "td", headerTd)
|
log.Info("Loaded most recent local header", "number", currentHeader.Number, "hash", currentHeader.Hash(), "td", headerTd)
|
||||||
log.Info("Loaded most recent local full block", "number", bc.currentBlock.Number(), "hash", bc.currentBlock.Hash(), "td", blockTd)
|
log.Info("Loaded most recent local full block", "number", currentBlock.Number(), "hash", currentBlock.Hash(), "td", blockTd)
|
||||||
log.Info("Loaded most recent local fast block", "number", bc.currentFastBlock.Number(), "hash", bc.currentFastBlock.Hash(), "td", fastTd)
|
log.Info("Loaded most recent local fast block", "number", currentFastBlock.Number(), "hash", currentFastBlock.Hash(), "td", fastTd)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -279,30 +281,32 @@ func (bc *BlockChain) SetHead(head uint64) error {
|
||||||
bc.futureBlocks.Purge()
|
bc.futureBlocks.Purge()
|
||||||
|
|
||||||
// Rewind the block chain, ensuring we don't end up with a stateless head block
|
// Rewind the block chain, ensuring we don't end up with a stateless head block
|
||||||
if bc.currentBlock != nil && currentHeader.Number.Uint64() < bc.currentBlock.NumberU64() {
|
if currentBlock := bc.CurrentBlock(); currentBlock != nil && currentHeader.Number.Uint64() < currentBlock.NumberU64() {
|
||||||
bc.currentBlock = bc.GetBlock(currentHeader.Hash(), currentHeader.Number.Uint64())
|
bc.currentBlock.Store(bc.GetBlock(currentHeader.Hash(), currentHeader.Number.Uint64()))
|
||||||
}
|
}
|
||||||
if bc.currentBlock != nil {
|
if currentBlock := bc.CurrentBlock(); currentBlock != nil {
|
||||||
if _, err := state.New(bc.currentBlock.Root(), bc.stateCache); err != nil {
|
if _, err := state.New(currentBlock.Root(), bc.stateCache); err != nil {
|
||||||
// Rewound state missing, rolled back to before pivot, reset to genesis
|
// Rewound state missing, rolled back to before pivot, reset to genesis
|
||||||
bc.currentBlock = nil
|
bc.currentBlock.Store(bc.genesisBlock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Rewind the fast block in a simpleton way to the target head
|
// Rewind the fast block in a simpleton way to the target head
|
||||||
if bc.currentFastBlock != nil && currentHeader.Number.Uint64() < bc.currentFastBlock.NumberU64() {
|
if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock != nil && currentHeader.Number.Uint64() < currentFastBlock.NumberU64() {
|
||||||
bc.currentFastBlock = bc.GetBlock(currentHeader.Hash(), currentHeader.Number.Uint64())
|
bc.currentFastBlock.Store(bc.GetBlock(currentHeader.Hash(), currentHeader.Number.Uint64()))
|
||||||
}
|
}
|
||||||
// If either blocks reached nil, reset to the genesis state
|
// If either blocks reached nil, reset to the genesis state
|
||||||
if bc.currentBlock == nil {
|
if currentBlock := bc.CurrentBlock(); currentBlock == nil {
|
||||||
bc.currentBlock = bc.genesisBlock
|
bc.currentBlock.Store(bc.genesisBlock)
|
||||||
}
|
}
|
||||||
if bc.currentFastBlock == nil {
|
if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock == nil {
|
||||||
bc.currentFastBlock = bc.genesisBlock
|
bc.currentFastBlock.Store(bc.genesisBlock)
|
||||||
}
|
}
|
||||||
if err := WriteHeadBlockHash(bc.db, bc.currentBlock.Hash()); err != nil {
|
currentBlock := bc.CurrentBlock()
|
||||||
|
currentFastBlock := bc.CurrentFastBlock()
|
||||||
|
if err := WriteHeadBlockHash(bc.db, currentBlock.Hash()); err != nil {
|
||||||
log.Crit("Failed to reset head full block", "err", err)
|
log.Crit("Failed to reset head full block", "err", err)
|
||||||
}
|
}
|
||||||
if err := WriteHeadFastBlockHash(bc.db, bc.currentFastBlock.Hash()); err != nil {
|
if err := WriteHeadFastBlockHash(bc.db, currentFastBlock.Hash()); err != nil {
|
||||||
log.Crit("Failed to reset head fast block", "err", err)
|
log.Crit("Failed to reset head fast block", "err", err)
|
||||||
}
|
}
|
||||||
return bc.loadLastState()
|
return bc.loadLastState()
|
||||||
|
|
@ -321,7 +325,7 @@ func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
|
||||||
}
|
}
|
||||||
// If all checks out, manually set the head block
|
// If all checks out, manually set the head block
|
||||||
bc.mu.Lock()
|
bc.mu.Lock()
|
||||||
bc.currentBlock = block
|
bc.currentBlock.Store(block)
|
||||||
bc.mu.Unlock()
|
bc.mu.Unlock()
|
||||||
|
|
||||||
log.Info("Committed new head block", "number", block.Number(), "hash", hash)
|
log.Info("Committed new head block", "number", block.Number(), "hash", hash)
|
||||||
|
|
@ -330,28 +334,19 @@ func (bc *BlockChain) FastSyncCommitHead(hash common.Hash) error {
|
||||||
|
|
||||||
// GasLimit returns the gas limit of the current HEAD block.
|
// GasLimit returns the gas limit of the current HEAD block.
|
||||||
func (bc *BlockChain) GasLimit() uint64 {
|
func (bc *BlockChain) GasLimit() uint64 {
|
||||||
bc.mu.RLock()
|
return bc.CurrentBlock().GasLimit()
|
||||||
defer bc.mu.RUnlock()
|
|
||||||
|
|
||||||
return bc.currentBlock.GasLimit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CurrentBlock retrieves the current head block of the canonical chain. The
|
// CurrentBlock retrieves the current head block of the canonical chain. The
|
||||||
// block is retrieved from the blockchain's internal cache.
|
// block is retrieved from the blockchain's internal cache.
|
||||||
func (bc *BlockChain) CurrentBlock() *types.Block {
|
func (bc *BlockChain) CurrentBlock() *types.Block {
|
||||||
bc.mu.RLock()
|
return bc.currentBlock.Load().(*types.Block)
|
||||||
defer bc.mu.RUnlock()
|
|
||||||
|
|
||||||
return bc.currentBlock
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CurrentFastBlock retrieves the current fast-sync head block of the canonical
|
// CurrentFastBlock retrieves the current fast-sync head block of the canonical
|
||||||
// chain. The block is retrieved from the blockchain's internal cache.
|
// chain. The block is retrieved from the blockchain's internal cache.
|
||||||
func (bc *BlockChain) CurrentFastBlock() *types.Block {
|
func (bc *BlockChain) CurrentFastBlock() *types.Block {
|
||||||
bc.mu.RLock()
|
return bc.currentFastBlock.Load().(*types.Block)
|
||||||
defer bc.mu.RUnlock()
|
|
||||||
|
|
||||||
return bc.currentFastBlock
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetProcessor sets the processor required for making state modifications.
|
// SetProcessor sets the processor required for making state modifications.
|
||||||
|
|
@ -416,10 +411,10 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
|
||||||
}
|
}
|
||||||
bc.genesisBlock = genesis
|
bc.genesisBlock = genesis
|
||||||
bc.insert(bc.genesisBlock)
|
bc.insert(bc.genesisBlock)
|
||||||
bc.currentBlock = bc.genesisBlock
|
bc.currentBlock.Store(bc.genesisBlock)
|
||||||
bc.hc.SetGenesis(bc.genesisBlock.Header())
|
bc.hc.SetGenesis(bc.genesisBlock.Header())
|
||||||
bc.hc.SetCurrentHeader(bc.genesisBlock.Header())
|
bc.hc.SetCurrentHeader(bc.genesisBlock.Header())
|
||||||
bc.currentFastBlock = bc.genesisBlock
|
bc.currentFastBlock.Store(bc.genesisBlock)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -444,7 +439,7 @@ func (bc *BlockChain) repair(head **types.Block) error {
|
||||||
|
|
||||||
// Export writes the active chain to the given writer.
|
// Export writes the active chain to the given writer.
|
||||||
func (bc *BlockChain) Export(w io.Writer) error {
|
func (bc *BlockChain) Export(w io.Writer) error {
|
||||||
return bc.ExportN(w, uint64(0), bc.currentBlock.NumberU64())
|
return bc.ExportN(w, uint64(0), bc.CurrentBlock().NumberU64())
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportN writes a subset of the active chain to the given writer.
|
// ExportN writes a subset of the active chain to the given writer.
|
||||||
|
|
@ -488,7 +483,7 @@ func (bc *BlockChain) insert(block *types.Block) {
|
||||||
if err := WriteHeadBlockHash(bc.db, block.Hash()); err != nil {
|
if err := WriteHeadBlockHash(bc.db, block.Hash()); err != nil {
|
||||||
log.Crit("Failed to insert head block hash", "err", err)
|
log.Crit("Failed to insert head block hash", "err", err)
|
||||||
}
|
}
|
||||||
bc.currentBlock = block
|
bc.currentBlock.Store(block)
|
||||||
|
|
||||||
// If the block is better than our head or is on a different chain, force update heads
|
// If the block is better than our head or is on a different chain, force update heads
|
||||||
if updateHeads {
|
if updateHeads {
|
||||||
|
|
@ -497,7 +492,7 @@ func (bc *BlockChain) insert(block *types.Block) {
|
||||||
if err := WriteHeadFastBlockHash(bc.db, block.Hash()); err != nil {
|
if err := WriteHeadFastBlockHash(bc.db, block.Hash()); err != nil {
|
||||||
log.Crit("Failed to insert head fast block hash", "err", err)
|
log.Crit("Failed to insert head fast block hash", "err", err)
|
||||||
}
|
}
|
||||||
bc.currentFastBlock = block
|
bc.currentFastBlock.Store(block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -714,13 +709,15 @@ func (bc *BlockChain) Rollback(chain []common.Hash) {
|
||||||
if currentHeader.Hash() == hash {
|
if currentHeader.Hash() == hash {
|
||||||
bc.hc.SetCurrentHeader(bc.GetHeader(currentHeader.ParentHash, currentHeader.Number.Uint64()-1))
|
bc.hc.SetCurrentHeader(bc.GetHeader(currentHeader.ParentHash, currentHeader.Number.Uint64()-1))
|
||||||
}
|
}
|
||||||
if bc.currentFastBlock.Hash() == hash {
|
if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock.Hash() == hash {
|
||||||
bc.currentFastBlock = bc.GetBlock(bc.currentFastBlock.ParentHash(), bc.currentFastBlock.NumberU64()-1)
|
newFastBlock := bc.GetBlock(currentFastBlock.ParentHash(), currentFastBlock.NumberU64()-1)
|
||||||
WriteHeadFastBlockHash(bc.db, bc.currentFastBlock.Hash())
|
bc.currentFastBlock.Store(newFastBlock)
|
||||||
|
WriteHeadFastBlockHash(bc.db, newFastBlock.Hash())
|
||||||
}
|
}
|
||||||
if bc.currentBlock.Hash() == hash {
|
if currentBlock := bc.CurrentBlock(); currentBlock.Hash() == hash {
|
||||||
bc.currentBlock = bc.GetBlock(bc.currentBlock.ParentHash(), bc.currentBlock.NumberU64()-1)
|
newBlock := bc.GetBlock(currentBlock.ParentHash(), currentBlock.NumberU64()-1)
|
||||||
WriteHeadBlockHash(bc.db, bc.currentBlock.Hash())
|
bc.currentBlock.Store(newBlock)
|
||||||
|
WriteHeadBlockHash(bc.db, newBlock.Hash())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -829,11 +826,12 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
bc.mu.Lock()
|
bc.mu.Lock()
|
||||||
head := blockChain[len(blockChain)-1]
|
head := blockChain[len(blockChain)-1]
|
||||||
if td := bc.GetTd(head.Hash(), head.NumberU64()); td != nil { // Rewind may have occurred, skip in that case
|
if td := bc.GetTd(head.Hash(), head.NumberU64()); td != nil { // Rewind may have occurred, skip in that case
|
||||||
if bc.GetTd(bc.currentFastBlock.Hash(), bc.currentFastBlock.NumberU64()).Cmp(td) < 0 {
|
currentFastBlock := bc.CurrentFastBlock()
|
||||||
|
if bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64()).Cmp(td) < 0 {
|
||||||
if err := WriteHeadFastBlockHash(bc.db, head.Hash()); err != nil {
|
if err := WriteHeadFastBlockHash(bc.db, head.Hash()); err != nil {
|
||||||
log.Crit("Failed to update head fast block hash", "err", err)
|
log.Crit("Failed to update head fast block hash", "err", err)
|
||||||
}
|
}
|
||||||
bc.currentFastBlock = head
|
bc.currentFastBlock.Store(head)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bc.mu.Unlock()
|
bc.mu.Unlock()
|
||||||
|
|
@ -880,7 +878,8 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
|
||||||
bc.mu.Lock()
|
bc.mu.Lock()
|
||||||
defer bc.mu.Unlock()
|
defer bc.mu.Unlock()
|
||||||
|
|
||||||
localTd := bc.GetTd(bc.currentBlock.Hash(), bc.currentBlock.NumberU64())
|
currentBlock := bc.CurrentBlock()
|
||||||
|
localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64())
|
||||||
externTd := new(big.Int).Add(block.Difficulty(), ptd)
|
externTd := new(big.Int).Add(block.Difficulty(), ptd)
|
||||||
|
|
||||||
// Irrelevant of the canonical status, write the block itself to the database
|
// Irrelevant of the canonical status, write the block itself to the database
|
||||||
|
|
@ -955,14 +954,15 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
|
||||||
// Second clause in the if statement reduces the vulnerability to selfish mining.
|
// Second clause in the if statement reduces the vulnerability to selfish mining.
|
||||||
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
|
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
|
||||||
reorg := externTd.Cmp(localTd) > 0
|
reorg := externTd.Cmp(localTd) > 0
|
||||||
|
currentBlock = bc.CurrentBlock()
|
||||||
if !reorg && externTd.Cmp(localTd) == 0 {
|
if !reorg && externTd.Cmp(localTd) == 0 {
|
||||||
// Split same-difficulty blocks by number, then at random
|
// Split same-difficulty blocks by number, then at random
|
||||||
reorg = block.NumberU64() < bc.currentBlock.NumberU64() || (block.NumberU64() == bc.currentBlock.NumberU64() && mrand.Float64() < 0.5)
|
reorg = block.NumberU64() < currentBlock.NumberU64() || (block.NumberU64() == currentBlock.NumberU64() && mrand.Float64() < 0.5)
|
||||||
}
|
}
|
||||||
if reorg {
|
if reorg {
|
||||||
// Reorganise the chain if the parent is not the head block
|
// Reorganise the chain if the parent is not the head block
|
||||||
if block.ParentHash() != bc.currentBlock.Hash() {
|
if block.ParentHash() != currentBlock.Hash() {
|
||||||
if err := bc.reorg(bc.currentBlock, block); err != nil {
|
if err := bc.reorg(currentBlock, block); err != nil {
|
||||||
return NonStatTy, err
|
return NonStatTy, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1091,7 +1091,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
|
||||||
case err == consensus.ErrPrunedAncestor:
|
case err == consensus.ErrPrunedAncestor:
|
||||||
// Block competing with the canonical chain, store in the db, but don't process
|
// Block competing with the canonical chain, store in the db, but don't process
|
||||||
// until the competitor TD goes above the canonical TD
|
// until the competitor TD goes above the canonical TD
|
||||||
localTd := bc.GetTd(bc.currentBlock.Hash(), bc.currentBlock.NumberU64())
|
currentBlock := bc.CurrentBlock()
|
||||||
|
localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64())
|
||||||
externTd := new(big.Int).Add(bc.GetTd(block.ParentHash(), block.NumberU64()-1), block.Difficulty())
|
externTd := new(big.Int).Add(bc.GetTd(block.ParentHash(), block.NumberU64()-1), block.Difficulty())
|
||||||
if localTd.Cmp(externTd) > 0 {
|
if localTd.Cmp(externTd) > 0 {
|
||||||
if err = bc.WriteBlockWithoutState(block, externTd); err != nil {
|
if err = bc.WriteBlockWithoutState(block, externTd); err != nil {
|
||||||
|
|
@ -1480,9 +1481,6 @@ func (bc *BlockChain) writeHeader(header *types.Header) error {
|
||||||
// CurrentHeader retrieves the current head header of the canonical chain. The
|
// CurrentHeader retrieves the current head header of the canonical chain. The
|
||||||
// header is retrieved from the HeaderChain's internal cache.
|
// header is retrieved from the HeaderChain's internal cache.
|
||||||
func (bc *BlockChain) CurrentHeader() *types.Header {
|
func (bc *BlockChain) CurrentHeader() *types.Header {
|
||||||
bc.mu.RLock()
|
|
||||||
defer bc.mu.RUnlock()
|
|
||||||
|
|
||||||
return bc.hc.CurrentHeader()
|
return bc.hc.CurrentHeader()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import (
|
||||||
"github.com/EthereumCommonwealth/go-callisto/log"
|
"github.com/EthereumCommonwealth/go-callisto/log"
|
||||||
"github.com/EthereumCommonwealth/go-callisto/params"
|
"github.com/EthereumCommonwealth/go-callisto/params"
|
||||||
"github.com/hashicorp/golang-lru"
|
"github.com/hashicorp/golang-lru"
|
||||||
|
"sync/atomic"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -51,7 +52,7 @@ type HeaderChain struct {
|
||||||
chainDb ethdb.Database
|
chainDb ethdb.Database
|
||||||
genesisHeader *types.Header
|
genesisHeader *types.Header
|
||||||
|
|
||||||
currentHeader *types.Header // Current head of the header chain (may be above the block chain!)
|
currentHeader atomic.Value // Current head of the header chain (may be above the block chain!)
|
||||||
currentHeaderHash common.Hash // Hash of the current head of the header chain (prevent recomputing all the time)
|
currentHeaderHash common.Hash // Hash of the current head of the header chain (prevent recomputing all the time)
|
||||||
|
|
||||||
headerCache *lru.Cache // Cache for the most recent block headers
|
headerCache *lru.Cache // Cache for the most recent block headers
|
||||||
|
|
@ -95,13 +96,13 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c
|
||||||
return nil, ErrNoGenesis
|
return nil, ErrNoGenesis
|
||||||
}
|
}
|
||||||
|
|
||||||
hc.currentHeader = hc.genesisHeader
|
hc.currentHeader.Store(hc.genesisHeader)
|
||||||
if head := GetHeadBlockHash(chainDb); head != (common.Hash{}) {
|
if head := GetHeadBlockHash(chainDb); head != (common.Hash{}) {
|
||||||
if chead := hc.GetHeaderByHash(head); chead != nil {
|
if chead := hc.GetHeaderByHash(head); chead != nil {
|
||||||
hc.currentHeader = chead
|
hc.currentHeader.Store(chead)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hc.currentHeaderHash = hc.currentHeader.Hash()
|
hc.currentHeaderHash = hc.CurrentHeader().Hash()
|
||||||
|
|
||||||
return hc, nil
|
return hc, nil
|
||||||
}
|
}
|
||||||
|
|
@ -139,7 +140,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
|
||||||
if ptd == nil {
|
if ptd == nil {
|
||||||
return NonStatTy, consensus.ErrUnknownAncestor
|
return NonStatTy, consensus.ErrUnknownAncestor
|
||||||
}
|
}
|
||||||
localTd := hc.GetTd(hc.currentHeaderHash, hc.currentHeader.Number.Uint64())
|
localTd := hc.GetTd(hc.currentHeaderHash, hc.CurrentHeader().Number.Uint64())
|
||||||
externTd := new(big.Int).Add(header.Difficulty, ptd)
|
externTd := new(big.Int).Add(header.Difficulty, ptd)
|
||||||
|
|
||||||
// Irrelevant of the canonical status, write the td and header to the database
|
// Irrelevant of the canonical status, write the td and header to the database
|
||||||
|
|
@ -181,7 +182,8 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
|
||||||
if err := WriteHeadHeaderHash(hc.chainDb, hash); err != nil {
|
if err := WriteHeadHeaderHash(hc.chainDb, hash); err != nil {
|
||||||
log.Crit("Failed to insert head header hash", "err", err)
|
log.Crit("Failed to insert head header hash", "err", err)
|
||||||
}
|
}
|
||||||
hc.currentHeaderHash, hc.currentHeader = hash, types.CopyHeader(header)
|
hc.currentHeaderHash = hash
|
||||||
|
hc.currentHeader.Store(types.CopyHeader(header))
|
||||||
|
|
||||||
status = CanonStatTy
|
status = CanonStatTy
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -383,7 +385,7 @@ func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header {
|
||||||
// CurrentHeader retrieves the current head header of the canonical chain. The
|
// CurrentHeader retrieves the current head header of the canonical chain. The
|
||||||
// header is retrieved from the HeaderChain's internal cache.
|
// header is retrieved from the HeaderChain's internal cache.
|
||||||
func (hc *HeaderChain) CurrentHeader() *types.Header {
|
func (hc *HeaderChain) CurrentHeader() *types.Header {
|
||||||
return hc.currentHeader
|
return hc.currentHeader.Load().(*types.Header)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetCurrentHeader sets the current head header of the canonical chain.
|
// SetCurrentHeader sets the current head header of the canonical chain.
|
||||||
|
|
@ -391,7 +393,7 @@ func (hc *HeaderChain) SetCurrentHeader(head *types.Header) {
|
||||||
if err := WriteHeadHeaderHash(hc.chainDb, head.Hash()); err != nil {
|
if err := WriteHeadHeaderHash(hc.chainDb, head.Hash()); err != nil {
|
||||||
log.Crit("Failed to insert head header hash", "err", err)
|
log.Crit("Failed to insert head header hash", "err", err)
|
||||||
}
|
}
|
||||||
hc.currentHeader = head
|
hc.currentHeader.Store(head)
|
||||||
hc.currentHeaderHash = head.Hash()
|
hc.currentHeaderHash = head.Hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -403,19 +405,20 @@ type DeleteCallback func(common.Hash, uint64)
|
||||||
// will be deleted and the new one set.
|
// will be deleted and the new one set.
|
||||||
func (hc *HeaderChain) SetHead(head uint64, delFn DeleteCallback) {
|
func (hc *HeaderChain) SetHead(head uint64, delFn DeleteCallback) {
|
||||||
height := uint64(0)
|
height := uint64(0)
|
||||||
if hc.currentHeader != nil {
|
|
||||||
height = hc.currentHeader.Number.Uint64()
|
if hdr := hc.CurrentHeader(); hdr != nil {
|
||||||
|
height = hdr.Number.Uint64()
|
||||||
}
|
}
|
||||||
|
|
||||||
for hc.currentHeader != nil && hc.currentHeader.Number.Uint64() > head {
|
for hdr := hc.CurrentHeader(); hdr != nil && hdr.Number.Uint64() > head; hdr = hc.CurrentHeader() {
|
||||||
hash := hc.currentHeader.Hash()
|
hash := hdr.Hash()
|
||||||
num := hc.currentHeader.Number.Uint64()
|
num := hdr.Number.Uint64()
|
||||||
if delFn != nil {
|
if delFn != nil {
|
||||||
delFn(hash, num)
|
delFn(hash, num)
|
||||||
}
|
}
|
||||||
DeleteHeader(hc.chainDb, hash, num)
|
DeleteHeader(hc.chainDb, hash, num)
|
||||||
DeleteTd(hc.chainDb, hash, num)
|
DeleteTd(hc.chainDb, hash, num)
|
||||||
hc.currentHeader = hc.GetHeader(hc.currentHeader.ParentHash, hc.currentHeader.Number.Uint64()-1)
|
hc.currentHeader.Store(hc.GetHeader(hdr.ParentHash, hdr.Number.Uint64()-1))
|
||||||
}
|
}
|
||||||
// Roll back the canonical chain numbering
|
// Roll back the canonical chain numbering
|
||||||
for i := height; i > head; i-- {
|
for i := height; i > head; i-- {
|
||||||
|
|
@ -426,10 +429,10 @@ func (hc *HeaderChain) SetHead(head uint64, delFn DeleteCallback) {
|
||||||
hc.tdCache.Purge()
|
hc.tdCache.Purge()
|
||||||
hc.numberCache.Purge()
|
hc.numberCache.Purge()
|
||||||
|
|
||||||
if hc.currentHeader == nil {
|
if hc.CurrentHeader() == nil {
|
||||||
hc.currentHeader = hc.genesisHeader
|
hc.currentHeader.Store(hc.genesisHeader)
|
||||||
}
|
}
|
||||||
hc.currentHeaderHash = hc.currentHeader.Hash()
|
hc.currentHeaderHash = hc.CurrentHeader().Hash()
|
||||||
|
|
||||||
if err := WriteHeadHeaderHash(hc.chainDb, hc.currentHeaderHash); err != nil {
|
if err := WriteHeadHeaderHash(hc.chainDb, hc.currentHeaderHash); err != nil {
|
||||||
log.Crit("Failed to reset head header hash", "err", err)
|
log.Crit("Failed to reset head header hash", "err", err)
|
||||||
|
|
|
||||||
|
|
@ -249,7 +249,8 @@ func (pm *ProtocolManager) newPeer(pv int, p *p2p.Peer, rw p2p.MsgReadWriter) *p
|
||||||
// handle is the callback invoked to manage the life cycle of an eth peer. When
|
// handle is the callback invoked to manage the life cycle of an eth peer. When
|
||||||
// this function terminates, the peer is disconnected.
|
// this function terminates, the peer is disconnected.
|
||||||
func (pm *ProtocolManager) handle(p *peer) error {
|
func (pm *ProtocolManager) handle(p *peer) error {
|
||||||
if pm.peers.Len() >= pm.maxPeers {
|
// Ignore maxPeers if this is a trusted peer
|
||||||
|
if pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted {
|
||||||
return p2p.DiscTooManyPeers
|
return p2p.DiscTooManyPeers
|
||||||
}
|
}
|
||||||
p.Log().Debug("Ethereum peer connected", "name", p.Name())
|
p.Log().Debug("Ethereum peer connected", "name", p.Name())
|
||||||
|
|
|
||||||
|
|
@ -260,7 +260,8 @@ func (pm *ProtocolManager) newPeer(pv int, nv uint64, p *p2p.Peer, rw p2p.MsgRea
|
||||||
// handle is the callback invoked to manage the life cycle of a les peer. When
|
// handle is the callback invoked to manage the life cycle of a les peer. When
|
||||||
// this function terminates, the peer is disconnected.
|
// this function terminates, the peer is disconnected.
|
||||||
func (pm *ProtocolManager) handle(p *peer) error {
|
func (pm *ProtocolManager) handle(p *peer) error {
|
||||||
if pm.peers.Len() >= pm.maxPeers {
|
// Ignore maxPeers if this is a trusted peer
|
||||||
|
if pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted {
|
||||||
return p2p.DiscTooManyPeers
|
return p2p.DiscTooManyPeers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -171,9 +171,6 @@ func (bc *LightChain) SetHead(head uint64) {
|
||||||
|
|
||||||
// GasLimit returns the gas limit of the current HEAD block.
|
// GasLimit returns the gas limit of the current HEAD block.
|
||||||
func (self *LightChain) GasLimit() uint64 {
|
func (self *LightChain) GasLimit() uint64 {
|
||||||
self.mu.RLock()
|
|
||||||
defer self.mu.RUnlock()
|
|
||||||
|
|
||||||
return self.hc.CurrentHeader().GasLimit
|
return self.hc.CurrentHeader().GasLimit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -387,9 +384,6 @@ func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int)
|
||||||
// CurrentHeader retrieves the current head header of the canonical chain. The
|
// CurrentHeader retrieves the current head header of the canonical chain. The
|
||||||
// header is retrieved from the HeaderChain's internal cache.
|
// header is retrieved from the HeaderChain's internal cache.
|
||||||
func (self *LightChain) CurrentHeader() *types.Header {
|
func (self *LightChain) CurrentHeader() *types.Header {
|
||||||
self.mu.RLock()
|
|
||||||
defer self.mu.RUnlock()
|
|
||||||
|
|
||||||
return self.hc.CurrentHeader()
|
return self.hc.CurrentHeader()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
10
node/api.go
10
node/api.go
|
|
@ -308,6 +308,11 @@ func (api *PublicDebugAPI) Metrics(raw bool) (map[string]interface{}, error) {
|
||||||
// Fill the counter with the metric details, formatting if requested
|
// Fill the counter with the metric details, formatting if requested
|
||||||
if raw {
|
if raw {
|
||||||
switch metric := metric.(type) {
|
switch metric := metric.(type) {
|
||||||
|
case metrics.Counter:
|
||||||
|
root[name] = map[string]interface{}{
|
||||||
|
"Overall": float64(metric.Count()),
|
||||||
|
}
|
||||||
|
|
||||||
case metrics.Meter:
|
case metrics.Meter:
|
||||||
root[name] = map[string]interface{}{
|
root[name] = map[string]interface{}{
|
||||||
"AvgRate01Min": metric.Rate1(),
|
"AvgRate01Min": metric.Rate1(),
|
||||||
|
|
@ -338,6 +343,11 @@ func (api *PublicDebugAPI) Metrics(raw bool) (map[string]interface{}, error) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch metric := metric.(type) {
|
switch metric := metric.(type) {
|
||||||
|
case metrics.Counter:
|
||||||
|
root[name] = map[string]interface{}{
|
||||||
|
"Overall": float64(metric.Count()),
|
||||||
|
}
|
||||||
|
|
||||||
case metrics.Meter:
|
case metrics.Meter:
|
||||||
root[name] = map[string]interface{}{
|
root[name] = map[string]interface{}{
|
||||||
"Avg01Min": format(metric.Rate1()*60, metric.Rate1()),
|
"Avg01Min": format(metric.Rate1()*60, metric.Rate1()),
|
||||||
|
|
|
||||||
|
|
@ -121,10 +121,6 @@ func (t *rlpx) close(err error) {
|
||||||
t.fd.Close()
|
t.fd.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// doEncHandshake runs the protocol handshake using authenticated
|
|
||||||
// messages. the protocol handshake is the first authenticated message
|
|
||||||
// and also verifies whether the encryption handshake 'worked' and the
|
|
||||||
// remote side actually provided the right public key.
|
|
||||||
func (t *rlpx) doProtoHandshake(our *protoHandshake) (their *protoHandshake, err error) {
|
func (t *rlpx) doProtoHandshake(our *protoHandshake) (their *protoHandshake, err error) {
|
||||||
// Writing our handshake happens concurrently, we prefer
|
// Writing our handshake happens concurrently, we prefer
|
||||||
// returning the handshake read error. If the remote side
|
// returning the handshake read error. If the remote side
|
||||||
|
|
@ -175,6 +171,10 @@ func readProtocolHandshake(rw MsgReader, our *protoHandshake) (*protoHandshake,
|
||||||
return &hs, nil
|
return &hs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// doEncHandshake runs the protocol handshake using authenticated
|
||||||
|
// messages. the protocol handshake is the first authenticated message
|
||||||
|
// and also verifies whether the encryption handshake 'worked' and the
|
||||||
|
// remote side actually provided the right public key.
|
||||||
func (t *rlpx) doEncHandshake(prv *ecdsa.PrivateKey, dial *discover.Node) (discover.NodeID, error) {
|
func (t *rlpx) doEncHandshake(prv *ecdsa.PrivateKey, dial *discover.Node) (discover.NodeID, error) {
|
||||||
var (
|
var (
|
||||||
sec secrets
|
sec secrets
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ import (
|
||||||
|
|
||||||
//templateMap holds a mapping of an HTTP error code to a template
|
//templateMap holds a mapping of an HTTP error code to a template
|
||||||
var templateMap map[int]*template.Template
|
var templateMap map[int]*template.Template
|
||||||
|
var caseErrors []CaseError
|
||||||
|
|
||||||
//metrics variables
|
//metrics variables
|
||||||
var (
|
var (
|
||||||
|
|
@ -51,6 +52,13 @@ type ErrorParams struct {
|
||||||
Details template.HTML
|
Details template.HTML
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//a custom error case struct that would be used to store validators and
|
||||||
|
//additional error info to display with client responses.
|
||||||
|
type CaseError struct {
|
||||||
|
Validator func(*Request) bool
|
||||||
|
Msg func(*Request) string
|
||||||
|
}
|
||||||
|
|
||||||
//we init the error handling right on boot time, so lookup and http response is fast
|
//we init the error handling right on boot time, so lookup and http response is fast
|
||||||
func init() {
|
func init() {
|
||||||
initErrHandling()
|
initErrHandling()
|
||||||
|
|
@ -74,6 +82,29 @@ func initErrHandling() {
|
||||||
//assign formatted HTML to the code
|
//assign formatted HTML to the code
|
||||||
templateMap[code] = template.Must(template.New(fmt.Sprintf("%d", code)).Parse(tname))
|
templateMap[code] = template.Must(template.New(fmt.Sprintf("%d", code)).Parse(tname))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
caseErrors = []CaseError{
|
||||||
|
{
|
||||||
|
Validator: func(r *Request) bool { return r.uri != nil && r.uri.Addr != "" && strings.HasPrefix(r.uri.Addr, "0x") },
|
||||||
|
Msg: func(r *Request) string {
|
||||||
|
uriCopy := r.uri
|
||||||
|
uriCopy.Addr = strings.TrimPrefix(uriCopy.Addr, "0x")
|
||||||
|
return fmt.Sprintf(`The requested hash seems to be prefixed with '0x'. You will be redirected to the correct URL within 5 seconds.<br/>
|
||||||
|
Please click <a href='%[1]s'>here</a> if your browser does not redirect you.<script>setTimeout("location.href='%[1]s';",5000);</script>`, "/"+uriCopy.String())
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ValidateCaseErrors is a method that process the request object through certain validators
|
||||||
|
//that assert if certain conditions are met for further information to log as an error
|
||||||
|
func ValidateCaseErrors(r *Request) string {
|
||||||
|
for _, err := range caseErrors {
|
||||||
|
if err.Validator(r) {
|
||||||
|
return err.Msg(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
//ShowMultipeChoices is used when a user requests a resource in a manifest which results
|
//ShowMultipeChoices is used when a user requests a resource in a manifest which results
|
||||||
|
|
@ -82,10 +113,10 @@ func initErrHandling() {
|
||||||
//For example, if the user requests bzz:/<hash>/read and that manifest contains entries
|
//For example, if the user requests bzz:/<hash>/read and that manifest contains entries
|
||||||
//"readme.md" and "readinglist.txt", a HTML page is returned with this two links.
|
//"readme.md" and "readinglist.txt", a HTML page is returned with this two links.
|
||||||
//This only applies if the manifest has no default entry
|
//This only applies if the manifest has no default entry
|
||||||
func ShowMultipleChoices(w http.ResponseWriter, r *http.Request, list api.ManifestList) {
|
func ShowMultipleChoices(w http.ResponseWriter, r *Request, list api.ManifestList) {
|
||||||
msg := ""
|
msg := ""
|
||||||
if list.Entries == nil {
|
if list.Entries == nil {
|
||||||
ShowError(w, r, "Internal Server Error", http.StatusInternalServerError)
|
ShowError(w, r, "Could not resolve", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//make links relative
|
//make links relative
|
||||||
|
|
@ -102,7 +133,7 @@ func ShowMultipleChoices(w http.ResponseWriter, r *http.Request, list api.Manife
|
||||||
//create clickable link for each entry
|
//create clickable link for each entry
|
||||||
msg += "<a href='" + base + e.Path + "'>" + e.Path + "</a><br/>"
|
msg += "<a href='" + base + e.Path + "'>" + e.Path + "</a><br/>"
|
||||||
}
|
}
|
||||||
respond(w, r, &ErrorParams{
|
respond(w, &r.Request, &ErrorParams{
|
||||||
Code: http.StatusMultipleChoices,
|
Code: http.StatusMultipleChoices,
|
||||||
Details: template.HTML(msg),
|
Details: template.HTML(msg),
|
||||||
Timestamp: time.Now().Format(time.RFC1123),
|
Timestamp: time.Now().Format(time.RFC1123),
|
||||||
|
|
@ -115,13 +146,15 @@ func ShowMultipleChoices(w http.ResponseWriter, r *http.Request, list api.Manife
|
||||||
//The function just takes a string message which will be displayed in the error page.
|
//The function just takes a string message which will be displayed in the error page.
|
||||||
//The code is used to evaluate which template will be displayed
|
//The code is used to evaluate which template will be displayed
|
||||||
//(and return the correct HTTP status code)
|
//(and return the correct HTTP status code)
|
||||||
func ShowError(w http.ResponseWriter, r *http.Request, msg string, code int) {
|
func ShowError(w http.ResponseWriter, r *Request, msg string, code int) {
|
||||||
|
additionalMessage := ValidateCaseErrors(r)
|
||||||
if code == http.StatusInternalServerError {
|
if code == http.StatusInternalServerError {
|
||||||
log.Error(msg)
|
log.Error(msg)
|
||||||
}
|
}
|
||||||
respond(w, r, &ErrorParams{
|
respond(w, &r.Request, &ErrorParams{
|
||||||
Code: code,
|
Code: code,
|
||||||
Msg: msg,
|
Msg: msg,
|
||||||
|
Details: template.HTML(additionalMessage),
|
||||||
Timestamp: time.Now().Format(time.RFC1123),
|
Timestamp: time.Now().Format(time.RFC1123),
|
||||||
template: getTemplate(code),
|
template: getTemplate(code),
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,11 @@ func GetGenericErrorPage() string {
|
||||||
{{.Msg}}
|
{{.Msg}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="value">
|
||||||
|
{{.Details}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="key">
|
<td class="key">
|
||||||
|
|
@ -342,6 +347,12 @@ func GetNotFoundErrorPage() string {
|
||||||
{{.Msg}}
|
{{.Msg}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="value">
|
||||||
|
{{.Details}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="key">
|
<td class="key">
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,13 @@ package http_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"golang.org/x/net/html"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/net/html"
|
||||||
|
|
||||||
"github.com/EthereumCommonwealth/go-callisto/swarm/testutil"
|
"github.com/EthereumCommonwealth/go-callisto/swarm/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -96,8 +97,37 @@ func Test500Page(t *testing.T) {
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
respbody, err = ioutil.ReadAll(resp.Body)
|
respbody, err = ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
if resp.StatusCode != 500 || !strings.Contains(string(respbody), "500") {
|
if resp.StatusCode != 404 {
|
||||||
t.Fatalf("Invalid Status Code received, expected 500, got %d", resp.StatusCode)
|
t.Fatalf("Invalid Status Code received, expected 404, got %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = html.Parse(strings.NewReader(string(respbody)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("HTML validation failed for error page returned!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func Test500PageWith0xHashPrefix(t *testing.T) {
|
||||||
|
srv := testutil.NewTestSwarmServer(t)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
var resp *http.Response
|
||||||
|
var respbody []byte
|
||||||
|
|
||||||
|
url := srv.URL + "/bzz:/0xthisShouldFailWith500CodeAndAHelpfulMessage"
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Request failed: %v", err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
respbody, err = ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
if resp.StatusCode != 404 {
|
||||||
|
t.Fatalf("Invalid Status Code received, expected 404, got %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !strings.Contains(string(respbody), "The requested hash seems to be prefixed with") {
|
||||||
|
t.Fatalf("Did not receive the expected error message")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = html.Parse(strings.NewReader(string(respbody)))
|
_, err = html.Parse(strings.NewReader(string(respbody)))
|
||||||
|
|
@ -127,8 +157,8 @@ func TestJsonResponse(t *testing.T) {
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
respbody, err = ioutil.ReadAll(resp.Body)
|
respbody, err = ioutil.ReadAll(resp.Body)
|
||||||
|
|
||||||
if resp.StatusCode != 500 {
|
if resp.StatusCode != 404 {
|
||||||
t.Fatalf("Invalid Status Code received, expected 500, got %d", resp.StatusCode)
|
t.Fatalf("Invalid Status Code received, expected 404, got %d", resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isJSON(string(respbody)) {
|
if !isJSON(string(respbody)) {
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@ func (s *Server) HandleGet(w http.ResponseWriter, r *Request) {
|
||||||
key, err := s.api.Resolve(r.uri)
|
key, err := s.api.Resolve(r.uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
getFail.Inc(1)
|
getFail.Inc(1)
|
||||||
s.Error(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
|
s.NotFound(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -421,7 +421,7 @@ func (s *Server) HandleGetFiles(w http.ResponseWriter, r *Request) {
|
||||||
key, err := s.api.Resolve(r.uri)
|
key, err := s.api.Resolve(r.uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
getFilesFail.Inc(1)
|
getFilesFail.Inc(1)
|
||||||
s.Error(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
|
s.NotFound(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -494,7 +494,7 @@ func (s *Server) HandleGetList(w http.ResponseWriter, r *Request) {
|
||||||
key, err := s.api.Resolve(r.uri)
|
key, err := s.api.Resolve(r.uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
getListFail.Inc(1)
|
getListFail.Inc(1)
|
||||||
s.Error(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
|
s.NotFound(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -598,7 +598,7 @@ func (s *Server) HandleGetFile(w http.ResponseWriter, r *Request) {
|
||||||
key, err := s.api.Resolve(r.uri)
|
key, err := s.api.Resolve(r.uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
getFileFail.Inc(1)
|
getFileFail.Inc(1)
|
||||||
s.Error(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
|
s.NotFound(w, r, fmt.Errorf("error resolving %s: %s", r.uri.Addr, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -628,7 +628,7 @@ func (s *Server) HandleGetFile(w http.ResponseWriter, r *Request) {
|
||||||
|
|
||||||
s.logDebug(fmt.Sprintf("Multiple choices! --> %v", list))
|
s.logDebug(fmt.Sprintf("Multiple choices! --> %v", list))
|
||||||
//show a nice page links to available entries
|
//show a nice page links to available entries
|
||||||
ShowMultipleChoices(w, &r.Request, list)
|
ShowMultipleChoices(w, r, list)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -660,6 +660,15 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
s.logDebug("HTTP %s request URL: '%s', Host: '%s', Path: '%s', Referer: '%s', Accept: '%s'", r.Method, r.RequestURI, r.URL.Host, r.URL.Path, r.Referer(), r.Header.Get("Accept"))
|
s.logDebug("HTTP %s request URL: '%s', Host: '%s', Path: '%s', Referer: '%s', Accept: '%s'", r.Method, r.RequestURI, r.URL.Host, r.URL.Path, r.Referer(), r.Header.Get("Accept"))
|
||||||
|
|
||||||
|
if r.RequestURI == "/" && strings.Contains(r.Header.Get("Accept"), "text/html") {
|
||||||
|
|
||||||
|
err := landingPageTemplate.Execute(w, nil)
|
||||||
|
if err != nil {
|
||||||
|
s.logError("error rendering landing page: %s", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
uri, err := api.Parse(strings.TrimLeft(r.URL.Path, "/"))
|
uri, err := api.Parse(strings.TrimLeft(r.URL.Path, "/"))
|
||||||
req := &Request{Request: *r, uri: uri}
|
req := &Request{Request: *r, uri: uri}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -684,7 +693,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
// strictly a traditional PUT request which replaces content
|
// strictly a traditional PUT request which replaces content
|
||||||
// at a URI, and POST is more ubiquitous)
|
// at a URI, and POST is more ubiquitous)
|
||||||
if uri.Raw() || uri.DeprecatedRaw() {
|
if uri.Raw() || uri.DeprecatedRaw() {
|
||||||
ShowError(w, r, fmt.Sprintf("No PUT to %s allowed.", uri), http.StatusBadRequest)
|
ShowError(w, req, fmt.Sprintf("No PUT to %s allowed.", uri), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
s.HandlePostFiles(w, req)
|
s.HandlePostFiles(w, req)
|
||||||
|
|
@ -692,7 +701,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
case "DELETE":
|
case "DELETE":
|
||||||
if uri.Raw() || uri.DeprecatedRaw() {
|
if uri.Raw() || uri.DeprecatedRaw() {
|
||||||
ShowError(w, r, fmt.Sprintf("No DELETE to %s allowed.", uri), http.StatusBadRequest)
|
ShowError(w, req, fmt.Sprintf("No DELETE to %s allowed.", uri), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.HandleDelete(w, req)
|
s.HandleDelete(w, req)
|
||||||
|
|
@ -716,7 +725,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
s.HandleGetFile(w, req)
|
s.HandleGetFile(w, req)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ShowError(w, r, fmt.Sprintf("Method "+r.Method+" is not supported.", uri), http.StatusMethodNotAllowed)
|
ShowError(w, req, fmt.Sprintf("Method "+r.Method+" is not supported.", uri), http.StatusMethodNotAllowed)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -748,13 +757,13 @@ func (s *Server) logError(format string, v ...interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) BadRequest(w http.ResponseWriter, r *Request, reason string) {
|
func (s *Server) BadRequest(w http.ResponseWriter, r *Request, reason string) {
|
||||||
ShowError(w, &r.Request, fmt.Sprintf("Bad request %s %s: %s", r.Method, r.uri, reason), http.StatusBadRequest)
|
ShowError(w, r, fmt.Sprintf("Bad request %s %s: %s", r.Request.Method, r.uri, reason), http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Error(w http.ResponseWriter, r *Request, err error) {
|
func (s *Server) Error(w http.ResponseWriter, r *Request, err error) {
|
||||||
ShowError(w, &r.Request, fmt.Sprintf("Error serving %s %s: %s", r.Method, r.uri, err), http.StatusInternalServerError)
|
ShowError(w, r, fmt.Sprintf("Error serving %s %s: %s", r.Request.Method, r.uri, err), http.StatusInternalServerError)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) NotFound(w http.ResponseWriter, r *Request, err error) {
|
func (s *Server) NotFound(w http.ResponseWriter, r *Request, err error) {
|
||||||
ShowError(w, &r.Request, fmt.Sprintf("NOT FOUND error serving %s %s: %s", r.Method, r.uri, err), http.StatusNotFound)
|
ShowError(w, r, fmt.Sprintf("NOT FOUND error serving %s %s: %s", r.Request.Method, r.uri, err), http.StatusNotFound)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue