Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
f082c1b8
Commit
f082c1b8
authored
May 28, 2015
by
obscuren
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'release/0.9.26'
parents
70867904
d51d74eb
Changes
24
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
779 additions
and
1986 deletions
+779
-1986
admin.go
cmd/geth/admin.go
+2
-2
blocktestcmd.go
cmd/geth/blocktestcmd.go
+1
-1
chaincmd.go
cmd/geth/chaincmd.go
+159
-0
js.go
cmd/geth/js.go
+44
-20
main.go
cmd/geth/main.go
+15
-201
coin.html
cmd/mist/assets/examples/coin.html
+1
-1
main.go
cmd/mist/main.go
+4
-0
cmd.go
cmd/utils/cmd.go
+79
-35
flags.go
cmd/utils/flags.go
+29
-32
db.go
common/db.go
+0
-1
block_processor.go
core/block_processor.go
+52
-32
block_processor_test.go
core/block_processor_test.go
+32
-0
blocks.go
core/blocks.go
+5
-3
chain_manager.go
core/chain_manager.go
+59
-26
manager.go
core/manager.go
+0
-6
log.go
core/state/log.go
+14
-7
receipt.go
core/types/receipt.go
+29
-0
downloader.go
eth/downloader/downloader.go
+16
-0
handler.go
eth/handler.go
+13
-6
sync.go
eth/sync.go
+1
-2
database.go
ethdb/database.go
+6
-58
ethereum_js.go
jsre/ethereum_js.go
+146
-1546
worker.go
miner/worker.go
+71
-6
nat_test.go
p2p/nat/nat_test.go
+1
-1
No files found.
cmd/geth/admin.go
View file @
f082c1b8
...
...
@@ -262,8 +262,8 @@ func (js *jsre) setHead(call otto.FunctionCall) otto.Value {
}
func
(
js
*
jsre
)
downloadProgress
(
call
otto
.
FunctionCall
)
otto
.
Value
{
current
,
max
:=
js
.
ethereum
.
Downloader
()
.
Stats
()
v
,
_
:=
call
.
Otto
.
ToValue
(
fmt
.
Sprintf
(
"%d/%d"
,
current
,
max
)
)
pending
,
cached
:=
js
.
ethereum
.
Downloader
()
.
Stats
()
v
,
_
:=
call
.
Otto
.
ToValue
(
map
[
string
]
interface
{}{
"pending"
:
pending
,
"cached"
:
cached
}
)
return
v
}
...
...
cmd/geth/blocktest.go
→
cmd/geth/blocktest
cmd
.go
View file @
f082c1b8
...
...
@@ -12,7 +12,7 @@ import (
"github.com/ethereum/go-ethereum/tests"
)
var
blocktestC
m
d
=
cli
.
Command
{
var
blocktestC
omman
d
=
cli
.
Command
{
Action
:
runBlockTest
,
Name
:
"blocktest"
,
Usage
:
`loads a block test file`
,
...
...
cmd/geth/chaincmd.go
0 → 100644
View file @
f082c1b8
package
main
import
(
"fmt"
"os"
"path/filepath"
"strconv"
"time"
"github.com/codegangsta/cli"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/logger/glog"
)
var
(
importCommand
=
cli
.
Command
{
Action
:
importChain
,
Name
:
"import"
,
Usage
:
`import a blockchain file`
,
}
exportCommand
=
cli
.
Command
{
Action
:
exportChain
,
Name
:
"export"
,
Usage
:
`export blockchain into file`
,
}
upgradedbCommand
=
cli
.
Command
{
Action
:
upgradeDB
,
Name
:
"upgradedb"
,
Usage
:
"upgrade chainblock database"
,
}
removedbCommand
=
cli
.
Command
{
Action
:
removeDB
,
Name
:
"removedb"
,
Usage
:
"Remove blockchain and state databases"
,
}
dumpCommand
=
cli
.
Command
{
Action
:
dump
,
Name
:
"dump"
,
Usage
:
`dump a specific block from storage`
,
Description
:
`
The arguments are interpreted as block numbers or hashes.
Use "ethereum dump 0" to dump the genesis block.
`
,
}
)
func
importChain
(
ctx
*
cli
.
Context
)
{
if
len
(
ctx
.
Args
())
!=
1
{
utils
.
Fatalf
(
"This command requires an argument."
)
}
chain
,
blockDB
,
stateDB
,
extraDB
:=
utils
.
MakeChain
(
ctx
)
start
:=
time
.
Now
()
err
:=
utils
.
ImportChain
(
chain
,
ctx
.
Args
()
.
First
())
closeAll
(
blockDB
,
stateDB
,
extraDB
)
if
err
!=
nil
{
utils
.
Fatalf
(
"Import error: %v"
,
err
)
}
fmt
.
Printf
(
"Import done in %v"
,
time
.
Since
(
start
))
}
func
exportChain
(
ctx
*
cli
.
Context
)
{
if
len
(
ctx
.
Args
())
!=
1
{
utils
.
Fatalf
(
"This command requires an argument."
)
}
chain
,
_
,
_
,
_
:=
utils
.
MakeChain
(
ctx
)
start
:=
time
.
Now
()
if
err
:=
utils
.
ExportChain
(
chain
,
ctx
.
Args
()
.
First
());
err
!=
nil
{
utils
.
Fatalf
(
"Export error: %v
\n
"
,
err
)
}
fmt
.
Printf
(
"Export done in %v"
,
time
.
Since
(
start
))
}
func
removeDB
(
ctx
*
cli
.
Context
)
{
confirm
,
err
:=
utils
.
PromptConfirm
(
"Remove local databases?"
)
if
err
!=
nil
{
utils
.
Fatalf
(
"%v"
,
err
)
}
if
confirm
{
fmt
.
Println
(
"Removing chain and state databases..."
)
start
:=
time
.
Now
()
os
.
RemoveAll
(
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
"blockchain"
))
os
.
RemoveAll
(
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
"state"
))
fmt
.
Printf
(
"Removed in %v
\n
"
,
time
.
Since
(
start
))
}
else
{
fmt
.
Println
(
"Operation aborted"
)
}
}
func
upgradeDB
(
ctx
*
cli
.
Context
)
{
glog
.
Infoln
(
"Upgrading blockchain database"
)
chain
,
blockDB
,
stateDB
,
extraDB
:=
utils
.
MakeChain
(
ctx
)
v
,
_
:=
blockDB
.
Get
([]
byte
(
"BlockchainVersion"
))
bcVersion
:=
int
(
common
.
NewValue
(
v
)
.
Uint
())
if
bcVersion
==
0
{
bcVersion
=
core
.
BlockChainVersion
}
// Export the current chain.
filename
:=
fmt
.
Sprintf
(
"blockchain_%d_%s.chain"
,
bcVersion
,
time
.
Now
()
.
Format
(
"20060102_150405"
))
exportFile
:=
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
filename
)
if
err
:=
utils
.
ExportChain
(
chain
,
exportFile
);
err
!=
nil
{
utils
.
Fatalf
(
"Unable to export chain for reimport %s"
,
err
)
}
closeAll
(
blockDB
,
stateDB
,
extraDB
)
os
.
RemoveAll
(
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
"blockchain"
))
os
.
RemoveAll
(
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
"state"
))
// Import the chain file.
chain
,
blockDB
,
stateDB
,
extraDB
=
utils
.
MakeChain
(
ctx
)
blockDB
.
Put
([]
byte
(
"BlockchainVersion"
),
common
.
NewValue
(
core
.
BlockChainVersion
)
.
Bytes
())
err
:=
utils
.
ImportChain
(
chain
,
exportFile
)
closeAll
(
blockDB
,
stateDB
,
extraDB
)
if
err
!=
nil
{
utils
.
Fatalf
(
"Import error %v (a backup is made in %s, use the import command to import it)"
,
err
,
exportFile
)
}
else
{
os
.
Remove
(
exportFile
)
glog
.
Infoln
(
"Import finished"
)
}
}
func
dump
(
ctx
*
cli
.
Context
)
{
chain
,
_
,
stateDB
,
_
:=
utils
.
MakeChain
(
ctx
)
for
_
,
arg
:=
range
ctx
.
Args
()
{
var
block
*
types
.
Block
if
hashish
(
arg
)
{
block
=
chain
.
GetBlock
(
common
.
HexToHash
(
arg
))
}
else
{
num
,
_
:=
strconv
.
Atoi
(
arg
)
block
=
chain
.
GetBlockByNumber
(
uint64
(
num
))
}
if
block
==
nil
{
fmt
.
Println
(
"{}"
)
utils
.
Fatalf
(
"block not found"
)
}
else
{
state
:=
state
.
New
(
block
.
Root
(),
stateDB
)
fmt
.
Printf
(
"%s
\n
"
,
state
.
Dump
())
}
}
}
// hashish returns true for strings that look like hashes.
func
hashish
(
x
string
)
bool
{
_
,
err
:=
strconv
.
Atoi
(
x
)
return
err
!=
nil
}
func
closeAll
(
dbs
...
common
.
Database
)
{
for
_
,
db
:=
range
dbs
{
db
.
Close
()
}
}
cmd/geth/js.go
View file @
f082c1b8
...
...
@@ -22,6 +22,7 @@ import (
"fmt"
"math/big"
"os"
"os/signal"
"path/filepath"
"strings"
...
...
@@ -47,7 +48,8 @@ type dumbterm struct{ r *bufio.Reader }
func
(
r
dumbterm
)
Prompt
(
p
string
)
(
string
,
error
)
{
fmt
.
Print
(
p
)
return
r
.
r
.
ReadString
(
'\n'
)
line
,
err
:=
r
.
r
.
ReadString
(
'\n'
)
return
strings
.
TrimSuffix
(
line
,
"
\n
"
),
err
}
func
(
r
dumbterm
)
PasswordPrompt
(
p
string
)
(
string
,
error
)
{
...
...
@@ -182,30 +184,52 @@ func (self *jsre) exec(filename string) error {
}
func
(
self
*
jsre
)
interactive
()
{
for
{
input
,
err
:=
self
.
Prompt
(
self
.
ps1
)
if
err
!=
nil
{
break
// Read input lines.
prompt
:=
make
(
chan
string
)
inputln
:=
make
(
chan
string
)
go
func
()
{
defer
close
(
inputln
)
for
{
line
,
err
:=
self
.
Prompt
(
<-
prompt
)
if
err
!=
nil
{
return
}
inputln
<-
line
}
if
input
==
""
{
continue
}()
// Wait for Ctrl-C, too.
sig
:=
make
(
chan
os
.
Signal
,
1
)
signal
.
Notify
(
sig
,
os
.
Interrupt
)
defer
func
()
{
if
self
.
atexit
!=
nil
{
self
.
atexit
()
}
str
+=
input
+
"
\n
"
self
.
setIndent
()
if
indentCount
<=
0
{
if
input
==
"exit"
{
break
self
.
re
.
Stop
(
false
)
}()
for
{
prompt
<-
self
.
ps1
select
{
case
<-
sig
:
fmt
.
Println
(
"caught interrupt, exiting"
)
return
case
input
,
ok
:=
<-
inputln
:
if
!
ok
||
indentCount
<=
0
&&
input
==
"exit"
{
return
}
if
input
==
""
{
continue
}
str
+=
input
+
"
\n
"
self
.
setIndent
()
if
indentCount
<=
0
{
hist
:=
str
[
:
len
(
str
)
-
1
]
self
.
AppendHistory
(
hist
)
self
.
parseInput
(
str
)
str
=
""
}
hist
:=
str
[
:
len
(
str
)
-
1
]
self
.
AppendHistory
(
hist
)
self
.
parseInput
(
str
)
str
=
""
}
}
if
self
.
atexit
!=
nil
{
self
.
atexit
()
}
self
.
re
.
Stop
(
false
)
}
func
(
self
*
jsre
)
withHistory
(
op
func
(
*
os
.
File
))
{
...
...
cmd/geth/main.go
View file @
f082c1b8
...
...
@@ -24,31 +24,27 @@ import (
"fmt"
"io"
"io/ioutil"
_
"net/http/pprof"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
"github.com/codegangsta/cli"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/logger"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
)
import
_
"net/http/pprof"
const
(
ClientIdentifier
=
"Geth"
Version
=
"0.9.2
5
"
Version
=
"0.9.2
6
"
)
var
(
...
...
@@ -68,7 +64,12 @@ func init() {
app
.
Action
=
run
app
.
HideVersion
=
true
// we have a command to print the version
app
.
Commands
=
[]
cli
.
Command
{
blocktestCmd
,
blocktestCommand
,
importCommand
,
exportCommand
,
upgradedbCommand
,
removedbCommand
,
dumpCommand
,
{
Action
:
makedag
,
Name
:
"makedag"
,
...
...
@@ -193,15 +194,6 @@ nodes.
},
},
},
{
Action
:
dump
,
Name
:
"dump"
,
Usage
:
`dump a specific block from storage`
,
Description
:
`
The arguments are interpreted as block numbers or hashes.
Use "ethereum dump 0" to dump the genesis block.
`
,
},
{
Action
:
console
,
Name
:
"console"
,
...
...
@@ -221,26 +213,6 @@ The JavaScript VM exposes a node admin interface as well as the Ðapp
JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Console
`
,
},
{
Action
:
importchain
,
Name
:
"import"
,
Usage
:
`import a blockchain file`
,
},
{
Action
:
exportchain
,
Name
:
"export"
,
Usage
:
`export blockchain into file`
,
},
{
Action
:
upgradeDb
,
Name
:
"upgradedb"
,
Usage
:
"upgrade chainblock database"
,
},
{
Action
:
removeDb
,
Name
:
"removedb"
,
Usage
:
"Remove blockchain and state databases"
,
},
}
app
.
Flags
=
[]
cli
.
Flag
{
utils
.
IdentityFlag
,
...
...
@@ -282,17 +254,12 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils
.
SolcPathFlag
,
}
app
.
Before
=
func
(
ctx
*
cli
.
Context
)
error
{
utils
.
SetupLogger
(
ctx
)
if
ctx
.
GlobalBool
(
utils
.
PProfEanbledFlag
.
Name
)
{
utils
.
StartPProf
(
ctx
)
}
return
nil
}
// missing:
// flag.StringVar(&ConfigFile, "conf", defaultConfigFile, "config file")
// flag.BoolVar(&DiffTool, "difftool", false, "creates output for diff'ing. Sets LogLevel=0")
// flag.StringVar(&DiffType, "diff", "all", "sets the level of diff output [vm, all]. Has no effect if difftool=false")
}
func
main
()
{
...
...
@@ -373,13 +340,13 @@ func unlockAccount(ctx *cli.Context, am *accounts.Manager, account string) (pass
var
err
error
// Load startup keys. XXX we are going to need a different format
if
len
(
account
)
==
0
{
if
!
((
len
(
account
)
==
40
)
||
(
len
(
account
)
==
42
))
{
// with or without 0x
utils
.
Fatalf
(
"Invalid account address '%s'"
,
account
)
}
// Attempt to unlock the account 3 times
attempts
:=
3
for
tries
:=
0
;
tries
<
attempts
;
tries
++
{
msg
:=
fmt
.
Sprintf
(
"Unlocking account %s
...%s | Attempt %d/%d"
,
account
[
:
8
],
account
[
len
(
account
)
-
6
:
]
,
tries
+
1
,
attempts
)
msg
:=
fmt
.
Sprintf
(
"Unlocking account %s
| Attempt %d/%d"
,
account
,
tries
+
1
,
attempts
)
passphrase
=
getPassPhrase
(
ctx
,
msg
,
false
)
err
=
am
.
Unlock
(
common
.
HexToAddress
(
account
),
passphrase
)
if
err
==
nil
{
...
...
@@ -427,7 +394,7 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) {
}
func
accountList
(
ctx
*
cli
.
Context
)
{
am
:=
utils
.
Get
AccountManager
(
ctx
)
am
:=
utils
.
Make
AccountManager
(
ctx
)
accts
,
err
:=
am
.
Accounts
()
if
err
!=
nil
{
utils
.
Fatalf
(
"Could not list accounts: %v"
,
err
)
...
...
@@ -469,7 +436,7 @@ func getPassPhrase(ctx *cli.Context, desc string, confirmation bool) (passphrase
}
func
accountCreate
(
ctx
*
cli
.
Context
)
{
am
:=
utils
.
Get
AccountManager
(
ctx
)
am
:=
utils
.
Make
AccountManager
(
ctx
)
passphrase
:=
getPassPhrase
(
ctx
,
"Your new account is locked with a password. Please give a password. Do not forget this password."
,
true
)
acct
,
err
:=
am
.
NewAccount
(
passphrase
)
if
err
!=
nil
{
...
...
@@ -488,7 +455,7 @@ func importWallet(ctx *cli.Context) {
utils
.
Fatalf
(
"Could not read wallet file: %v"
,
err
)
}
am
:=
utils
.
Get
AccountManager
(
ctx
)
am
:=
utils
.
Make
AccountManager
(
ctx
)
passphrase
:=
getPassPhrase
(
ctx
,
""
,
false
)
acct
,
err
:=
am
.
ImportPreSaleKey
(
keyJson
,
passphrase
)
...
...
@@ -503,7 +470,7 @@ func accountImport(ctx *cli.Context) {
if
len
(
keyfile
)
==
0
{
utils
.
Fatalf
(
"keyfile must be given as argument"
)
}
am
:=
utils
.
Get
AccountManager
(
ctx
)
am
:=
utils
.
Make
AccountManager
(
ctx
)
passphrase
:=
getPassPhrase
(
ctx
,
"Your new account is locked with a password. Please give a password. Do not forget this password."
,
true
)
acct
,
err
:=
am
.
Import
(
keyfile
,
passphrase
)
if
err
!=
nil
{
...
...
@@ -512,153 +479,6 @@ func accountImport(ctx *cli.Context) {
fmt
.
Printf
(
"Address: %x
\n
"
,
acct
)
}
func
importchain
(
ctx
*
cli
.
Context
)
{
if
len
(
ctx
.
Args
())
!=
1
{
utils
.
Fatalf
(
"This command requires an argument."
)
}
cfg
:=
utils
.
MakeEthConfig
(
ClientIdentifier
,
Version
,
ctx
)
cfg
.
SkipBcVersionCheck
=
true
ethereum
,
err
:=
eth
.
New
(
cfg
)
if
err
!=
nil
{
utils
.
Fatalf
(
"%v
\n
"
,
err
)
}
chainmgr
:=
ethereum
.
ChainManager
()
start
:=
time
.
Now
()
err
=
utils
.
ImportChain
(
chainmgr
,
ctx
.
Args
()
.
First
())
if
err
!=
nil
{
utils
.
Fatalf
(
"Import error: %v
\n
"
,
err
)
}
// force database flush
ethereum
.
BlockDb
()
.
Flush
()
ethereum
.
StateDb
()
.
Flush
()
ethereum
.
ExtraDb
()
.
Flush
()
fmt
.
Printf
(
"Import done in %v"
,
time
.
Since
(
start
))
return
}
func
exportchain
(
ctx
*
cli
.
Context
)
{
if
len
(
ctx
.
Args
())
!=
1
{
utils
.
Fatalf
(
"This command requires an argument."
)
}
cfg
:=
utils
.
MakeEthConfig
(
ClientIdentifier
,
nodeNameVersion
,
ctx
)
cfg
.
SkipBcVersionCheck
=
true
ethereum
,
err
:=
eth
.
New
(
cfg
)
if
err
!=
nil
{
utils
.
Fatalf
(
"%v
\n
"
,
err
)
}
chainmgr
:=
ethereum
.
ChainManager
()
start
:=
time
.
Now
()
err
=
utils
.
ExportChain
(
chainmgr
,
ctx
.
Args
()
.
First
())
if
err
!=
nil
{
utils
.
Fatalf
(
"Export error: %v
\n
"
,
err
)
}
fmt
.
Printf
(
"Export done in %v"
,
time
.
Since
(
start
))
return
}
func
removeDb
(
ctx
*
cli
.
Context
)
{
confirm
,
err
:=
utils
.
PromptConfirm
(
"Remove local databases?"
)
if
err
!=
nil
{
utils
.
Fatalf
(
"%v"
,
err
)
}
if
confirm
{
fmt
.
Println
(
"Removing chain and state databases..."
)
start
:=
time
.
Now
()
os
.
RemoveAll
(
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
"blockchain"
))
os
.
RemoveAll
(
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
"state"
))
fmt
.
Printf
(
"Removed in %v
\n
"
,
time
.
Since
(
start
))
}
else
{
fmt
.
Println
(
"Operation aborted"
)
}
}
func
upgradeDb
(
ctx
*
cli
.
Context
)
{
fmt
.
Println
(
"Upgrade blockchain DB"
)
cfg
:=
utils
.
MakeEthConfig
(
ClientIdentifier
,
Version
,
ctx
)
cfg
.
SkipBcVersionCheck
=
true
ethereum
,
err
:=
eth
.
New
(
cfg
)
if
err
!=
nil
{
utils
.
Fatalf
(
"%v
\n
"
,
err
)
}
v
,
_
:=
ethereum
.
BlockDb
()
.
Get
([]
byte
(
"BlockchainVersion"
))
bcVersion
:=
int
(
common
.
NewValue
(
v
)
.
Uint
())
if
bcVersion
==
0
{
bcVersion
=
core
.
BlockChainVersion
}
filename
:=
fmt
.
Sprintf
(
"blockchain_%d_%s.chain"
,
bcVersion
,
time
.
Now
()
.
Format
(
"20060102_150405"
))
exportFile
:=
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
filename
)
err
=
utils
.
ExportChain
(
ethereum
.
ChainManager
(),
exportFile
)
if
err
!=
nil
{
utils
.
Fatalf
(
"Unable to export chain for reimport %s
\n
"
,
err
)
}
ethereum
.
BlockDb
()
.
Close
()
ethereum
.
StateDb
()
.
Close
()
ethereum
.
ExtraDb
()
.
Close
()
os
.
RemoveAll
(
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
"blockchain"
))
os
.
RemoveAll
(
filepath
.
Join
(
ctx
.
GlobalString
(
utils
.
DataDirFlag
.
Name
),
"state"
))
ethereum
,
err
=
eth
.
New
(
cfg
)
if
err
!=
nil
{
utils
.
Fatalf
(
"%v
\n
"
,
err
)
}
ethereum
.
BlockDb
()
.
Put
([]
byte
(
"BlockchainVersion"
),
common
.
NewValue
(
core
.
BlockChainVersion
)
.
Bytes
())
err
=
utils
.
ImportChain
(
ethereum
.
ChainManager
(),
exportFile
)
if
err
!=
nil
{
utils
.
Fatalf
(
"Import error %v (a backup is made in %s, use the import command to import it)
\n
"
,
err
,
exportFile
)
}
// force database flush
ethereum
.
BlockDb
()
.
Flush
()
ethereum
.
StateDb
()
.
Flush
()
ethereum
.
ExtraDb
()
.
Flush
()
os
.
Remove
(
exportFile
)
fmt
.
Println
(
"Import finished"
)
}
func
dump
(
ctx
*
cli
.
Context
)
{
chainmgr
,
_
,
stateDb
:=
utils
.
GetChain
(
ctx
)
for
_
,
arg
:=
range
ctx
.
Args
()
{
var
block
*
types
.
Block
if
hashish
(
arg
)
{
block
=
chainmgr
.
GetBlock
(
common
.
HexToHash
(
arg
))
}
else
{
num
,
_
:=
strconv
.
Atoi
(
arg
)
block
=
chainmgr
.
GetBlockByNumber
(
uint64
(
num
))
}
if
block
==
nil
{
fmt
.
Println
(
"{}"
)
utils
.
Fatalf
(
"block not found"
)
}
else
{
statedb
:=
state
.
New
(
block
.
Root
(),
stateDb
)
fmt
.
Printf
(
"%s
\n
"
,
statedb
.
Dump
())
}
}
}
func
makedag
(
ctx
*
cli
.
Context
)
{
args
:=
ctx
.
Args
()
wrongArgs
:=
func
()
{
...
...
@@ -701,9 +521,3 @@ func version(c *cli.Context) {
fmt
.
Printf
(
"GOPATH=%s
\n
"
,
os
.
Getenv
(
"GOPATH"
))
fmt
.
Printf
(
"GOROOT=%s
\n
"
,
runtime
.
GOROOT
())
}
// hashish returns true for strings that look like hashes.
func
hashish
(
x
string
)
bool
{
_
,
err
:=
strconv
.
Atoi
(
x
)
return
err
!=
nil
}
cmd/mist/assets/examples/coin.html
View file @
f082c1b8
...
...
@@ -102,7 +102,7 @@ window.filter = filter;
var
amount
=
parseInt
(
value
.
value
);
console
.
log
(
"transact: "
,
to
.
value
,
" => "
,
amount
)
contract
.
send
Transaction
({
from
:
eth
.
accounts
[
0
]}).
send
(
to
.
value
,
amount
);
contract
.
send
.
sendTransaction
(
to
.
value
,
amount
,{
from
:
eth
.
accounts
[
0
]}
);
to
.
value
=
""
;
value
.
value
=
""
;
...
...
cmd/mist/main.go
View file @
f082c1b8
...
...
@@ -86,6 +86,10 @@ func init() {
utils
.
BlockchainVersionFlag
,
utils
.
NetworkIdFlag
,
}
app
.
Before
=
func
(
ctx
*
cli
.
Context
)
error
{
utils
.
SetupLogger
(
ctx
)
return
nil
}
}
func
main
()
{
...
...
cmd/utils/cmd.go
View file @
f082c1b8
...
...
@@ -40,6 +40,10 @@ import (
"github.com/peterh/liner"
)
const
(
importBatchSize
=
2500
)
var
interruptCallbacks
=
[]
func
(
os
.
Signal
){}
// Register interrupt handlers callbacks
...
...
@@ -125,10 +129,17 @@ func initDataDir(Datadir string) {
}
}
// Fatalf formats a message to standard output and exits the program.
// Fatalf formats a message to standard error and exits the program.
// The message is also printed to standard output if standard error
// is redirected to a different file.
func
Fatalf
(
format
string
,
args
...
interface
{})
{
fmt
.
Fprintf
(
os
.
Stderr
,
"Fatal: "
+
format
+
"
\n
"
,
args
...
)
fmt
.
Fprintf
(
os
.
Stdout
,
"Fatal: "
+
format
+
"
\n
"
,
args
...
)
w
:=
io
.
MultiWriter
(
os
.
Stdout
,
os
.
Stderr
)
outf
,
_
:=
os
.
Stdout
.
Stat
()
errf
,
_
:=
os
.
Stderr
.
Stat
()
if
outf
!=
nil
&&
errf
!=
nil
&&
os
.
SameFile
(
outf
,
errf
)
{
w
=
os
.
Stderr
}
fmt
.
Fprintf
(
w
,
"Fatal: "
+
format
+
"
\n
"
,
args
...
)
logger
.
Flush
()
os
.
Exit
(
1
)
}
...
...
@@ -166,53 +177,86 @@ func FormatTransactionData(data string) []byte {
return
d
}
func
ImportChain
(
chainmgr
*
core
.
ChainManager
,
fn
string
)
error
{
fmt
.
Printf
(
"importing blockchain '%s'
\n
"
,
fn
)
fh
,
err
:=
os
.
OpenFile
(
fn
,
os
.
O_RDONLY
,
os
.
ModePerm
)
func
ImportChain
(
chain
*
core
.
ChainManager
,
fn
string
)
error
{
// Watch for Ctrl-C while the import is running.
// If a signal is received, the import will stop at the next batch.
interrupt
:=
make
(
chan
os
.
Signal
,
1
)
stop
:=
make
(
chan
struct
{})
signal
.
Notify
(
interrupt
,
os
.
Interrupt
)
defer
signal
.
Stop
(
interrupt
)
defer
close
(
interrupt
)
go
func
()
{
if
_
,
ok
:=
<-
interrupt
;
ok
{
glog
.
Info
(
"caught interrupt during import, will stop at next batch"
)
}
close
(
stop
)
}()
checkInterrupt
:=
func
()
bool
{
select
{
case
<-
stop
:
return
true
default
:
return
false
}
}
glog
.
Infoln
(
"Importing blockchain"
,
fn
)
fh
,
err
:=
os
.
Open
(
fn
)
if
err
!=
nil
{
return
err
}
defer
fh
.
Close
()
chainmgr
.
Reset
()
stream
:=
rlp
.
NewStream
(
fh
,
0
)
var
i
,
n
int
batchSize
:=
2500
blocks
:=
make
(
types
.
Blocks
,
batchSize
)
for
;
;
i
++
{
var
b
types
.
Block
if
err
:=
stream
.
Decode
(
&
b
);
err
==
io
.
EOF
{
break
}
else
if
err
!=
nil
{
return
fmt
.
Errorf
(
"at block %d: %v"
,
i
,
err
)
// Run actual the import.
blocks
:=
make
(
types
.
Blocks
,
importBatchSize
)
n
:=
0
for
batch
:=
0
;
;
batch
++
{
// Load a batch of RLP blocks.
if
checkInterrupt
()
{
return
fmt
.
Errorf
(
"interrupted"
)
}
blocks
[
n
]
=
&
b
n
++
if
n
==
batchSize
{
if
_
,
err
:=
chainmgr
.
InsertChain
(
blocks
);
err
!=
nil
{
return
fmt
.
Errorf
(
"
invalid block %v"
,
err
)
i
:=
0
for
;
i
<
importBatchSize
;
i
++
{
var
b
types
.
Block
if
err
:=
stream
.
Decode
(
&
b
);
err
==
io
.
EOF
{
break
}
else
if
err
!=
nil
{
return
fmt
.
Errorf
(
"
at block %d: %v"
,
n
,
err
)
}
n
=
0
blocks
=
make
(
types
.
Blocks
,
batchSize
)
blocks
[
i
]
=
&
b
n
++
}
if
i
==
0
{
break
}
// Import the batch.
if
checkInterrupt
()
{
return
fmt
.
Errorf
(
"interrupted"
)
}
if
hasAllBlocks
(
chain
,
blocks
[
:
i
])
{
glog
.
Infof
(
"skipping batch %d, all blocks present [%x / %x]"
,
batch
,
blocks
[
0
]
.
Hash
()
.
Bytes
()[
:
4
],
blocks
[
i
-
1
]
.
Hash
()
.
Bytes
()[
:
4
])
continue
}
if
_
,
err
:=
chain
.
InsertChain
(
blocks
[
:
i
]);
err
!=
nil
{
return
fmt
.
Errorf
(
"invalid block %d: %v"
,
n
,
err
)
}
}
return
nil
}
if
n
>
0
{
if
_
,
err
:=
chainmgr
.
InsertChain
(
blocks
[
:
n
]);
err
!=
nil
{
return
fmt
.
Errorf
(
"invalid block %v"
,
err
)
func
hasAllBlocks
(
chain
*
core
.
ChainManager
,
bs
[]
*
types
.
Block
)
bool
{
for
_
,
b
:=
range
bs
{
if
!
chain
.
HasBlock
(
b
.
Hash
())
{
return
false
}
}
fmt
.
Printf
(
"imported %d blocks
\n
"
,
i
)
return
nil
return
true
}
func
ExportChain
(
chainmgr
*
core
.
ChainManager
,
fn
string
)
error
{
fmt
.
Printf
(
"exporting blockchain '%s'
\n
"
,
fn
)
glog
.
Infoln
(
"Exporting blockchain to
"
,
fn
)
fh
,
err
:=
os
.
OpenFile
(
fn
,
os
.
O_CREATE
|
os
.
O_WRONLY
|
os
.
O_TRUNC
,
os
.
ModePerm
)
if
err
!=
nil
{
return
err
...
...
@@ -221,6 +265,6 @@ func ExportChain(chainmgr *core.ChainManager, fn string) error {
if
err
:=
chainmgr
.
Export
(
fh
);
err
!=
nil
{
return
err
}
fmt
.
Printf
(
"exported blockchain
\n
"
)
glog
.
Infoln
(
"Exported blockchain to"
,
fn
)
return
nil
}
cmd/utils/flags.go
View file @
f082c1b8
...
...
@@ -256,7 +256,8 @@ var (
}
)
func
GetNAT
(
ctx
*
cli
.
Context
)
nat
.
Interface
{
// MakeNAT creates a port mapper from set command line flags.
func
MakeNAT
(
ctx
*
cli
.
Context
)
nat
.
Interface
{
natif
,
err
:=
nat
.
Parse
(
ctx
.
GlobalString
(
NATFlag
.
Name
))
if
err
!=
nil
{
Fatalf
(
"Option %s: %v"
,
NATFlag
.
Name
,
err
)
...
...
@@ -264,7 +265,8 @@ func GetNAT(ctx *cli.Context) nat.Interface {
return
natif
}
func
GetNodeKey
(
ctx
*
cli
.
Context
)
(
key
*
ecdsa
.
PrivateKey
)
{
// MakeNodeKey creates a node key from set command line flags.
func
MakeNodeKey
(
ctx
*
cli
.
Context
)
(
key
*
ecdsa
.
PrivateKey
)
{
hex
,
file
:=
ctx
.
GlobalString
(
NodeKeyHexFlag
.
Name
),
ctx
.
GlobalString
(
NodeKeyFileFlag
.
Name
)
var
err
error
switch
{
...
...
@@ -282,21 +284,12 @@ func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) {
return
key
}
// MakeEthConfig creates ethereum options from set command line flags.
func
MakeEthConfig
(
clientID
,
version
string
,
ctx
*
cli
.
Context
)
*
eth
.
Config
{
// Set verbosity on glog
glog
.
SetV
(
ctx
.
GlobalInt
(
VerbosityFlag
.
Name
))
glog
.
CopyStandardLogTo
(
"INFO"
)
// Set the log type
//glog.SetToStderr(ctx.GlobalBool(LogToStdErrFlag.Name))
glog
.
SetToStderr
(
true
)
// Set the log dir
glog
.
SetLogDir
(
ctx
.
GlobalString
(
LogFileFlag
.
Name
))
customName
:=
ctx
.
GlobalString
(
IdentityFlag
.
Name
)
if
len
(
customName
)
>
0
{
clientID
+=
"/"
+
customName
}
return
&
eth
.
Config
{
Name
:
common
.
MakeName
(
clientID
,
version
),
DataDir
:
ctx
.
GlobalString
(
DataDirFlag
.
Name
),
...
...
@@ -309,15 +302,15 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
LogJSON
:
ctx
.
GlobalString
(
LogJSONFlag
.
Name
),
Etherbase
:
ctx
.
GlobalString
(
EtherbaseFlag
.
Name
),
MinerThreads
:
ctx
.
GlobalInt
(
MinerThreadsFlag
.
Name
),
AccountManager
:
Get
AccountManager
(
ctx
),
AccountManager
:
Make
AccountManager
(
ctx
),
VmDebug
:
ctx
.
GlobalBool
(
VMDebugFlag
.
Name
),
MaxPeers
:
ctx
.
GlobalInt
(
MaxPeersFlag
.
Name
),
MaxPendingPeers
:
ctx
.
GlobalInt
(
MaxPendingPeersFlag
.
Name
),
Port
:
ctx
.
GlobalString
(
ListenPortFlag
.
Name
),
NAT
:
Get
NAT
(
ctx
),
NAT
:
Make
NAT
(
ctx
),
NatSpec
:
ctx
.
GlobalBool
(
NatspecEnabledFlag
.
Name
),
Discovery
:
!
ctx
.
GlobalBool
(
NoDiscoverFlag
.
Name
),
NodeKey
:
Get
NodeKey
(
ctx
),
NodeKey
:
Make
NodeKey
(
ctx
),
Shh
:
ctx
.
GlobalBool
(
WhisperEnabledFlag
.
Name
),
Dial
:
true
,
BootNodes
:
ctx
.
GlobalString
(
BootnodesFlag
.
Name
),
...
...
@@ -327,35 +320,39 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
}
}
func
GetChain
(
ctx
*
cli
.
Context
)
(
*
core
.
ChainManager
,
common
.
Database
,
common
.
Database
)
{
dataDir
:=
ctx
.
GlobalString
(
DataDirFlag
.
Name
)
// SetupLogger configures glog from the logging-related command line flags.
func
SetupLogger
(
ctx
*
cli
.
Context
)
{
glog
.
SetV
(
ctx
.
GlobalInt
(
VerbosityFlag
.
Name
))
glog
.
CopyStandardLogTo
(
"INFO"
)
glog
.
SetToStderr
(
true
)
glog
.
SetLogDir
(
ctx
.
GlobalString
(
LogFileFlag
.
Name
))
}
blockDb
,
err
:=
ethdb
.
NewLDBDatabase
(
filepath
.
Join
(
dataDir
,
"blockchain"
))
if
err
!=
nil
{
// MakeChain creates a chain manager from set command line flags.
func
MakeChain
(
ctx
*
cli
.
Context
)
(
chain
*
core
.
ChainManager
,
blockDB
,
stateDB
,
extraDB
common
.
Database
)
{
dd
:=
ctx
.
GlobalString
(
DataDirFlag
.
Name
)
var
err
error
if
blockDB
,
err
=
ethdb
.
NewLDBDatabase
(
filepath
.
Join
(
dd
,
"blockchain"
));
err
!=
nil
{
Fatalf
(
"Could not open database: %v"
,
err
)
}
stateDb
,
err
:=
ethdb
.
NewLDBDatabase
(
filepath
.
Join
(
dataDir
,
"state"
))
if
err
!=
nil
{
if
stateDB
,
err
=
ethdb
.
NewLDBDatabase
(
filepath
.
Join
(
dd
,
"state"
));
err
!=
nil
{
Fatalf
(
"Could not open database: %v"
,
err
)
}
extraDb
,
err
:=
ethdb
.
NewLDBDatabase
(
filepath
.
Join
(
dataDir
,
"extra"
))
if
err
!=
nil
{
if
extraDB
,
err
=
ethdb
.
NewLDBDatabase
(
filepath
.
Join
(
dd
,
"extra"
));
err
!=
nil
{
Fatalf
(
"Could not open database: %v"
,
err
)
}
eventMux
:=
new
(
event
.
TypeMux
)
pow
:=
ethash
.
New
()
chainManager
:=
core
.
NewChainManager
(
blockDb
,
stateDb
,
pow
,
eventMux
)
txPool
:=
core
.
NewTxPool
(
eventMux
,
chainManager
.
State
,
chainManager
.
GasLimit
)
blockProcessor
:=
core
.
NewBlockProcessor
(
stateDb
,
extraDb
,
pow
,
txPool
,
chainManager
,
eventMux
)
chainManager
.
SetProcessor
(
blockProcessor
)
return
chainManager
,
blockDb
,
stateDb
chain
=
core
.
NewChainManager
(
blockDB
,
stateDB
,
pow
,
eventMux
)
txpool
:=
core
.
NewTxPool
(
eventMux
,
chain
.
State
,
chain
.
GasLimit
)
proc
:=
core
.
NewBlockProcessor
(
stateDB
,
extraDB
,
pow
,
txpool
,
chain
,
eventMux
)
chain
.
SetProcessor
(
proc
)
return
chain
,
blockDB
,
stateDB
,
extraDB
}
func
GetAccountManager
(
ctx
*
cli
.
Context
)
*
accounts
.
Manager
{
// MakeChain creates an account manager from set command line flags.
func
MakeAccountManager
(
ctx
*
cli
.
Context
)
*
accounts
.
Manager
{
dataDir
:=
ctx
.
GlobalString
(
DataDirFlag
.
Name
)
ks
:=
crypto
.
NewKeyStorePassphrase
(
filepath
.
Join
(
dataDir
,
"keystore"
))
return
accounts
.
NewManager
(
ks
)
...
...
common/db.go
View file @
f082c1b8
...
...
@@ -5,7 +5,6 @@ type Database interface {
Put
(
key
[]
byte
,
value
[]
byte
)
Get
(
key
[]
byte
)
([]
byte
,
error
)
Delete
(
key
[]
byte
)
error
LastKnownTD
()
[]
byte
Close
()
Flush
()
error
}
core/block_processor.go
View file @
f082c1b8
...
...
@@ -40,11 +40,6 @@ type BlockProcessor struct {
txpool
*
TxPool
// The last attempted block is mainly used for debugging purposes
// This does not have to be a valid block and will be set during
// 'Process' & canonical validation.
lastAttemptedBlock
*
types
.
Block
events
event
.
Subscription
eventMux
*
event
.
TypeMux
...
...
@@ -188,8 +183,6 @@ func (sm *BlockProcessor) Process(block *types.Block) (logs state.Logs, err erro
}
func
(
sm
*
BlockProcessor
)
processWithParent
(
block
,
parent
*
types
.
Block
)
(
logs
state
.
Logs
,
err
error
)
{
sm
.
lastAttemptedBlock
=
block
// Create a new state based on the parent's root (e.g., create copy)
state
:=
state
.
New
(
parent
.
Root
(),
sm
.
db
)
...
...
@@ -255,6 +248,12 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
return
}
// store the receipts
err
=
putReceipts
(
sm
.
extraDb
,
block
.
Hash
(),
receipts
)
if
err
!=
nil
{
return
nil
,
err
}
// Calculate the td for this block
//td = CalculateTD(block, parent)
// Sync the current block's state to the database
...
...
@@ -268,26 +267,11 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
putTx
(
sm
.
extraDb
,
tx
,
block
,
uint64
(
i
))
}
receiptsRlp
:=
block
.
Receipts
()
.
RlpEncode
()
sm
.
extraDb
.
Put
(
append
(
receiptsPre
,
block
.
Hash
()
.
Bytes
()
...
),
receiptsRlp
)
return
state
.
Logs
(),
nil
}
func
(
self
*
BlockProcessor
)
GetBlockReceipts
(
bhash
common
.
Hash
)
(
receipts
types
.
Receipts
,
err
error
)
{
var
rdata
[]
byte
rdata
,
err
=
self
.
extraDb
.
Get
(
append
(
receiptsPre
,
bhash
[
:
]
...
))
if
err
==
nil
{
err
=
rlp
.
DecodeBytes
(
rdata
,
&
receipts
)
}
return
}
// Validates the current block. Returns an error if the block was invalid,
// an uncle or anything that isn't on the current block chain.
// Validation validates easy over difficult (dagger takes longer time = difficult)
// See YP section 4.3.4. "Block Header Validity"
// Validates a block. Returns an error if the block is invalid.
func
(
sm
*
BlockProcessor
)
ValidateHeader
(
block
,
parent
*
types
.
Header
,
checkPow
bool
)
error
{
if
big
.
NewInt
(
int64
(
len
(
block
.
Extra
)))
.
Cmp
(
params
.
MaximumExtraDataSize
)
==
1
{
return
fmt
.
Errorf
(
"Block extra data too long (%d)"
,
len
(
block
.
Extra
))
...
...
@@ -298,16 +282,14 @@ func (sm *BlockProcessor) ValidateHeader(block, parent *types.Header, checkPow b
return
fmt
.
Errorf
(
"Difficulty check failed for block %v, %v"
,
block
.
Difficulty
,
expd
)
}
// block.gasLimit - parent.gasLimit <= parent.gasLimit / GasLimitBoundDivisor
a
:=
new
(
big
.
Int
)
.
Sub
(
block
.
GasLimit
,
parent
.
GasLimit
)
a
.
Abs
(
a
)
b
:=
new
(
big
.
Int
)
.
Div
(
parent
.
GasLimit
,
params
.
GasLimitBoundDivisor
)
if
!
(
a
.
Cmp
(
b
)
<
=
0
)
||
(
block
.
GasLimit
.
Cmp
(
params
.
MinGasLimit
)
==
-
1
)
{
if
!
(
a
.
Cmp
(
b
)
<
0
)
||
(
block
.
GasLimit
.
Cmp
(
params
.
MinGasLimit
)
==
-
1
)
{
return
fmt
.
Errorf
(
"GasLimit check failed for block %v (%v > %v)"
,
block
.
GasLimit
,
a
,
b
)
}
// Allow future blocks up to 10 seconds
if
int64
(
block
.
Time
)
>
time
.
Now
()
.
Unix
()
+
4
{
if
int64
(
block
.
Time
)
>
time
.
Now
()
.
Unix
()
{
return
BlockFutureErr
}
...
...
@@ -394,13 +376,25 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty
return
nil
}
// GetBlockReceipts returns the receipts beloniging to the block hash
func
(
sm
*
BlockProcessor
)
GetBlockReceipts
(
bhash
common
.
Hash
)
(
receipts
types
.
Receipts
,
err
error
)
{
return
getBlockReceipts
(
sm
.
extraDb
,
bhash
)
}
// GetLogs returns the logs of the given block. This method is using a two step approach
// where it tries to get it from the (updated) method which gets them from the receipts or
// the depricated way by re-processing the block.
func
(
sm
*
BlockProcessor
)
GetLogs
(
block
*
types
.
Block
)
(
logs
state
.
Logs
,
err
error
)
{
if
!
sm
.
bc
.
HasBlock
(
block
.
Header
()
.
ParentHash
)
{
return
nil
,
ParentError
(
block
.
Header
()
.
ParentHash
)
receipts
,
err
:=
sm
.
GetBlockReceipts
(
block
.
Hash
())
if
err
==
nil
&&
len
(
receipts
)
>
0
{
// coalesce logs
for
_
,
receipt
:=
range
receipts
{
logs
=
append
(
logs
,
receipt
.
Logs
()
...
)
}
return
}
sm
.
lastAttemptedBlock
=
block
// TODO: remove backward compatibility
var
(
parent
=
sm
.
bc
.
GetBlock
(
block
.
Header
()
.
ParentHash
)
state
=
state
.
New
(
parent
.
Root
(),
sm
.
db
)
...
...
@@ -411,6 +405,16 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
return
state
.
Logs
(),
nil
}
func
getBlockReceipts
(
db
common
.
Database
,
bhash
common
.
Hash
)
(
receipts
types
.
Receipts
,
err
error
)
{
var
rdata
[]
byte
rdata
,
err
=
db
.
Get
(
append
(
receiptsPre
,
bhash
[
:
]
...
))
if
err
==
nil
{
err
=
rlp
.
DecodeBytes
(
rdata
,
&
receipts
)
}
return
}
func
putTx
(
db
common
.
Database
,
tx
*
types
.
Transaction
,
block
*
types
.
Block
,
i
uint64
)
{
rlpEnc
,
err
:=
rlp
.
EncodeToBytes
(
tx
)
if
err
!=
nil
{
...
...
@@ -434,3 +438,19 @@ func putTx(db common.Database, tx *types.Transaction, block *types.Block, i uint
}
db
.
Put
(
append
(
tx
.
Hash
()
.
Bytes
(),
0x0001
),
rlpMeta
)
}
func
putReceipts
(
db
common
.
Database
,
hash
common
.
Hash
,
receipts
types
.
Receipts
)
error
{
storageReceipts
:=
make
([]
*
types
.
ReceiptForStorage
,
len
(
receipts
))
for
i
,
receipt
:=
range
receipts
{
storageReceipts
[
i
]
=
(
*
types
.
ReceiptForStorage
)(
receipt
)
}
bytes
,
err
:=
rlp
.
EncodeToBytes
(
storageReceipts
)
if
err
!=
nil
{
return
err
}
db
.
Put
(
append
(
receiptsPre
,
hash
[
:
]
...
),
bytes
)
return
nil
}
core/block_processor_test.go
View file @
f082c1b8
...
...
@@ -5,6 +5,8 @@ import (
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/pow/ezp"
...
...
@@ -35,3 +37,33 @@ func TestNumber(t *testing.T) {
t
.
Errorf
(
"didn't expect block number error"
)
}
}
func
TestPutReceipt
(
t
*
testing
.
T
)
{
db
,
_
:=
ethdb
.
NewMemDatabase
()
var
addr
common
.
Address
addr
[
0
]
=
1
var
hash
common
.
Hash
hash
[
0
]
=
2
receipt
:=
new
(
types
.
Receipt
)
receipt
.
SetLogs
(
state
.
Logs
{
&
state
.
Log
{
Address
:
addr
,
Topics
:
[]
common
.
Hash
{
hash
},
Data
:
[]
byte
(
"hi"
),
Number
:
42
,
TxHash
:
hash
,
TxIndex
:
0
,
BlockHash
:
hash
,
Index
:
0
,
}})
putReceipts
(
db
,
hash
,
types
.
Receipts
{
receipt
})
receipts
,
err
:=
getBlockReceipts
(
db
,
hash
)
if
err
!=
nil
{
t
.
Error
(
"got err:"
,
err
)
}
if
len
(
receipts
)
!=
1
{
t
.
Error
(
"expected to get 1 receipt, got"
,
len
(
receipts
))
}
}
core/blocks.go
View file @
f082c1b8
...
...
@@ -2,7 +2,9 @@ package core
import
"github.com/ethereum/go-ethereum/common"
var
badHashes
=
[]
common
.
Hash
{
common
.
HexToHash
(
"f269c503aed286caaa0d114d6a5320e70abbc2febe37953207e76a2873f2ba79"
),
common
.
HexToHash
(
"38f5bbbffd74804820ffa4bab0cd540e9de229725afb98c1a7e57936f4a714bc"
),
// Set of manually tracked bad hashes (usually hard forks)
var
BadHashes
=
map
[
common
.
Hash
]
bool
{
common
.
HexToHash
(
"f269c503aed286caaa0d114d6a5320e70abbc2febe37953207e76a2873f2ba79"
)
:
true
,
common
.
HexToHash
(
"38f5bbbffd74804820ffa4bab0cd540e9de229725afb98c1a7e57936f4a714bc"
)
:
true
,
common
.
HexToHash
(
"7064455b364775a16afbdecd75370e912c6e2879f202eda85b9beae547fff3ac"
)
:
true
,
}
core/chain_manager.go
View file @
f082c1b8
...
...
@@ -69,6 +69,7 @@ func CalcGasLimit(parent *types.Block) *big.Int {
gl
:=
new
(
big
.
Int
)
.
Sub
(
parent
.
GasLimit
(),
decay
)
gl
=
gl
.
Add
(
gl
,
contrib
)
gl
=
gl
.
Add
(
gl
,
big
.
NewInt
(
1
))
gl
=
common
.
BigMax
(
gl
,
params
.
MinGasLimit
)
if
gl
.
Cmp
(
params
.
GenesisGasLimit
)
<
0
{
...
...
@@ -120,7 +121,7 @@ func NewChainManager(blockDb, stateDb common.Database, pow pow.PoW, mux *event.T
bc
.
setLastState
()
// Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
for
_
,
hash
:=
range
b
adHashes
{
for
hash
,
_
:=
range
B
adHashes
{
if
block
:=
bc
.
GetBlock
(
hash
);
block
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Found bad hash. Reorganising chain to state %x
\n
"
,
block
.
ParentHash
()
.
Bytes
()[
:
4
])
block
=
bc
.
GetBlock
(
block
.
ParentHash
())
...
...
@@ -547,18 +548,21 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
tstart
=
time
.
Now
()
)
// check the nonce in parallel to the block processing
// this speeds catching up significantly
nonceErrCh
:=
make
(
chan
error
)
go
func
()
{
nonceErrCh
<-
verifyNonces
(
self
.
pow
,
chain
)
}()
for
i
,
block
:=
range
chain
{
if
block
==
nil
{
continue
}
if
BadHashes
[
block
.
Hash
()]
{
err
:=
fmt
.
Errorf
(
"Found known bad hash in chain %x"
,
block
.
Hash
())
blockErr
(
block
,
err
)
return
i
,
err
}
// create a nonce channel for parallisation of the nonce check
nonceErrCh
:=
make
(
chan
error
)
go
verifyBlockNonce
(
self
.
pow
,
block
,
nonceErrCh
)
// Setting block.Td regardless of error (known for example) prevents errors down the line
// in the protocol handler
block
.
Td
=
new
(
big
.
Int
)
.
Set
(
CalcTD
(
block
,
self
.
GetBlock
(
block
.
ParentHash
())))
...
...
@@ -567,13 +571,14 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
// all others will fail too (unless a known block is returned).
logs
,
err
:=
self
.
processor
.
Process
(
block
)
if
err
!=
nil
{
// empty the nonce channel
<-
nonceErrCh
if
IsKnownBlockErr
(
err
)
{
stats
.
ignored
++
continue
}
// Do not penelise on future block. We'll need a block queue eventually that will queue
// future block for future use
if
err
==
BlockFutureErr
{
block
.
SetQueued
(
true
)
self
.
futureBlocks
.
Push
(
block
)
...
...
@@ -592,18 +597,23 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
return
i
,
err
}
// Wait and check nonce channel and make sure it checks out fine
// otherwise return the error
if
err
:=
<-
nonceErrCh
;
err
!=
nil
{
return
i
,
err
}
cblock
:=
self
.
currentBlock
// Write block to database. Eventually we'll have to improve on this and throw away blocks that are
// not in the canonical chain.
self
.
write
(
block
)
// Compare the TD of the last known block in the canonical chain to make sure it's greater.
// At this point it's possible that a different chain (fork) becomes the new canonical chain.
if
block
.
Td
.
Cmp
(
self
.
td
)
>
0
{
// chain fork
if
block
.
ParentHash
()
!=
cblock
.
Hash
()
{
// during split we merge two different chains and create the new canonical chain
self
.
merge
(
cblock
,
block
)
err
:=
self
.
merge
(
cblock
,
block
)
if
err
!=
nil
{
return
i
,
err
}
queue
[
i
]
=
ChainSplitEvent
{
block
,
logs
}
queueEvent
.
splitCount
++
...
...
@@ -636,19 +646,16 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
queue
[
i
]
=
ChainSideEvent
{
block
,
logs
}
queueEvent
.
sideCount
++
}
// Write block to database. Eventually we'll have to improve on this and throw away blocks that are
// not in the canonical chain.
self
.
write
(
block
)
// Delete from future blocks
self
.
futureBlocks
.
Delete
(
block
.
Hash
())
stats
.
processed
++
}
// check and wait for the nonce error channel and
// make sure no nonce error was thrown in the process
err
:=
<-
nonceErrCh
if
err
!=
nil
{
return
0
,
err
}
if
(
stats
.
queued
>
0
||
stats
.
processed
>
0
||
stats
.
ignored
>
0
)
&&
bool
(
glog
.
V
(
logger
.
Info
))
{
tend
:=
time
.
Since
(
tstart
)
start
,
end
:=
chain
[
0
],
chain
[
len
(
chain
)
-
1
]
...
...
@@ -662,7 +669,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
// diff takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them
// to be part of the new canonical chain.
func
(
self
*
ChainManager
)
diff
(
oldBlock
,
newBlock
*
types
.
Block
)
types
.
Blocks
{
func
(
self
*
ChainManager
)
diff
(
oldBlock
,
newBlock
*
types
.
Block
)
(
types
.
Blocks
,
error
)
{
var
(
newChain
types
.
Blocks
commonBlock
*
types
.
Block
...
...
@@ -674,10 +681,17 @@ func (self *ChainManager) diff(oldBlock, newBlock *types.Block) types.Blocks {
if
oldBlock
.
NumberU64
()
>
newBlock
.
NumberU64
()
{
// reduce old chain
for
oldBlock
=
oldBlock
;
oldBlock
.
NumberU64
()
!=
newBlock
.
NumberU64
();
oldBlock
=
self
.
GetBlock
(
oldBlock
.
ParentHash
())
{
if
oldBlock
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Invalid old chain"
)
}
}
}
else
{
// reduce new chain and append new chain blocks for inserting later on
for
newBlock
=
newBlock
;
newBlock
.
NumberU64
()
!=
oldBlock
.
NumberU64
();
newBlock
=
self
.
GetBlock
(
newBlock
.
ParentHash
())
{
if
newBlock
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Invalid new chain"
)
}
newChain
=
append
(
newChain
,
newBlock
)
}
}
...
...
@@ -691,6 +705,12 @@ func (self *ChainManager) diff(oldBlock, newBlock *types.Block) types.Blocks {
newChain
=
append
(
newChain
,
newBlock
)
oldBlock
,
newBlock
=
self
.
GetBlock
(
oldBlock
.
ParentHash
()),
self
.
GetBlock
(
newBlock
.
ParentHash
())
if
oldBlock
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Invalid old chain"
)
}
if
newBlock
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Invalid new chain"
)
}
}
if
glog
.
V
(
logger
.
Info
)
{
...
...
@@ -698,17 +718,22 @@ func (self *ChainManager) diff(oldBlock, newBlock *types.Block) types.Blocks {
glog
.
Infof
(
"Fork detected @ %x. Reorganising chain from #%v %x to %x"
,
commonHash
[
:
4
],
numSplit
,
oldStart
.
Hash
()
.
Bytes
()[
:
4
],
newStart
.
Hash
()
.
Bytes
()[
:
4
])
}
return
newChain
return
newChain
,
nil
}
// merge merges two different chain to the new canonical chain
func
(
self
*
ChainManager
)
merge
(
oldBlock
,
newBlock
*
types
.
Block
)
{
newChain
:=
self
.
diff
(
oldBlock
,
newBlock
)
func
(
self
*
ChainManager
)
merge
(
oldBlock
,
newBlock
*
types
.
Block
)
error
{
newChain
,
err
:=
self
.
diff
(
oldBlock
,
newBlock
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"chain reorg failed: %v"
,
err
)
}
// insert blocks. Order does not matter. Last block will be written in ImportChain itself which creates the new head properly
for
_
,
block
:=
range
newChain
{
self
.
insert
(
block
)
}
return
nil
}
func
(
self
*
ChainManager
)
update
()
{
...
...
@@ -801,9 +826,17 @@ func verifyNonces(pow pow.PoW, blocks []*types.Block) error {
func
verifyNonce
(
pow
pow
.
PoW
,
in
<-
chan
*
types
.
Block
,
done
chan
<-
error
)
{
for
block
:=
range
in
{
if
!
pow
.
Verify
(
block
)
{
done
<-
ValidationError
(
"Block
(#%v) nonce is invalid (= %x)"
,
block
.
Number
(),
block
.
Nonce
)
done
<-
ValidationError
(
"Block
(#%v / %x) nonce is invalid (= %x)"
,
block
.
Number
(),
block
.
Hash
(),
block
.
Nonce
)
}
else
{
done
<-
nil
}
}
}
func
verifyBlockNonce
(
pow
pow
.
PoW
,
block
*
types
.
Block
,
done
chan
<-
error
)
{
if
!
pow
.
Verify
(
block
)
{
done
<-
ValidationError
(
"Block (#%v / %x) nonce is invalid (= %x)"
,
block
.
Number
(),
block
.
Hash
(),
block
.
Nonce
)
}
else
{
done
<-
nil
}
}
core/manager.go
View file @
f082c1b8
...
...
@@ -3,9 +3,7 @@ package core
import
(
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
)
// TODO move this to types?
...
...
@@ -14,11 +12,7 @@ type Backend interface {
BlockProcessor
()
*
BlockProcessor
ChainManager
()
*
ChainManager
TxPool
()
*
TxPool
PeerCount
()
int
IsListening
()
bool
Peers
()
[]
*
p2p
.
Peer
BlockDb
()
common
.
Database
StateDb
()
common
.
Database
EventMux
()
*
event
.
TypeMux
Downloader
()
*
downloader
.
Downloader
}
core/state/log.go
View file @
f082c1b8
...
...
@@ -29,15 +29,22 @@ func (self *Log) EncodeRLP(w io.Writer) error {
}
func
(
self
*
Log
)
String
()
string
{
return
fmt
.
Sprintf
(
`log: %x %x %x
`
,
self
.
Address
,
self
.
Topics
,
self
.
Data
)
return
fmt
.
Sprintf
(
`log: %x %x %x
%x %d %x %d`
,
self
.
Address
,
self
.
Topics
,
self
.
Data
,
self
.
TxHash
,
self
.
TxIndex
,
self
.
BlockHash
,
self
.
Index
)
}
type
Logs
[]
*
Log
func
(
self
Logs
)
String
()
(
ret
string
)
{
for
_
,
log
:=
range
self
{
ret
+=
fmt
.
Sprintf
(
"%v"
,
log
)
}
return
"["
+
ret
+
"]"
type
LogForStorage
Log
func
(
self
*
LogForStorage
)
EncodeRLP
(
w
io
.
Writer
)
error
{
return
rlp
.
Encode
(
w
,
[]
interface
{}{
self
.
Address
,
self
.
Topics
,
self
.
Data
,
self
.
Number
,
self
.
TxHash
,
self
.
TxIndex
,
self
.
BlockHash
,
self
.
Index
,
})
}
core/types/receipt.go
View file @
f082c1b8
...
...
@@ -26,10 +26,39 @@ func (self *Receipt) SetLogs(logs state.Logs) {
self
.
logs
=
logs
}
func
(
self
*
Receipt
)
Logs
()
state
.
Logs
{
return
self
.
logs
}
func
(
self
*
Receipt
)
EncodeRLP
(
w
io
.
Writer
)
error
{
return
rlp
.
Encode
(
w
,
[]
interface
{}{
self
.
PostState
,
self
.
CumulativeGasUsed
,
self
.
Bloom
,
self
.
logs
})
}
func
(
self
*
Receipt
)
DecodeRLP
(
s
*
rlp
.
Stream
)
error
{
var
r
struct
{
PostState
[]
byte
CumulativeGasUsed
*
big
.
Int
Bloom
Bloom
Logs
state
.
Logs
}
if
err
:=
s
.
Decode
(
&
r
);
err
!=
nil
{
return
err
}
self
.
PostState
,
self
.
CumulativeGasUsed
,
self
.
Bloom
,
self
.
logs
=
r
.
PostState
,
r
.
CumulativeGasUsed
,
r
.
Bloom
,
r
.
Logs
return
nil
}
type
ReceiptForStorage
Receipt
func
(
self
*
ReceiptForStorage
)
EncodeRLP
(
w
io
.
Writer
)
error
{
storageLogs
:=
make
([]
*
state
.
LogForStorage
,
len
(
self
.
logs
))
for
i
,
log
:=
range
self
.
logs
{
storageLogs
[
i
]
=
(
*
state
.
LogForStorage
)(
log
)
}
return
rlp
.
Encode
(
w
,
[]
interface
{}{
self
.
PostState
,
self
.
CumulativeGasUsed
,
self
.
Bloom
,
storageLogs
})
}
func
(
self
*
Receipt
)
RlpEncode
()
[]
byte
{
bytes
,
err
:=
rlp
.
EncodeToBytes
(
self
)
if
err
!=
nil
{
...
...
eth/downloader/downloader.go
View file @
f082c1b8
...
...
@@ -7,7 +7,10 @@ import (
"sync/atomic"
"time"
"gopkg.in/fatih/set.v0"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
...
...
@@ -75,6 +78,7 @@ type Downloader struct {
queue
*
queue
// Scheduler for selecting the hashes to download
peers
*
peerSet
// Set of active peers from which download can proceed
checks
map
[
common
.
Hash
]
*
crossCheck
// Pending cross checks to verify a hash chain
banned
*
set
.
SetNonTS
// Set of hashes we've received and banned
// Callbacks
hasBlock
hashCheckFn
...
...
@@ -100,6 +104,7 @@ type Block struct {
}
func
New
(
mux
*
event
.
TypeMux
,
hasBlock
hashCheckFn
,
getBlock
getBlockFn
)
*
Downloader
{
// Create the base downloader
downloader
:=
&
Downloader
{
mux
:
mux
,
queue
:
newQueue
(),
...
...
@@ -110,6 +115,11 @@ func New(mux *event.TypeMux, hasBlock hashCheckFn, getBlock getBlockFn) *Downloa
hashCh
:
make
(
chan
hashPack
,
1
),
blockCh
:
make
(
chan
blockPack
,
1
),
}
// Inject all the known bad hashes
downloader
.
banned
=
set
.
NewNonTS
()
for
hash
,
_
:=
range
core
.
BadHashes
{
downloader
.
banned
.
Add
(
hash
)
}
return
downloader
}
...
...
@@ -280,6 +290,12 @@ func (d *Downloader) fetchHashes(p *peer, h common.Hash) error {
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Peer (%s) responded with empty hash set
\n
"
,
active
.
id
)
return
errEmptyHashSet
}
for
_
,
hash
:=
range
hashPack
.
hashes
{
if
d
.
banned
.
Has
(
hash
)
{
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Peer (%s) sent a known invalid chain
\n
"
,
active
.
id
)
return
ErrInvalidChain
}
}
// Determine if we're done fetching hashes (queue up all pending), and continue if not done
done
,
index
:=
false
,
0
for
index
,
head
=
range
hashPack
.
hashes
{
...
...
eth/handler.go
View file @
f082c1b8
...
...
@@ -2,7 +2,6 @@ package eth
import
(
"fmt"
"math"
"math/big"
"sync"
"time"
...
...
@@ -93,14 +92,22 @@ func NewProtocolManager(protocolVersion, networkId int, mux *event.TypeMux, txpo
}
func
(
pm
*
ProtocolManager
)
removePeer
(
id
string
)
{
// Unregister the peer from the downloader
pm
.
downloader
.
UnregisterPeer
(
id
)
// Short circuit if the peer was already removed
peer
:=
pm
.
peers
.
Peer
(
id
)
if
peer
==
nil
{
return
}
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"Removing peer"
,
id
)
//
Remove the peer from the Ethereum peer set too
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
"Removing peer"
,
id
)
//
Unregister the peer from the downloader and Ethereum peer set
pm
.
downloader
.
UnregisterPeer
(
id
)
if
err
:=
pm
.
peers
.
Unregister
(
id
);
err
!=
nil
{
glog
.
V
(
logger
.
Error
)
.
Infoln
(
"Removal failed:"
,
err
)
}
// Hard disconnect at the networking layer
if
peer
!=
nil
{
peer
.
Peer
.
Disconnect
(
p2p
.
DiscUselessPeer
)
}
}
func
(
pm
*
ProtocolManager
)
Start
()
{
...
...
@@ -351,7 +358,7 @@ func (pm *ProtocolManager) verifyTd(peer *peer, request newBlockMsgData) error {
func
(
pm
*
ProtocolManager
)
BroadcastBlock
(
hash
common
.
Hash
,
block
*
types
.
Block
)
{
// Broadcast block to a batch of peers not knowing about it
peers
:=
pm
.
peers
.
PeersWithoutBlock
(
hash
)
peers
=
peers
[
:
int
(
math
.
Sqrt
(
float64
(
len
(
peers
))))]
//
peers = peers[:int(math.Sqrt(float64(len(peers))))]
for
_
,
peer
:=
range
peers
{
peer
.
sendNewBlock
(
block
)
}
...
...
eth/sync.go
View file @
f082c1b8
...
...
@@ -70,6 +70,7 @@ func (pm *ProtocolManager) processBlocks() error {
// Try to inset the blocks, drop the originating peer if there's an error
index
,
err
:=
pm
.
chainman
.
InsertChain
(
raw
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"Downloaded block import failed:"
,
err
)
pm
.
removePeer
(
blocks
[
index
]
.
OriginPeer
)
pm
.
downloader
.
Cancel
()
return
err
...
...
@@ -84,12 +85,10 @@ func (pm *ProtocolManager) processBlocks() error {
func
(
pm
*
ProtocolManager
)
synchronise
(
peer
*
peer
)
{
// Short circuit if no peers are available
if
peer
==
nil
{
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"Synchronisation canceled: no peers available"
)
return
}
// Make sure the peer's TD is higher than our own. If not drop.
if
peer
.
td
.
Cmp
(
pm
.
chainman
.
Td
())
<=
0
{
glog
.
V
(
logger
.
Debug
)
.
Infoln
(
"Synchronisation canceled: peer's total difficulty is too small"
)
return
}
// FIXME if we have the hash in our chain and the TD of the peer is
...
...
ethdb/database.go
View file @
f082c1b8
package
ethdb
import
(
"sync"
"github.com/ethereum/go-ethereum/compression/rle"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
...
...
@@ -15,14 +13,10 @@ import (
var
OpenFileLimit
=
64
type
LDBDatabase
struct
{
// filename for reporting
fn
string
mu
sync
.
Mutex
// LevelDB instance
db
*
leveldb
.
DB
queue
map
[
string
][]
byte
quit
chan
struct
{}
}
// NewLDBDatabase returns a LevelDB wrapped object. LDBDatabase does not persist data by
...
...
@@ -40,85 +34,39 @@ func NewLDBDatabase(file string) (*LDBDatabase, error) {
return
nil
,
err
}
database
:=
&
LDBDatabase
{
fn
:
file
,
db
:
db
,
quit
:
make
(
chan
struct
{}),
fn
:
file
,
db
:
db
,
}
database
.
makeQueue
()
return
database
,
nil
}
func
(
self
*
LDBDatabase
)
makeQueue
()
{
self
.
queue
=
make
(
map
[
string
][]
byte
)
}
// Put puts the given key / value to the queue
func
(
self
*
LDBDatabase
)
Put
(
key
[]
byte
,
value
[]
byte
)
{
self
.
mu
.
Lock
()
defer
self
.
mu
.
Unlock
()
self
.
queue
[
string
(
key
)]
=
value
self
.
db
.
Put
(
key
,
rle
.
Compress
(
value
),
nil
)
}
// Get returns the given key if it's present.
func
(
self
*
LDBDatabase
)
Get
(
key
[]
byte
)
([]
byte
,
error
)
{
self
.
mu
.
Lock
()
defer
self
.
mu
.
Unlock
()
// Check queue first
if
dat
,
ok
:=
self
.
queue
[
string
(
key
)];
ok
{
return
dat
,
nil
}
dat
,
err
:=
self
.
db
.
Get
(
key
,
nil
)
if
err
!=
nil
{
return
nil
,
err
}
return
rle
.
Decompress
(
dat
)
}
// Delete deletes the key from the queue and database
func
(
self
*
LDBDatabase
)
Delete
(
key
[]
byte
)
error
{
self
.
mu
.
Lock
()
defer
self
.
mu
.
Unlock
()
// make sure it's not in the queue
delete
(
self
.
queue
,
string
(
key
))
return
self
.
db
.
Delete
(
key
,
nil
)
}
func
(
self
*
LDBDatabase
)
LastKnownTD
()
[]
byte
{
data
,
_
:=
self
.
Get
([]
byte
(
"LTD"
))
if
len
(
data
)
==
0
{
data
=
[]
byte
{
0x0
}
}
return
data
}
func
(
self
*
LDBDatabase
)
NewIterator
()
iterator
.
Iterator
{
return
self
.
db
.
NewIterator
(
nil
,
nil
)
}
// Flush flushes out the queue to leveldb
func
(
self
*
LDBDatabase
)
Flush
()
error
{
self
.
mu
.
Lock
()
defer
self
.
mu
.
Unlock
()
batch
:=
new
(
leveldb
.
Batch
)
for
key
,
value
:=
range
self
.
queue
{
batch
.
Put
([]
byte
(
key
),
rle
.
Compress
(
value
))
}
self
.
makeQueue
()
// reset the queue
glog
.
V
(
logger
.
Detail
)
.
Infoln
(
"Flush database: "
,
self
.
fn
)
return
self
.
db
.
Write
(
batch
,
nil
)
return
nil
}
func
(
self
*
LDBDatabase
)
Close
()
{
...
...
jsre/ethereum_js.go
View file @
f082c1b8
This diff is collapsed.
Click to expand it.
miner/worker.go
View file @
f082c1b8
...
...
@@ -38,6 +38,13 @@ type Agent interface {
GetHashRate
()
int64
}
const
miningLogAtDepth
=
5
type
uint64RingBuffer
struct
{
ints
[]
uint64
//array of all integers in buffer
next
int
//where is the next insertion? assert 0 <= next < len(ints)
}
// environment is the workers current environment and holds
// all of the current state information
type
environment
struct
{
...
...
@@ -54,6 +61,7 @@ type environment struct {
lowGasTransactors
*
set
.
Set
ownedAccounts
*
set
.
Set
lowGasTxs
types
.
Transactions
localMinedBlocks
*
uint64RingBuffer
// the most recent block numbers that were mined locally (used to check block inclusion)
}
// env returns a new environment for the current cycle
...
...
@@ -209,6 +217,18 @@ out:
events
.
Unsubscribe
()
}
func
newLocalMinedBlock
(
blockNumber
uint64
,
prevMinedBlocks
*
uint64RingBuffer
)
(
minedBlocks
*
uint64RingBuffer
)
{
if
prevMinedBlocks
==
nil
{
minedBlocks
=
&
uint64RingBuffer
{
next
:
0
,
ints
:
make
([]
uint64
,
miningLogAtDepth
+
1
)}
}
else
{
minedBlocks
=
prevMinedBlocks
}
minedBlocks
.
ints
[
minedBlocks
.
next
]
=
blockNumber
minedBlocks
.
next
=
(
minedBlocks
.
next
+
1
)
%
len
(
minedBlocks
.
ints
)
return
minedBlocks
}
func
(
self
*
worker
)
wait
()
{
for
{
for
block
:=
range
self
.
recv
{
...
...
@@ -224,13 +244,16 @@ func (self *worker) wait() {
}
self
.
mux
.
Post
(
core
.
NewMinedBlockEvent
{
block
})
var
stale
string
var
stale
,
confirm
string
canonBlock
:=
self
.
chain
.
GetBlockByNumber
(
block
.
NumberU64
())
if
canonBlock
!=
nil
&&
canonBlock
.
Hash
()
!=
block
.
Hash
()
{
stale
=
"stale-"
stale
=
"stale "
}
else
{
confirm
=
"Wait 5 blocks for confirmation"
self
.
current
.
localMinedBlocks
=
newLocalMinedBlock
(
block
.
Number
()
.
Uint64
(),
self
.
current
.
localMinedBlocks
)
}
glog
.
V
(
logger
.
Info
)
.
Infof
(
"🔨 Mined %sblock
#%v (%x)"
,
stale
,
block
.
Number
(),
block
.
Hash
()
.
Bytes
()[
:
4
]
)
glog
.
V
(
logger
.
Info
)
.
Infof
(
"🔨 Mined %sblock
(#%v / %x). %s"
,
stale
,
block
.
Number
(),
block
.
Hash
()
.
Bytes
()[
:
4
],
confirm
)
jsonlogger
.
LogJson
(
&
logger
.
EthMinerNewBlock
{
BlockHash
:
block
.
Hash
()
.
Hex
(),
...
...
@@ -265,8 +288,14 @@ func (self *worker) push() {
func
(
self
*
worker
)
makeCurrent
()
{
block
:=
self
.
chain
.
NewBlock
(
self
.
coinbase
)
if
block
.
Time
()
==
self
.
chain
.
CurrentBlock
()
.
Time
()
{
block
.
Header
()
.
Time
++
parent
:=
self
.
chain
.
GetBlock
(
block
.
ParentHash
())
// TMP fix for build server ...
if
parent
==
nil
{
return
}
if
block
.
Time
()
<=
parent
.
Time
()
{
block
.
Header
()
.
Time
=
parent
.
Header
()
.
Time
+
1
}
block
.
Header
()
.
Extra
=
self
.
extra
...
...
@@ -286,8 +315,10 @@ func (self *worker) makeCurrent() {
current
.
ignoredTransactors
=
set
.
New
()
current
.
lowGasTransactors
=
set
.
New
()
current
.
ownedAccounts
=
accountAddressesSet
(
accounts
)
if
self
.
current
!=
nil
{
current
.
localMinedBlocks
=
self
.
current
.
localMinedBlocks
}
parent
:=
self
.
chain
.
GetBlock
(
current
.
block
.
ParentHash
())
current
.
coinbase
.
SetGasPool
(
core
.
CalcGasLimit
(
parent
))
self
.
current
=
current
...
...
@@ -304,6 +335,38 @@ func (w *worker) setGasPrice(p *big.Int) {
w
.
mux
.
Post
(
core
.
GasPriceChanged
{
w
.
gasPrice
})
}
func
(
self
*
worker
)
isBlockLocallyMined
(
deepBlockNum
uint64
)
bool
{
//Did this instance mine a block at {deepBlockNum} ?
var
isLocal
=
false
for
idx
,
blockNum
:=
range
self
.
current
.
localMinedBlocks
.
ints
{
if
deepBlockNum
==
blockNum
{
isLocal
=
true
self
.
current
.
localMinedBlocks
.
ints
[
idx
]
=
0
//prevent showing duplicate logs
break
}
}
//Short-circuit on false, because the previous and following tests must both be true
if
!
isLocal
{
return
false
}
//Does the block at {deepBlockNum} send earnings to my coinbase?
var
block
=
self
.
chain
.
GetBlockByNumber
(
deepBlockNum
)
return
block
.
Header
()
.
Coinbase
==
self
.
coinbase
}
func
(
self
*
worker
)
logLocalMinedBlocks
(
previous
*
environment
)
{
if
previous
!=
nil
&&
self
.
current
.
localMinedBlocks
!=
nil
{
nextBlockNum
:=
self
.
current
.
block
.
Number
()
.
Uint64
()
for
checkBlockNum
:=
previous
.
block
.
Number
()
.
Uint64
();
checkBlockNum
<
nextBlockNum
;
checkBlockNum
++
{
inspectBlockNum
:=
checkBlockNum
-
miningLogAtDepth
if
self
.
isBlockLocallyMined
(
inspectBlockNum
)
{
glog
.
V
(
logger
.
Info
)
.
Infof
(
"🔨 🔗 Mined %d blocks back: block #%v"
,
miningLogAtDepth
,
inspectBlockNum
)
}
}
}
}
func
(
self
*
worker
)
commitNewWork
()
{
self
.
mu
.
Lock
()
defer
self
.
mu
.
Unlock
()
...
...
@@ -312,6 +375,7 @@ func (self *worker) commitNewWork() {
self
.
currentMu
.
Lock
()
defer
self
.
currentMu
.
Unlock
()
previous
:=
self
.
current
self
.
makeCurrent
()
current
:=
self
.
current
...
...
@@ -347,6 +411,7 @@ func (self *worker) commitNewWork() {
// We only care about logging if we're actually mining
if
atomic
.
LoadInt32
(
&
self
.
mining
)
==
1
{
glog
.
V
(
logger
.
Info
)
.
Infof
(
"commit new work on block %v with %d txs & %d uncles
\n
"
,
current
.
block
.
Number
(),
current
.
tcount
,
len
(
uncles
))
self
.
logLocalMinedBlocks
(
previous
)
}
for
_
,
hash
:=
range
badUncles
{
...
...
p2p/nat/nat_test.go
View file @
f082c1b8
...
...
@@ -30,7 +30,7 @@ func TestAutoDiscRace(t *testing.T) {
}
// Check that they all return the correct result within the deadline.
deadline
:=
time
.
After
(
550
*
time
.
Millis
econd
)
deadline
:=
time
.
After
(
2
*
time
.
S
econd
)
for
i
:=
0
;
i
<
cap
(
results
);
i
++
{
select
{
case
<-
deadline
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment