Compare commits

...

180 Commits

Author SHA1 Message Date
Felix Lange
da2a22c384 params: stable 1.5.7 2017-01-16 10:57:02 +01:00
Felföldi Zsolt
0fa9a8929c les: fixed transaction sending deadlock (#3568) 2017-01-16 10:51:29 +01:00
Péter Szilágyi
2a1a531ba3 Merge pull request #3570 from fjl/hexutil-zero-fix
common/hexutil: fix EncodeBig, Big.MarshalJSON
2017-01-16 11:49:17 +02:00
Felix Lange
51f6b6d33f common/hexutil: fix EncodeBig, Big.MarshalJSON
The code was too clever and failed to include zeros on a big.Word
boundary.
2017-01-16 10:32:40 +01:00
Péter Szilágyi
b5a100b859 Merge pull request #3560 from karalabe/ci-misspell
travis, appveyor, build: add source spell checking
2017-01-13 12:16:22 +02:00
Péter Szilágyi
54fcab20e3 appveyor, build: fix review requests 2017-01-13 12:04:55 +02:00
Péter Szilágyi
a2bc90d1d7 build: spellcheck individual packages (Windows path limits) 2017-01-13 11:22:24 +02:00
Péter Szilágyi
c01f8c3d3c accounts/abi: fix comment spelling error 2017-01-13 11:14:47 +02:00
Péter Szilágyi
e4181a7f1b travis, appveyor, build: add source spell checking 2017-01-13 11:14:13 +02:00
Felix Lange
01f6f2d741 common/hexutil: allow empty strings when decoding JSON (#3559) 2017-01-13 09:45:40 +01:00
Felix Lange
c5df37c111 eth: accept leading zeros for nonce parameter of submitWork (#3558) 2017-01-13 00:37:23 +01:00
Felix Lange
e0ceeab0d1 crypto/secp256k1: update to github.com/bitcoin-core/secp256k1 @ 9d560f9 (#3544)
- Use defined constants instead of hard-coding their integer value.
- Allocate secp256k1 structs on the C stack instead of converting []byte
- Remove dead code
2017-01-12 21:29:11 +01:00
Péter Szilágyi
93077c98e4 internal: update web3.js to 0.18.1, embed deps with go-bindata (#3545) 2017-01-12 21:28:35 +01:00
Péter Szilágyi
3dab303826 Merge pull request #3555 from obscuren/unskip-test
tests: unskip test
2017-01-12 12:08:56 +02:00
Jeffrey Wilcke
3160fd24ba tests: unskip test 2017-01-12 10:32:21 +01:00
Péter Szilágyi
ce7822c130 Merge pull request #3553 from bas-vk/rm-olympic-support
core: remove support for Olympic network
2017-01-12 11:26:00 +02:00
Bas van Kervel
745a3adebd core: remove support for Olympic network 2017-01-12 09:50:54 +01:00
Péter Szilágyi
218ec6c085 Merge pull request #3551 from fjl/core-import-log-align
core: improve import log alignment
2017-01-11 14:53:54 +02:00
Nick Johnson
d30d7800e0 ethdb: Implement interface for prefixed operations to the DB (#3536) 2017-01-11 13:26:09 +01:00
Felix Lange
8820d97039 internal/ethapi: fix duration parameter of personal_unlockAccount (#3542) 2017-01-11 13:20:24 +01:00
Péter Szilágyi
b52fde7cf7 Merge pull request #3546 from fjl/deps-update
vendor: update dependencies
2017-01-11 12:14:08 +02:00
Péter Szilágyi
2b4d0b6ff9 Merge pull request #3548 from fjl/geth-fix-bootnodes
cmd/utils: fix comma-separated --bootnodes
2017-01-11 10:59:14 +02:00
Felix Lange
21f1370d2a core: improve import log alignment 2017-01-10 23:14:08 +01:00
Felix Lange
d78f9b834a vendor: update all dependencies except Azure SDK
The Azure SDK doesn't support Go 1.5 anymore. We can't upgrade it until
Go 1.8 comes out.
2017-01-10 22:33:24 +01:00
Felix Lange
445deb7470 cmd/utils: fix comma-separated --bootnodes 2017-01-10 21:13:43 +01:00
Péter Szilágyi
02b67558e8 Merge pull request #3535 from fjl/all-ineffassign
all: fix ineffectual assignments
2017-01-09 23:53:17 +02:00
Péter Szilágyi
91c8f87fb1 Merge pull request #3538 from karalabe/cycle-1.5.7
params, VERSION: start 1.5.7 release cycle
2017-01-09 17:47:35 +02:00
Péter Szilágyi
d056b7fa52 params, VERSION: start 1.5.7 release cycle 2017-01-09 17:45:49 +02:00
Péter Szilágyi
2a609af518 Merge pull request #3537 from karalabe/release-1.5.6
params: stable version 1.5.6
2017-01-09 17:39:27 +02:00
Péter Szilágyi
1d5d6616ae params: stable version 1.5.6 2017-01-09 17:30:35 +02:00
Felix Lange
b9b3efb09f all: fix ineffectual assignments and remove uses of crypto.Sha3
go get github.com/gordonklaus/ineffassign
ineffassign .
2017-01-09 16:24:42 +01:00
Felix Lange
0f34d506b5 generators: delete dead code
We don't use this anymore.
2017-01-09 16:12:54 +01:00
Felix Lange
5eccc122e8 build, node: fix go vet nits 2017-01-09 16:12:54 +01:00
Péter Szilágyi
681b51aac4 Merge pull request #3519 from zsfelfoldi/light-topic5
les: fixed selectPeer deadlock, improved request distribution
2017-01-09 16:58:23 +02:00
Péter Szilágyi
4268cb8efe Merge pull request #3534 from bas-vk/writemipmaprace
core: fix race condition in WriteMipmapBloom
2017-01-09 16:58:05 +02:00
Viktor Trón
3f1a72908c cmd/swarm: uploader uses HTTP PUT for directories (#3488) 2017-01-09 15:19:56 +01:00
Bas van Kervel
2fed476ce1 core: fix race condition in WriteMipmapBloom 2017-01-09 15:35:58 +02:00
Péter Szilágyi
6cb39dd3da Merge pull request #3529 from fjl/console-error-fix
console: fix error message in faux JSON-RPC responses
2017-01-09 13:46:15 +02:00
Péter Szilágyi
88cc1ca55a Merge pull request #3533 from karalabe/modum-io-develop-2
accounts/abi: support custom int slice types
2017-01-09 11:49:17 +02:00
Thomas Bocek
1bd9769111 accounts/abi: fixed broken types slice testcases
Check for slice in type as well and adapted test case as arrays
also store its types.
2017-01-09 11:36:33 +02:00
Jeffrey Wilcke
47372813ef accounts/abi: fixed comments 2017-01-09 11:36:33 +02:00
tbocek
fc213c873d accounts/abi: added testcase to unpack []uint32 2017-01-09 11:36:32 +02:00
Thomas Bocek
972f0bd3db accounts/abi: support custom int slice types
On solidity contract I have "uint32 []" type, when abigen creates Go
bindings - they are also "[]uint32" type on Go side. Even though it
looks like it should work - the actual type of the data coming from
the chain is of type " []*big.Int".

When executing contract function from Go side - getting unmarshal error:
abi: cannot unmarshal []*big.Int in to []uint32

The fix is to create array with the correct type

This fixed the issue reported in: https://github.com/ethereum/go-ethereum/issues/2802
2017-01-09 11:36:31 +02:00
Victor Farazdagi
808310a569 node: fix pointer dereference issue in StartRPC (#3532) 2017-01-08 15:55:37 +01:00
Valentin Wüstholz
0a5450fe04 cmd/disasm: fix array-out-of-bounds error (#3491) 2017-01-08 01:18:22 +01:00
Felix Lange
9bab0b8a24 console: fix error message in faux JSON-RPC responses
The message was used as both key and value in the error object.
This only affected unusual errors with no error code.
2017-01-08 00:55:48 +01:00
Péter Szilágyi
17182732f5 Merge pull request #3526 from karalabe/misspell
all: fix spelling errors
2017-01-06 20:03:44 +02:00
Péter Szilágyi
18c77744ff all: fix spelling errors 2017-01-06 19:44:35 +02:00
Péter Szilágyi
ac93a6ff6c Merge pull request #3525 from fjl/all-gosimple-cleanup
all: clean up lint issues, remove more dead code
2017-01-06 19:30:44 +02:00
Felix Lange
13e3b2f433 logger, pow/dagger, pow/ezp: delete dead code 2017-01-06 18:18:07 +01:00
Felix Lange
f2da6581ba all: fix issues reported by honnef.co/go/simple/cmd/gosimple 2017-01-06 18:18:07 +01:00
Péter Szilágyi
444fc892b0 Merge pull request #3524 from karalabe/mobile-signwith-swift-fixup
mobile: rename passphrase signing method to avoid Swift rewrite
2017-01-06 18:04:19 +02:00
Péter Szilágyi
b56aee3697 mobile: rename passphrase signing method to avoid Swift rewrite 2017-01-06 17:47:15 +02:00
Felix Lange
35a7dcb162 all: gofmt -w -s 2017-01-06 15:52:03 +01:00
Felix Lange
e0fde02290 common/compiler: remove workaround for solc 0.3.5 stdin bug (#3522)
The crash when compiling stdin was fixed in solc 0.3.6 (released
2016-08-10). While here, simplify the test so it runs with any solc
version.

Fixes #3484. The byte code was different for each run because recent
solc embeds the swarm hash of contract metadata into the code. When
compiling from stdin the name in the metadata is constant.
2017-01-06 15:39:35 +01:00
Péter Szilágyi
59b8245bbc Merge pull request #3516 from fjl/types-drop-sign-ecdsa
core/types: remove redundant SignECDSA wrappers, rename to SignTx
2017-01-06 15:55:55 +02:00
Péter Szilágyi
8f9daaa3ba Merge pull request #3518 from fjl/ethclient-dependency-cleanup
core/types: dependency cleanup
2017-01-06 15:42:03 +02:00
Felix Lange
d3b751e4d9 trie: remove dependency on ethdb
This removes the core/types -> leveldb dependency.
2017-01-06 14:15:22 +01:00
Felix Lange
7731061903 core/vm: move Log to core/types
This significantly reduces the dependency closure of ethclient, which no
longer depends on core/vm as of this change.

All uses of vm.Logs are replaced by []*types.Log. NewLog is gone too,
the constructor simply returned a literal.
2017-01-06 14:15:22 +01:00
Felix Lange
b9683d3748 params: avoid importing p2p/discover for bootnodes
params is imported by leaf-ish library packages and should not pull in
the p2p stack.
2017-01-06 14:15:21 +01:00
Zsolt Felfoldi
66979aa468 light: fixed data race in TestTxPool 2017-01-06 04:34:35 +01:00
Zsolt Felfoldi
93f9c023cc les: fixed selectPeer deadlock, improved request distribution
les/flowcontrol: using proper types for relative and absolute times
2017-01-06 04:34:31 +01:00
Péter Szilágyi
e0ee0cc66a Merge pull request #3517 from karalabe/empty-ios-prefix
build: finally settle on empty iOS ObjC package prefixes
2017-01-05 15:29:36 +02:00
Péter Szilágyi
9b135a9c20 build: finally settle on empty iOS ObjC package prefixes 2017-01-05 14:32:30 +02:00
Felix Lange
e171bf74f8 core/types: remove redundant SignECDSA wrappers, rename to SignTx 2017-01-05 12:59:17 +01:00
Péter Szilágyi
bb2e99dfc2 Merge pull request #3417 from karalabe/mobile-polishes
Account management API polishes
2017-01-05 13:57:12 +02:00
Péter Szilágyi
b37d175e59 accounts, internal, mobile: polish accounts API, extend Android tests 2017-01-05 12:58:03 +02:00
Maran
f087633efd swarm/api/http: add support for CORS headers (#3388) 2017-01-05 11:57:41 +01:00
Péter Szilágyi
bbce726c8a Merge pull request #3515 from bas-vk/exportropsten
core,cmd/utils: bugfix for ropsten dump imports
2017-01-05 12:54:45 +02:00
Jeffrey Wilcke
bbc4ea4ae8 core/vm: improved EVM run loop & instruction calling (#3378)
The run loop, which previously contained custom opcode executes have been
removed and has been simplified to a few checks.

Each operation consists of 4 elements: execution function, gas cost function,
stack validation function and memory size function. The execution function
implements the operation's runtime behaviour, the gas cost function implements
the operation gas costs function and greatly depends on the memory and stack,
the stack validation function validates the stack and makes sure that enough
items can be popped off and pushed on and the memory size function calculates
the memory required for the operation and returns it.

This commit also allows the EVM to go unmetered. This is helpful for offline
operations such as contract calls.
2017-01-05 11:52:10 +01:00
RJ
2126d81488 accounts/abi: add support for function types (#3405) 2017-01-05 11:46:44 +01:00
Péter Szilágyi
06b381d1c9 cmd/utils: disallow --fakepow for live operation (#3512) 2017-01-05 11:40:56 +01:00
Péter Szilágyi
08eea0f0e4 accounts, core, crypto, internal: use normalised V during signature handling (#3455)
To address increasing complexity in code that handles signatures, this PR
discards all notion of "different" signature types at the library level. Both
the crypto and accounts package is reduced to only be able to produce plain
canonical secp256k1 signatures. This makes the crpyto APIs much cleaner,
simpler and harder to abuse.
2017-01-05 11:35:23 +01:00
Bas van Kervel
a1798a8188 core,cmd/utils: bugfix for ropsten dump imports 2017-01-05 11:31:57 +01:00
Péter Szilágyi
0fac8cba47 Merge pull request #3511 from karalabe/live-fakepow
cmd/utils, eth, les: bubble --fakepow flag into eth/les too
2017-01-04 13:27:51 +02:00
Péter Szilágyi
1ca74aba6f Merge pull request #3505 from bas-vk/txinblock
ethclient: hex encode request args for TransactionInBlock
2017-01-04 12:43:27 +02:00
Péter Szilágyi
2ce30382d9 cmd/utils, eth, les: bubble --fakepow flag into eth/les too 2017-01-04 10:42:41 +02:00
Bas van Kervel
8bc545be2a ethclient: hex encode request args for TransactionInBlock 2017-01-03 14:46:00 +01:00
Péter Szilágyi
891fcd8ce1 Merge pull request #3486 from bas-vk/txbyhash
ethclient: pass ptr when parsing eth_getTransactionByHash result
2017-01-03 10:56:22 +02:00
Guillaume NICOLAS
bd06091874 mobile: add SetVerbosity (#3492) 2017-01-02 18:12:31 +01:00
Péter Szilágyi
3e3edcc465 Merge pull request #3490 from karalabe/fix-miner-api
eth: fix miner start API to accept int, not hexint
2016-12-23 14:59:26 +02:00
Péter Szilágyi
89a32267f7 eth: fix miner start API to accept int, not hexint 2016-12-23 11:28:11 +02:00
Bas van Kervel
021177ca9b ethclient: pass ptr when parsing eth_getTransactionByHash result 2016-12-22 14:45:01 +01:00
Péter Szilágyi
115364b0a9 Merge pull request #3475 from fjl/rpc-hex-improvements
rpc: remove HexBytes, HexNumber
2016-12-22 13:49:16 +02:00
bas-vk
6d15d00ac4 accounts/abi: add support for "anonymous" and "indexed" for events (#3464) 2016-12-22 01:51:20 +01:00
Valentin Wüstholz
bdaa43510b cmd/disasm: fix off-by-one error and improve error handling (#3482) 2016-12-22 00:37:27 +01:00
Aron Fischer
9a51f5c350 swarm/http: check error returned by reader.Size (#3470) 2016-12-22 00:35:05 +01:00
Aron Fischer
301c0a6303 swarm/storage: call size before seek-from-end (#3469) 2016-12-22 00:34:05 +01:00
Aron Fischer
65f486ff02 swarm/api: check for zero length manifest error (#3468) 2016-12-22 00:32:08 +01:00
Péter Szilágyi
df096a7771 Merge pull request #3479 from karalabe/android-ropsten-dao
mobile: fix ropsten chain configs
2016-12-21 13:25:00 +02:00
Péter Szilágyi
0e9a9f243f mobile: fix ropsten chain configs 2016-12-21 13:10:57 +02:00
Felix Lange
12c964b2b7 internal/ethapi: fix hex handling for eth_call input and eth_sendRawTransaction 2016-12-20 14:46:22 +01:00
Felix Lange
cf71f5cd60 rpc: remove HexNumber, replace all uses with hexutil types
This change couldn't be automated because HexNumber was used for numbers
of all sizes.
2016-12-20 14:41:58 +01:00
Felix Lange
adab2e16bd rpc: remove HexBytes, replace all uses with hexutil.Bytes 2016-12-20 14:35:26 +01:00
Felix Lange
a3e3235d97 rpc: improve error messages for invalid arguments
The message now includes the index of the invalid arg.
2016-12-20 14:35:26 +01:00
Felix Lange
2be3c4b0e3 internal/jsre: fix built-in inspect function
inspect was broken by ffaf58f0a9 (May 2016!).
Looks like nobody uses this function.
2016-12-20 14:35:14 +01:00
Péter Szilágyi
0ee796632a eth, miner: verify PoW in the remote agent to notify submitter (#3438) 2016-12-20 02:14:36 +01:00
Nick Johnson
1fe67c125d eth/filters: add FindOnce for iterator-like operation (#3435)
This commit introduces a FindOnce method for filters. FindOnce finds the next block that
matches the filter and returns all matching logs from that block. If there are no further
matching logs, it returns a nil slice. This method allows callers to iterate over large
sets of logs progressively.

The changes introduce a small inefficiency relating to mipmaps: the first time a filter is
called, it acts as if all mipmaps are matched, and thus iterates several blocks near the
requested start point. This is in the interest of simplicity and avoiding duplicate mipmap
lookups each time FindOnce is called.
2016-12-20 02:00:03 +01:00
gluk256
ba996f5e27 whisper: refactoring (#3411)
* whisper: refactored message processing
* whisper: final polishing
* whisper: logging updated
* whisper: moved the check, changed the default PoW
* whisper: refactoring of message queuing
* whisper: refactored parameters
2016-12-20 00:58:01 +01:00
Péter Szilágyi
64bf5bafe9 Merge pull request #3403 from VoR0220/fixedPointsAbi
accounts/abi: prepare ABI to handle fixed point types
2016-12-19 14:22:57 +02:00
Péter Szilágyi
4d05bbf2a4 accounts/abi: clean up PR and add type parsing tests 2016-12-19 14:11:11 +02:00
VoR0220
471990f771 accounts/abi: prepare ABI to handle fixed point types
Signed-off-by: VoR0220 <rj@erisindustries.com>
2016-12-19 14:11:11 +02:00
Péter Szilágyi
7b623aab9d Merge pull request #3454 from karalabe/allow-zeroprice-tx
core: allow zero priced transactions from inexistent accounts too
2016-12-19 12:23:46 +02:00
Péter Szilágyi
e871ae1270 Merge pull request #3453 from fjl/api-sign-recover-hex
internal/ethapi: fix hex handling for eth_sign, personal_{sign,recover}
2016-12-19 11:49:21 +02:00
Péter Szilágyi
c44830ebf3 core, light: allow zero cost txs from inexistent accounts too 2016-12-16 13:30:39 +02:00
Felix Lange
3e4a04f34d internal/ethapi: fix hex handling for eth_sign, personal_{sign,recover} 2016-12-16 11:32:51 +01:00
Péter Szilágyi
38827dd9ca Merge pull request #3445 from karalabe/govet-ip-signal
p2p/nat: fix a bytes based net.IP comparison
2016-12-15 16:51:14 +02:00
Péter Szilágyi
21fd9f037e p2p/nat: fix a bytes based net.IP comparison 2016-12-15 16:28:31 +02:00
Péter Szilágyi
033763eaf7 Merge pull request #3442 from karalabe/discv5-fix-ip-comparison
p2p/discover, p2p/discv5: use flexible comparison for IPs
2016-12-14 19:15:05 +02:00
Péter Szilágyi
2573094df2 p2p/discover, p2p/discv5: use flexible comparison for IPs 2016-12-14 18:40:49 +02:00
Péter Szilágyi
745026b7b4 Merge pull request #3433 from karalabe/badblock-order-fix
core: import future blocks one-by-one, enfore chain ancestry
2016-12-14 16:45:48 +02:00
Péter Szilágyi
a07d955eaa Merge pull request #3441 from karalabe/begin-1.5.6-cycle
VERSION, params: start Geth 1.5.6 development cycle
2016-12-14 16:28:45 +02:00
Péter Szilágyi
9d6f4e2e7f VERSION, params: start Geth 1.5.6 development cycle 2016-12-14 16:27:35 +02:00
Péter Szilágyi
ff07d54843 Merge pull request #3440 from karalabe/release-1.5.5
params: stable version 1.5.5
2016-12-14 16:06:54 +02:00
Péter Szilágyi
e53879328c params: stable version 1.5.5 2016-12-14 15:57:44 +02:00
Péter Szilágyi
b792412d31 Merge pull request #3430 from karalabe/miner-pending-race
miner: clean up unconfirmed mined block tracking
2016-12-14 15:05:50 +02:00
Péter Szilágyi
49c6f1053c Merge pull request #3421 from ethersphere/s/swarm-cmd
cmd/swarm: one command  with subcommands
2016-12-14 12:26:20 +02:00
Péter Szilágyi
4d960f6dc6 Merge pull request #3439 from karalabe/drop-deprecated-wily
build: Ubuntu wily was officially deprecated, drop support
2016-12-14 12:18:03 +02:00
Péter Szilágyi
8941665896 build: Ubuntu wily was officially deprecated, drop support 2016-12-14 11:45:14 +02:00
Péter Szilágyi
9cc0f60666 Merge pull request #3429 from bas-vk/txpool-crash
core: init pending state in tx pool on creation
2016-12-14 11:17:39 +02:00
Péter Szilágyi
fdb8edf5ea Merge pull request #3427 from Arachnid/gzipdump
cmd/utils, eth: Add gzip support for chain dump and restore
2016-12-14 11:15:21 +02:00
Nick Johnson
9ba9fe818d cmd/utils, eth: Add gzip support for chain dump and restore 2016-12-14 08:59:55 +00:00
zelig
92224d27b1 cmd/swarm: testnet bootnodes IP address change 2016-12-14 08:14:52 +01:00
Péter Szilágyi
157a4bd926 Merge pull request #3437 from karalabe/update-ci-go1.7.4
travis, appveyor: build with Go 1.7.4
2016-12-13 22:30:14 +02:00
Péter Szilágyi
29d6881112 travis, appveyor: build with Go 1.7.4 2016-12-13 19:54:56 +02:00
Péter Szilágyi
e2692921e1 Merge pull request #3434 from karalabe/drop-legacy-android
cmd/geth: drop legacy android code
2016-12-13 18:53:06 +02:00
Péter Szilágyi
b63138c3ec cmd/geth: drop legacy android code 2016-12-13 18:17:49 +02:00
Péter Szilágyi
a59fcc33e6 core: import future blocks one-by-one, enfore chain ancestry 2016-12-13 16:19:45 +02:00
Péter Szilágyi
07311f3157 miner: rename pending to unconformed, add bounds and ops tests 2016-12-13 15:10:52 +02:00
Péter Szilágyi
17637ed1bb miner: clean up unconfirmed mined block tracking 2016-12-13 14:31:32 +02:00
Péter Szilágyi
f15828e901 Merge pull request #3431 from karalabe/miner-race-fixes
Miner race fixes
2016-12-13 14:30:26 +02:00
Péter Szilágyi
dadd689359 miner: fix data race on setting etherbase/extradata 2016-12-13 14:04:05 +02:00
Péter Szilágyi
b750cab56a miner: fix a race between remote agent start/loop 2016-12-13 14:03:57 +02:00
zelig
485748c416 cmd/swarm: improve uploader output and add defaultpath option 2016-12-13 12:54:13 +01:00
zelig
080699f7df cmd/swarm: ethapi not required 2016-12-13 12:54:13 +01:00
zelig
8e35f54931 cmd/swarm: trim trailing slash from bzzapi url 2016-12-13 12:54:13 +01:00
zelig
d44f1a77ee cmd/swarm: add default bootnodes for testnet 3 2016-12-13 12:54:13 +01:00
zelig
4181046488 swarm/network, cmd/swarm: swarm default network id is 3 (to match Ropsten) 2016-12-13 12:54:13 +01:00
zelig
d7c398b638 build: add swarm command to binary packages, update README 2016-12-13 12:54:13 +01:00
zelig
5f5d0aa4ff cmd/swarm: subsume cmd/bzz* as subcommands under swarm
cmd/swarm: subsume cmd/bzz* under cmd/swarm as subcommands
2016-12-13 12:54:05 +01:00
Bas van Kervel
9f1520b4c0 core: init pending state in tx pool on creation 2016-12-13 10:38:04 +01:00
Felix Lange
a98e8c0889 Merge pull request #3413 from zsfelfoldi/light-topic4
les, p2p/discv5: implement server pool, improve peer selection, light fetcher and topic searching
2016-12-12 20:46:15 +01:00
Péter Szilágyi
ee445a2ba4 Merge pull request #3425 from karalabe/netstats-time-fixup
netstats: time and block history
2016-12-12 14:55:00 +02:00
Péter Szilágyi
b2c226cb7d ethstats: implement block history retrievals 2016-12-12 14:01:52 +02:00
Péter Szilágyi
13614f4e1c ethstats: fix timestamps and add custom proto support 2016-12-11 20:16:30 +02:00
bas-vk
4f9ccdd70f build: safe update of PATH on Windows (#3419)
NSIS has a default MAX_STR_LEN of 1024. If $ENV{PATH} is longer
the returned string is truncated to an empty string. Its then not
possible to distinguis between the variable not set or too long.
As a result the variable is set with the location where geth and/or
dev tools are installed. This may override any previous set values.
2016-12-11 00:01:57 +01:00
bas-vk
4e36b1e3da core: bugfix state change race condition in txpool (#3412)
The transaction pool keeps track of the current nonce in its local pendingState. When a
new block comes in the pendingState is reset. During the reset it fetches multiple times
the current state through the use of the currentState callback. When a second block comes
in during the reset its possible that the state changes during the reset. If that block
holds transactions that are currently in the pool the local pendingState that is used to
determine nonces can get out of sync.
2016-12-10 23:54:58 +01:00
Zsolt Felfoldi
f12f8a6c14 les, light: add block availability check for ODR requests 2016-12-10 09:53:25 +01:00
Zsolt Felfoldi
c57c54ce96 eth, les: defer starting LES service until ETH initial sync is finished 2016-12-10 09:53:25 +01:00
Zsolt Felfoldi
c8130df1d9 les: using random request IDs 2016-12-10 09:53:25 +01:00
Zsolt Felfoldi
af8a742d00 les: improved header fetcher and server statistics 2016-12-10 09:53:08 +01:00
Zsolt Felfoldi
e67500aa15 les: fixed light fetcher request ID matching 2016-12-08 13:38:15 +01:00
Zsolt Felfoldi
a6d3bf6fc3 p2p/discv5: search and lookup improvement 2016-12-08 13:38:15 +01:00
Zsolt Felfoldi
3e617f3cd6 les: implement light server pool 2016-12-08 13:38:15 +01:00
Péter Szilágyi
0fe35b907a mobile: iOS naming and API fixes for generators and Swift (#3408)
* build: modify the iOS namespace to iGeth (gomobile limitation)
* mobile: assign names to return types for ObjC wrapper
* mobile: use more expanded names for iOS/Swift API
2016-12-08 13:09:26 +01:00
Jeffrey Wilcke
3fc7c97827 core, core/vm: implemented a generic environment (#3348)
Environment is now a struct (not an interface). This
reduces a lot of tech-debt throughout the codebase where a virtual
machine environment had to be implemented in order to test or run it.

The new environment is suitable to be used en the json tests, core
consensus and light client.
2016-12-06 02:16:03 +01:00
Felix Lange
7f79d249a6 Merge pull request #3402 from fjl/ethclient-api-fixes
eth/filters, ethclient, ethereum: API improvements
2016-12-05 20:08:18 +01:00
Felix Lange
f138374027 ethereum: document use of Removed field for SubscribeFilterLogs 2016-12-05 10:57:11 +01:00
Felix Lange
f52a1ae849 core, core/vm, eth/filters: move Removed field into vm.Log
This field used to be assigned by the filter system and returned through
the RPC API. Now that we have a Go client that uses the underlying type,
the field needs to move. It is now assigned to true when the RemovedLogs
event is generated so the filter system doesn't need to care about the
field at all.

While here, remove the log list from ChainSideEvent. There are no users
of this field right now and any potential users could subscribe to
RemovedLogsEvent instead.
2016-12-05 10:57:11 +01:00
Felix Lange
3bc0fe1ee3 ethclient, ethereum: add NotFound, split transactions out of ChainReader
ethclient now returns ethereum.NotFound if the server returns null and
no error while accessing blockchain data.

The light client cannot provide arbitrary transactions. The change to
split transaction access into its own interface emphasizes that
transactions should not be relied on and recommends use of logs.
2016-12-05 10:57:11 +01:00
Felix Lange
fa0cc27400 ethclient: use package hexutil for number encoding 2016-12-04 19:45:55 +01:00
Felix Lange
4cb29bde2e ethclient: don't crash if server returns null uncle header
It should never return null for a known uncle, but even if it does
we can't just crash.
2016-12-04 19:45:55 +01:00
gluk256
2dcf75a722 whisper/shhapi, whisper/whisperv5: refactoring (#3364)
* Filter refactoring
* API tests added + bugfix
* fixed the error logs
* FilterID fixed
* test cases fixed
* key generation updated
* POW updated
* got rid of redundant stuff
2016-12-01 20:09:22 +01:00
Nick Johnson
671fd94e25 swarm/api: Update ENS root address for Ropsten & prod (#3391) 2016-12-01 19:33:10 +01:00
Péter Szilágyi
717d2f6f9e Merge pull request #3390 from bas-vk/statsd-stop
ethstats: check if received event is valid
2016-12-01 10:30:19 +02:00
Maran
8cb95cb916 README: removed develop mentions 2016-11-30 19:39:05 +01:00
Bas van Kervel
56b446190a ethstats: check if received event is valid 2016-11-30 17:47:39 +01:00
Péter Szilágyi
86f9e836be cmd/geth: tidied up the source (#3385)
cmd/geth: tidied up the source
2016-11-30 13:34:24 +02:00
Péter Szilágyi
a90a170361 Merge pull request #3373 from karalabe/ethstats-block-fields
ethstats: don't drop concurrent head reports (mini forks)
2016-11-30 12:36:22 +02:00
Péter Szilágyi
889a5e0cf1 Merge pull request #3368 from bas-vk/sha3
node: improve error handling for web3_sha3 RPC method
2016-11-30 12:10:05 +02:00
Martin Holst Swende
9f8bc00cf5 eth, miner: removed unnecessary state.Copy()
* miner: removed unnecessary state.Copy()

* eth: made use of new miner method without state copying

* miner: More documentation about new method
2016-11-30 11:48:48 +02:00
Luca Zeug
3363a1c227 cmd/utils: update helpscreen's testnet description (#3377) 2016-11-29 16:23:11 +02:00
Péter Szilágyi
fc9939c4e1 Merge pull request #3376 from karalabe/drop-dao-flags
cmd: drop DAO related choice flags since ETC diverged
2016-11-29 16:12:40 +02:00
Péter Szilágyi
7267f796e6 cmd: drop DAO related choice flags since ETC diverged 2016-11-29 15:50:27 +02:00
Péter Szilágyi
7dfeceb8cc ethstats: don't drop concurrent head reports (mini forks) 2016-11-29 14:17:20 +02:00
Péter Szilágyi
3807e520ec Merge pull request #3370 from karalabe/ethstats-block-fields
ethstats: report block miner, gas limit and gas consumption
2016-11-29 13:15:58 +02:00
Péter Szilágyi
7625b1a4f4 ethstats: report block miner, gas limit and gas consumption 2016-11-29 11:39:56 +02:00
Bas van Kervel
1fc5cc1b59 node: improve error handling for web3_sha3 RPC method 2016-11-29 09:36:51 +01:00
Steven Roose
61ccb43487 core/types: Document Transaction.To (#3366) 2016-11-28 21:56:38 +01:00
Jeffrey Wilcke
bf24b120d7 VERSION, params: bump unstable version 1.5.5 (#3361) 2016-11-28 15:09:12 +01:00
544 changed files with 32475 additions and 12507 deletions

View File

@@ -9,9 +9,7 @@ and help.
If you'd like to contribute to go-ethereum please fork, fix, commit and
send a pull request. Commits which do not comply with the coding standards
are ignored (use gofmt!). If you send pull requests make absolute sure that you
commit on the `develop` branch and that you do not merge to master.
Commits that are directly based on master are simply ignored.
are ignored (use gofmt!).
See [Developers' Guide](https://github.com/ethereum/go-ethereum/wiki/Developers'-Guide)
for more details on configuring your environment, testing, and

View File

@@ -13,15 +13,15 @@ matrix:
go: 1.6.2
- os: linux
dist: trusty
go: 1.7
go: 1.7.4
- os: osx
go: 1.7
go: 1.7.4
# This builder does the Ubuntu PPA and Linux Azure uploads
- os: linux
dist: trusty
sudo: required
go: 1.7
go: 1.7.4
env:
- ubuntu-ppa
- azure-linux
@@ -55,7 +55,7 @@ matrix:
# This builder does the OSX Azure, Android Maven and Azure and iOS CocoaPods and Azure uploads
- os: osx
go: 1.7
go: 1.7.4
env:
- azure-osx
- mobile
@@ -90,7 +90,7 @@ install:
- go get golang.org/x/tools/cmd/cover
script:
- go run build/ci.go install
- go run build/ci.go test -coverage -vet
- go run build/ci.go test -coverage -vet -misspell
notifications:
webhooks:

View File

@@ -39,9 +39,7 @@ The go-ethereum project comes with several wrappers/executables found in the `cm
| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow insolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug`). |
| `gethrpctest` | Developer utility tool to support our [ethereum/rpc-test](https://github.com/ethereum/rpc-tests) test suite which validates baseline conformity to the [Ethereum JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) specs. Please see the [test suite's readme](https://github.com/ethereum/rpc-tests/blob/master/README.md) for details. |
| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://github.com/ethereum/wiki/wiki/RLP)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). |
| `bzzd` | swarm daemon. This is the entrypoint for the swarm network. `bzzd --help` for command line options. See https://swarm-guide.readthedocs.io for swarm documentation. |
| `bzzup` | swarm command line file uploader. `bzzup --help` for command line options |
| `bzzhash` | command to calculate the swarm hash of a file or directory. `bzzhash --help` for command line options |
| `swarm` | swarm daemon and tools. This is the entrypoint for the swarm network. `swarm --help` for command line options and subcommands. See https://swarm-guide.readthedocs.io for swarm documentation. |
## Running geth

View File

@@ -1 +1 @@
1.5.4
1.5.7

View File

@@ -91,8 +91,30 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
// first we need to create a slice of the type
var refSlice reflect.Value
switch elem.T {
case IntTy, UintTy, BoolTy: // int, uint, bool can all be of type big int.
refSlice = reflect.ValueOf([]*big.Int(nil))
case IntTy, UintTy, BoolTy:
// create a new reference slice matching the element type
switch t.Type.Kind {
case reflect.Bool:
refSlice = reflect.ValueOf([]bool(nil))
case reflect.Uint8:
refSlice = reflect.ValueOf([]uint8(nil))
case reflect.Uint16:
refSlice = reflect.ValueOf([]uint16(nil))
case reflect.Uint32:
refSlice = reflect.ValueOf([]uint32(nil))
case reflect.Uint64:
refSlice = reflect.ValueOf([]uint64(nil))
case reflect.Int8:
refSlice = reflect.ValueOf([]int8(nil))
case reflect.Int16:
refSlice = reflect.ValueOf([]int16(nil))
case reflect.Int32:
refSlice = reflect.ValueOf([]int32(nil))
case reflect.Int64:
refSlice = reflect.ValueOf([]int64(nil))
default:
refSlice = reflect.ValueOf([]*big.Int(nil))
}
case AddressTy: // address must be of slice Address
refSlice = reflect.ValueOf([]common.Address(nil))
case HashTy: // hash must be of slice hash
@@ -147,7 +169,27 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
// set inter to the correct type (cast)
switch elem.T {
case IntTy, UintTy:
inter = common.BytesToBig(returnOutput)
bigNum := common.BytesToBig(returnOutput)
switch t.Type.Kind {
case reflect.Uint8:
inter = uint8(bigNum.Uint64())
case reflect.Uint16:
inter = uint16(bigNum.Uint64())
case reflect.Uint32:
inter = uint32(bigNum.Uint64())
case reflect.Uint64:
inter = bigNum.Uint64()
case reflect.Int8:
inter = int8(bigNum.Int64())
case reflect.Int16:
inter = int16(bigNum.Int64())
case reflect.Int32:
inter = int32(bigNum.Int64())
case reflect.Int64:
inter = bigNum.Int64()
default:
inter = common.BytesToBig(returnOutput)
}
case BoolTy:
inter = common.BytesToBig(returnOutput).Uint64() > 0
case AddressTy:
@@ -169,7 +211,7 @@ func toGoSlice(i int, t Argument, output []byte) (interface{}, error) {
// argument in T.
func toGoType(i int, t Argument, output []byte) (interface{}, error) {
// we need to treat slices differently
if (t.Type.IsSlice || t.Type.IsArray) && t.Type.T != BytesTy && t.Type.T != StringTy && t.Type.T != FixedBytesTy {
if (t.Type.IsSlice || t.Type.IsArray) && t.Type.T != BytesTy && t.Type.T != StringTy && t.Type.T != FixedBytesTy && t.Type.T != FunctionTy {
return toGoSlice(i, t, output)
}
@@ -233,7 +275,7 @@ func toGoType(i int, t Argument, output []byte) (interface{}, error) {
return common.BytesToAddress(returnOutput), nil
case HashTy:
return common.BytesToHash(returnOutput), nil
case BytesTy, FixedBytesTy:
case BytesTy, FixedBytesTy, FunctionTy:
return returnOutput, nil
case StringTy:
return string(returnOutput), nil
@@ -345,12 +387,13 @@ func (abi ABI) Unpack(v interface{}, name string, output []byte) error {
func (abi *ABI) UnmarshalJSON(data []byte) error {
var fields []struct {
Type string
Name string
Constant bool
Indexed bool
Inputs []Argument
Outputs []Argument
Type string
Name string
Constant bool
Indexed bool
Anonymous bool
Inputs []Argument
Outputs []Argument
}
if err := json.Unmarshal(data, &fields); err != nil {
@@ -375,8 +418,9 @@ func (abi *ABI) UnmarshalJSON(data []byte) error {
}
case "event":
abi.Events[field.Name] = Event{
Name: field.Name,
Inputs: field.Inputs,
Name: field.Name,
Anonymous: field.Anonymous,
Inputs: field.Inputs,
}
}
}

View File

@@ -67,10 +67,10 @@ func TestTypeCheck(t *testing.T) {
{"uint16[3]", [4]uint16{1, 2, 3}, "abi: cannot use [4]uint16 as type [3]uint16 as argument"},
{"uint16[3]", []uint16{1, 2, 3}, ""},
{"uint16[3]", []uint16{1, 2, 3, 4}, "abi: cannot use [4]uint16 as type [3]uint16 as argument"},
{"address[]", []common.Address{common.Address{1}}, ""},
{"address[1]", []common.Address{common.Address{1}}, ""},
{"address[1]", [1]common.Address{common.Address{1}}, ""},
{"address[2]", [1]common.Address{common.Address{1}}, "abi: cannot use [1]array as type [2]array as argument"},
{"address[]", []common.Address{{1}}, ""},
{"address[1]", []common.Address{{1}}, ""},
{"address[1]", [1]common.Address{{1}}, ""},
{"address[2]", [1]common.Address{{1}}, "abi: cannot use [1]array as type [2]array as argument"},
{"bytes32", [32]byte{}, ""},
{"bytes32", [33]byte{}, "abi: cannot use [33]uint8 as type [32]uint8 as argument"},
{"bytes32", common.Hash{1}, ""},
@@ -80,7 +80,8 @@ func TestTypeCheck(t *testing.T) {
{"bytes", [2]byte{0, 1}, ""},
{"bytes", common.Hash{1}, ""},
{"string", "hello world", ""},
{"bytes32[]", [][32]byte{[32]byte{}}, ""},
{"bytes32[]", [][32]byte{{}}, ""},
{"function", [24]byte{}, ""},
} {
typ, err := NewType(test.typ)
if err != nil {
@@ -197,6 +198,13 @@ func TestSimpleMethodUnpack(t *testing.T) {
"interface",
"",
},
{
`[ { "type": "function" } ]`,
pad([]byte{1}, 32, false),
[24]byte{1},
"function",
"",
},
} {
abiDefinition := fmt.Sprintf(`[{ "name" : "method", "outputs": %s}]`, test.def)
abi, err := JSON(strings.NewReader(abiDefinition))
@@ -255,6 +263,10 @@ func TestSimpleMethodUnpack(t *testing.T) {
var v common.Hash
err = abi.Unpack(&v, "method", test.marshalledOutput)
outvar = v
case "function":
var v [24]byte
err = abi.Unpack(&v, "method", test.marshalledOutput)
outvar = v
case "interface":
err = abi.Unpack(&outvar, "method", test.marshalledOutput)
default:
@@ -320,6 +332,30 @@ func TestUnpackSetInterfaceSlice(t *testing.T) {
}
}
func TestUnpackSetInterfaceArrayOutput(t *testing.T) {
var (
var1 = new([1]uint32)
var2 = new([1]uint32)
)
out := []interface{}{var1, var2}
abi, err := JSON(strings.NewReader(`[{"type":"function", "name":"ints", "outputs":[{"type":"uint32[1]"}, {"type":"uint32[1]"}]}]`))
if err != nil {
t.Fatal(err)
}
marshalledReturn := append(pad([]byte{1}, 32, true), pad([]byte{2}, 32, true)...)
err = abi.Unpack(&out, "ints", marshalledReturn)
if err != nil {
t.Fatal(err)
}
if *var1 != [1]uint32{1} {
t.Error("expected var1 to be [1], got", *var1)
}
if *var2 != [1]uint32{2} {
t.Error("expected var2 to be [2], got", *var2)
}
}
func TestPack(t *testing.T) {
for i, test := range []struct {
typ string
@@ -331,8 +367,9 @@ func TestPack(t *testing.T) {
{"uint16[]", []uint16{1, 2}, formatSliceOutput([]byte{1}, []byte{2})},
{"bytes20", [20]byte{1}, pad([]byte{1}, 32, false)},
{"uint256[]", []*big.Int{big.NewInt(1), big.NewInt(2)}, formatSliceOutput([]byte{1}, []byte{2})},
{"address[]", []common.Address{common.Address{1}, common.Address{2}}, formatSliceOutput(pad([]byte{1}, 20, false), pad([]byte{2}, 20, false))},
{"bytes32[]", []common.Hash{common.Hash{1}, common.Hash{2}}, formatSliceOutput(pad([]byte{1}, 32, false), pad([]byte{2}, 32, false))},
{"address[]", []common.Address{{1}, {2}}, formatSliceOutput(pad([]byte{1}, 20, false), pad([]byte{2}, 20, false))},
{"bytes32[]", []common.Hash{{1}, {2}}, formatSliceOutput(pad([]byte{1}, 32, false), pad([]byte{2}, 32, false))},
{"function", [24]byte{1}, pad([]byte{1}, 32, false)},
} {
typ, err := NewType(test.typ)
if err != nil {
@@ -445,12 +482,12 @@ func TestReader(t *testing.T) {
Uint256, _ := NewType("uint256")
exp := ABI{
Methods: map[string]Method{
"balance": Method{
"balance": {
"balance", true, nil, nil,
},
"send": Method{
"send": {
"send", false, []Argument{
Argument{"amount", Uint256, false},
{"amount", Uint256, false},
}, nil,
},
},
@@ -549,7 +586,7 @@ func TestTestSlice(t *testing.T) {
func TestMethodSignature(t *testing.T) {
String, _ := NewType("string")
m := Method{"foo", false, []Argument{Argument{"bar", String, false}, Argument{"baz", String, false}}, nil}
m := Method{"foo", false, []Argument{{"bar", String, false}, {"baz", String, false}}, nil}
exp := "foo(string,string)"
if m.Sig() != exp {
t.Error("signature mismatch", exp, "!=", m.Sig())
@@ -561,7 +598,7 @@ func TestMethodSignature(t *testing.T) {
}
uintt, _ := NewType("uint")
m = Method{"foo", false, []Argument{Argument{"bar", uintt, false}}, nil}
m = Method{"foo", false, []Argument{{"bar", uintt, false}}, nil}
exp = "foo(uint256)"
if m.Sig() != exp {
t.Error("signature mismatch", exp, "!=", m.Sig())
@@ -752,23 +789,58 @@ func TestDefaultFunctionParsing(t *testing.T) {
func TestBareEvents(t *testing.T) {
const definition = `[
{ "type" : "event", "name" : "balance" },
{ "type" : "event", "name" : "name" }]`
{ "type" : "event", "name" : "anon", "anonymous" : true},
{ "type" : "event", "name" : "args", "inputs" : [{ "indexed":false, "name":"arg0", "type":"uint256" }, { "indexed":true, "name":"arg1", "type":"address" }] }
]`
arg0, _ := NewType("uint256")
arg1, _ := NewType("address")
expectedEvents := map[string]struct {
Anonymous bool
Args []Argument
}{
"balance": {false, nil},
"anon": {true, nil},
"args": {false, []Argument{
{Name: "arg0", Type: arg0, Indexed: false},
{Name: "arg1", Type: arg1, Indexed: true},
}},
}
abi, err := JSON(strings.NewReader(definition))
if err != nil {
t.Fatal(err)
}
if len(abi.Events) != 2 {
t.Error("expected 2 events")
if len(abi.Events) != len(expectedEvents) {
t.Fatalf("invalid number of events after parsing, want %d, got %d", len(expectedEvents), len(abi.Events))
}
if _, ok := abi.Events["balance"]; !ok {
t.Error("expected 'balance' event to be present")
}
if _, ok := abi.Events["name"]; !ok {
t.Error("expected 'name' event to be present")
for name, exp := range expectedEvents {
got, ok := abi.Events[name]
if !ok {
t.Errorf("could not found event %s", name)
continue
}
if got.Anonymous != exp.Anonymous {
t.Errorf("invalid anonymous indication for event %s, want %v, got %v", name, exp.Anonymous, got.Anonymous)
}
if len(got.Inputs) != len(exp.Args) {
t.Errorf("invalid number of args, want %d, got %d", len(exp.Args), len(got.Inputs))
continue
}
for i, arg := range exp.Args {
if arg.Name != got.Inputs[i].Name {
t.Errorf("events[%s].Input[%d] has an invalid name, want %s, got %s", name, i, arg.Name, got.Inputs[i].Name)
}
if arg.Indexed != got.Inputs[i].Indexed {
t.Errorf("events[%s].Input[%d] has an invalid indexed indication, want %v, got %v", name, i, arg.Indexed, got.Inputs[i].Indexed)
}
if arg.Type.T != got.Inputs[i].Type.T {
t.Errorf("events[%s].Input[%d] has an invalid type, want %x, got %x", name, i, arg.Type.T, got.Inputs[i].Type.T)
}
}
}
}

View File

@@ -31,8 +31,9 @@ type Argument struct {
func (a *Argument) UnmarshalJSON(data []byte) error {
var extarg struct {
Name string
Type string
Name string
Type string
Indexed bool
}
err := json.Unmarshal(data, &extarg)
if err != nil {
@@ -44,6 +45,7 @@ func (a *Argument) UnmarshalJSON(data []byte) error {
return err
}
a.Name = extarg.Name
a.Indexed = extarg.Indexed
return nil
}

View File

@@ -52,7 +52,7 @@ func NewKeyedTransactor(key *ecdsa.PrivateKey) *TransactOpts {
if address != keyAddr {
return nil, errors.New("not authorized to sign this account")
}
signature, err := crypto.SignEthereum(signer.Hash(tx).Bytes(), key)
signature, err := crypto.Sign(signer.Hash(tx).Bytes(), key)
if err != nil {
return nil, err
}

View File

@@ -225,7 +225,11 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
from.SetBalance(common.MaxBig)
// Execute the call.
msg := callmsg{call}
vmenv := core.NewEnv(statedb, chainConfig, b.blockchain, msg, block.Header(), vm.Config{})
evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, statedb, chainConfig, vm.Config{})
gaspool := new(core.GasPool).AddGas(common.MaxBig)
ret, gasUsed, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
return ret, gasUsed, err

View File

@@ -170,7 +170,7 @@ func (c *BoundContract) transact(opts *TransactOpts, contract *common.Address, i
if value == nil {
value = new(big.Int)
}
nonce := uint64(0)
var nonce uint64
if opts.Nonce == nil {
nonce, err = c.transactor.PendingNonceAt(ensureContext(opts.Context), opts.From)
if err != nil {

View File

@@ -147,21 +147,21 @@ func bindTypeGo(kind abi.Type) string {
switch {
case strings.HasPrefix(stringKind, "address"):
parts := regexp.MustCompile("address(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
parts := regexp.MustCompile(`address(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
if len(parts) != 2 {
return stringKind
}
return fmt.Sprintf("%scommon.Address", parts[1])
case strings.HasPrefix(stringKind, "bytes"):
parts := regexp.MustCompile("bytes([0-9]*)(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
parts := regexp.MustCompile(`bytes([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
if len(parts) != 3 {
return stringKind
}
return fmt.Sprintf("%s[%s]byte", parts[2], parts[1])
case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"):
parts := regexp.MustCompile("(u)?int([0-9]*)(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
if len(parts) != 4 {
return stringKind
}
@@ -172,7 +172,7 @@ func bindTypeGo(kind abi.Type) string {
return fmt.Sprintf("%s*big.Int", parts[3])
case strings.HasPrefix(stringKind, "bool") || strings.HasPrefix(stringKind, "string"):
parts := regexp.MustCompile("([a-z]+)(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
parts := regexp.MustCompile(`([a-z]+)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
if len(parts) != 3 {
return stringKind
}
@@ -191,7 +191,7 @@ func bindTypeJava(kind abi.Type) string {
switch {
case strings.HasPrefix(stringKind, "address"):
parts := regexp.MustCompile("address(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
parts := regexp.MustCompile(`address(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
if len(parts) != 2 {
return stringKind
}
@@ -201,7 +201,7 @@ func bindTypeJava(kind abi.Type) string {
return fmt.Sprintf("Addresses")
case strings.HasPrefix(stringKind, "bytes"):
parts := regexp.MustCompile("bytes([0-9]*)(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
parts := regexp.MustCompile(`bytes([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
if len(parts) != 3 {
return stringKind
}
@@ -211,7 +211,7 @@ func bindTypeJava(kind abi.Type) string {
return "byte[]"
case strings.HasPrefix(stringKind, "int") || strings.HasPrefix(stringKind, "uint"):
parts := regexp.MustCompile("(u)?int([0-9]*)(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
if len(parts) != 4 {
return stringKind
}
@@ -230,7 +230,7 @@ func bindTypeJava(kind abi.Type) string {
return fmt.Sprintf("BigInts")
case strings.HasPrefix(stringKind, "bool"):
parts := regexp.MustCompile("bool(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
parts := regexp.MustCompile(`bool(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
if len(parts) != 2 {
return stringKind
}
@@ -240,7 +240,7 @@ func bindTypeJava(kind abi.Type) string {
return fmt.Sprintf("bool[]")
case strings.HasPrefix(stringKind, "string"):
parts := regexp.MustCompile("string(\\[[0-9]*\\])?").FindStringSubmatch(stringKind)
parts := regexp.MustCompile(`string(\[[0-9]*\])?`).FindStringSubmatch(stringKind)
if len(parts) != 2 {
return stringKind
}
@@ -278,7 +278,7 @@ func namedTypeJava(javaKind string, solKind abi.Type) string {
case "bool[]":
return "Bools"
case "BigInt":
parts := regexp.MustCompile("(u)?int([0-9]*)(\\[[0-9]*\\])?").FindStringSubmatch(solKind.String())
parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(solKind.String())
if len(parts) != 4 {
return javaKind
}

View File

@@ -60,7 +60,7 @@ func TestWaitDeployed(t *testing.T) {
// Create the transaction.
tx := types.NewContractCreation(0, big.NewInt(0), test.gas, big.NewInt(1), common.FromHex(test.code))
tx, _ = tx.SignECDSA(types.HomesteadSigner{}, testKey)
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
// Wait for it to get mined in the background.
var (

View File

@@ -25,10 +25,12 @@ import (
)
// Event is an event potentially triggered by the EVM's LOG mechanism. The Event
// holds type information (inputs) about the yielded output
// holds type information (inputs) about the yielded output. Anonymous events
// don't get the signature canonical representation as the first LOG topic.
type Event struct {
Name string
Inputs []Argument
Name string
Anonymous bool
Inputs []Argument
}
// Id returns the canonical representation of the event's signature used by the

View File

@@ -54,7 +54,7 @@ func packElement(t Type, reflectValue reflect.Value) []byte {
reflectValue = mustArrayToByteSlice(reflectValue)
}
return packBytesSlice(reflectValue.Bytes(), reflectValue.Len())
case FixedBytesTy:
case FixedBytesTy, FunctionTy:
if reflectValue.Kind() == reflect.Array {
reflectValue = mustArrayToByteSlice(reflectValue)
}

View File

@@ -33,7 +33,8 @@ const (
FixedBytesTy
BytesTy
HashTy
RealTy
FixedpointTy
FunctionTy
)
// Type is the reflection of the supported argument type
@@ -57,16 +58,16 @@ var (
// Types can be in the format of:
//
// Input = Type [ "[" [ Number ] "]" ] Name .
// Type = [ "u" ] "int" [ Number ] .
// Type = [ "u" ] "int" [ Number ] [ x ] [ Number ].
//
// Examples:
//
// string int uint real
// string int uint fixed
// string32 int8 uint8 uint[]
// address int256 uint256 real[2]
fullTypeRegex = regexp.MustCompile("([a-zA-Z0-9]+)(\\[([0-9]*)?\\])?")
// address int256 uint256 fixed128x128[2]
fullTypeRegex = regexp.MustCompile(`([a-zA-Z0-9]+)(\[([0-9]*)\])?`)
// typeRegex parses the abi sub types
typeRegex = regexp.MustCompile("([a-zA-Z]+)([0-9]*)?")
typeRegex = regexp.MustCompile("([a-zA-Z]+)(([0-9]+)(x([0-9]+))?)?")
)
// NewType creates a new reflection type of abi type given in t.
@@ -90,14 +91,19 @@ func NewType(t string) (typ Type, err error) {
}
typ.Elem = &sliceType
typ.stringKind = sliceType.stringKind + t[len(res[1]):]
return typ, nil
// Although we know that this is an array, we cannot return
// as we don't know the type of the element, however, if it
// is still an array, then don't determine the type.
if typ.Elem.IsArray || typ.Elem.IsSlice {
return typ, nil
}
}
// parse the type and size of the abi-type.
parsedType := typeRegex.FindAllStringSubmatch(res[1], -1)[0]
// varSize is the size of the variable
var varSize int
if len(parsedType[2]) > 0 {
if len(parsedType[3]) > 0 {
var err error
varSize, err = strconv.Atoi(parsedType[2])
if err != nil {
@@ -111,7 +117,12 @@ func NewType(t string) (typ Type, err error) {
varSize = 256
t += "256"
}
typ.stringKind = t
// only set stringKind if not array or slice, as for those,
// the correct string type has been set
if !(typ.IsArray || typ.IsSlice) {
typ.stringKind = t
}
switch varType {
case "int":
@@ -148,6 +159,12 @@ func NewType(t string) (typ Type, err error) {
typ.T = FixedBytesTy
typ.SliceSize = varSize
}
case "function":
sliceType, _ := NewType("uint8")
typ.Elem = &sliceType
typ.IsArray = true
typ.T = FunctionTy
typ.SliceSize = 24
default:
return Type{}, fmt.Errorf("unsupported arg type: %s", t)
}
@@ -168,7 +185,7 @@ func (t Type) pack(v reflect.Value) ([]byte, error) {
return nil, err
}
if (t.IsSlice || t.IsArray) && t.T != BytesTy && t.T != FixedBytesTy {
if (t.IsSlice || t.IsArray) && t.T != BytesTy && t.T != FixedBytesTy && t.T != FunctionTy {
var packed []byte
for i := 0; i < v.Len(); i++ {

78
accounts/abi/type_test.go Normal file
View File

@@ -0,0 +1,78 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package abi
import (
"reflect"
"testing"
)
// typeWithoutStringer is a alias for the Type type which simply doesn't implement
// the stringer interface to allow printing type details in the tests below.
type typeWithoutStringer Type
// Tests that all allowed types get recognized by the type parser.
func TestTypeRegexp(t *testing.T) {
tests := []struct {
blob string
kind Type
}{
{"int", Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}},
{"int8", Type{Kind: reflect.Int8, Type: big_t, Size: 8, T: IntTy, stringKind: "int8"}},
{"int256", Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}},
{"int[]", Type{IsSlice: true, SliceSize: -1, Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, Elem: &Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[]"}},
{"int[2]", Type{IsArray: true, SliceSize: 2, Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, Elem: &Type{Kind: reflect.Ptr, Type: big_t, Size: 256, T: IntTy, stringKind: "int256"}, stringKind: "int256[2]"}},
{"int32[]", Type{IsSlice: true, SliceSize: -1, Kind: reflect.Int32, Type: big_t, Size: 32, T: IntTy, Elem: &Type{Kind: reflect.Int32, Type: big_t, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[]"}},
{"int32[2]", Type{IsArray: true, SliceSize: 2, Kind: reflect.Int32, Type: big_t, Size: 32, T: IntTy, Elem: &Type{Kind: reflect.Int32, Type: big_t, Size: 32, T: IntTy, stringKind: "int32"}, stringKind: "int32[2]"}},
{"uint", Type{Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, stringKind: "uint256"}},
{"uint8", Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}},
{"uint256", Type{Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, stringKind: "uint256"}},
{"uint[]", Type{IsSlice: true, SliceSize: -1, Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, Elem: &Type{Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[]"}},
{"uint[2]", Type{IsArray: true, SliceSize: 2, Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, Elem: &Type{Kind: reflect.Ptr, Type: ubig_t, Size: 256, T: UintTy, stringKind: "uint256"}, stringKind: "uint256[2]"}},
{"uint32[]", Type{IsSlice: true, SliceSize: -1, Kind: reflect.Uint32, Type: ubig_t, Size: 32, T: UintTy, Elem: &Type{Kind: reflect.Uint32, Type: big_t, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[]"}},
{"uint32[2]", Type{IsArray: true, SliceSize: 2, Kind: reflect.Uint32, Type: ubig_t, Size: 32, T: UintTy, Elem: &Type{Kind: reflect.Uint32, Type: big_t, Size: 32, T: UintTy, stringKind: "uint32"}, stringKind: "uint32[2]"}},
{"bytes", Type{IsSlice: true, SliceSize: -1, Elem: &Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}, T: BytesTy, stringKind: "bytes"}},
{"bytes32", Type{IsArray: true, SliceSize: 32, Elem: &Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}, T: FixedBytesTy, stringKind: "bytes32"}},
{"bytes[]", Type{IsSlice: true, SliceSize: -1, Elem: &Type{IsSlice: true, SliceSize: -1, Elem: &Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}, T: BytesTy, stringKind: "bytes"}, stringKind: "bytes[]"}},
{"bytes[2]", Type{IsArray: true, SliceSize: 2, Elem: &Type{IsSlice: true, SliceSize: -1, Elem: &Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}, T: BytesTy, stringKind: "bytes"}, stringKind: "bytes[2]"}},
{"bytes32[]", Type{IsSlice: true, SliceSize: -1, Elem: &Type{IsArray: true, SliceSize: 32, Elem: &Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}, T: FixedBytesTy, stringKind: "bytes32"}, stringKind: "bytes32[]"}},
{"bytes32[2]", Type{IsArray: true, SliceSize: 2, Elem: &Type{IsArray: true, SliceSize: 32, Elem: &Type{Kind: reflect.Uint8, Type: ubig_t, Size: 8, T: UintTy, stringKind: "uint8"}, T: FixedBytesTy, stringKind: "bytes32"}, stringKind: "bytes32[2]"}},
{"string", Type{Kind: reflect.String, Size: -1, T: StringTy, stringKind: "string"}},
{"string[]", Type{IsSlice: true, SliceSize: -1, Kind: reflect.String, T: StringTy, Size: -1, Elem: &Type{Kind: reflect.String, T: StringTy, Size: -1, stringKind: "string"}, stringKind: "string[]"}},
{"string[2]", Type{IsArray: true, SliceSize: 2, Kind: reflect.String, T: StringTy, Size: -1, Elem: &Type{Kind: reflect.String, T: StringTy, Size: -1, stringKind: "string"}, stringKind: "string[2]"}},
{"address", Type{Kind: reflect.Array, Type: address_t, Size: 20, T: AddressTy, stringKind: "address"}},
{"address[]", Type{IsSlice: true, SliceSize: -1,Kind: reflect.Array, Type:address_t, T: AddressTy, Size:20, Elem: &Type{Kind: reflect.Array, Type: address_t, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[]"}},
{"address[2]", Type{IsArray: true, SliceSize: 2,Kind: reflect.Array, Type:address_t, T: AddressTy, Size:20, Elem: &Type{Kind: reflect.Array, Type: address_t, Size: 20, T: AddressTy, stringKind: "address"}, stringKind: "address[2]"}},
// TODO when fixed types are implemented properly
// {"fixed", Type{}},
// {"fixed128x128", Type{}},
// {"fixed[]", Type{}},
// {"fixed[2]", Type{}},
// {"fixed128x128[]", Type{}},
// {"fixed128x128[2]", Type{}},
}
for i, tt := range tests {
typ, err := NewType(tt.blob)
if err != nil {
t.Errorf("type %d: failed to parse type string: %v", i, err)
}
if !reflect.DeepEqual(typ, tt.kind) {
t.Errorf("type %d: parsed type mismatch:\n have %+v\n want %+v", i, typeWithoutStringer(typ), typeWithoutStringer(tt.kind))
}
}
}

View File

@@ -136,13 +136,12 @@ func (am *Manager) DeleteAccount(a Account, passphrase string) error {
return err
}
// Sign calculates a ECDSA signature for the given hash.
// Note, Ethereum signatures have a particular format as described in the
// yellow paper. Use the SignEthereum function to calculate a signature
// in Ethereum format.
// Sign calculates a ECDSA signature for the given hash. The produced signature
// is in the [R || S || V] format where V is 0 or 1.
func (am *Manager) Sign(addr common.Address, hash []byte) ([]byte, error) {
am.mu.RLock()
defer am.mu.RUnlock()
unlockedKey, found := am.unlocked[addr]
if !found {
return nil, ErrLocked
@@ -150,28 +149,16 @@ func (am *Manager) Sign(addr common.Address, hash []byte) ([]byte, error) {
return crypto.Sign(hash, unlockedKey.PrivateKey)
}
// SignEthereum calculates a ECDSA signature for the given hash.
// The signature has the format as described in the Ethereum yellow paper.
func (am *Manager) SignEthereum(addr common.Address, hash []byte) ([]byte, error) {
am.mu.RLock()
defer am.mu.RUnlock()
unlockedKey, found := am.unlocked[addr]
if !found {
return nil, ErrLocked
}
return crypto.SignEthereum(hash, unlockedKey.PrivateKey)
}
// SignWithPassphrase signs hash if the private key matching the given
// address can be decrypted with the given passphrase.
func (am *Manager) SignWithPassphrase(addr common.Address, passphrase string, hash []byte) (signature []byte, err error) {
_, key, err := am.getDecryptedKey(Account{Address: addr}, passphrase)
// SignWithPassphrase signs hash if the private key matching the given address
// can be decrypted with the given passphrase. The produced signature is in the
// [R || S || V] format where V is 0 or 1.
func (am *Manager) SignWithPassphrase(a Account, passphrase string, hash []byte) (signature []byte, err error) {
_, key, err := am.getDecryptedKey(a, passphrase)
if err != nil {
return nil, err
}
defer zeroKey(key.PrivateKey)
return crypto.SignEthereum(hash, key.PrivateKey)
return crypto.Sign(hash, key.PrivateKey)
}
// Unlock unlocks the given account indefinitely.

View File

@@ -95,7 +95,7 @@ func TestSignWithPassphrase(t *testing.T) {
t.Fatal("expected account to be locked")
}
_, err = am.SignWithPassphrase(acc.Address, pass, testSigData)
_, err = am.SignWithPassphrase(acc, pass, testSigData)
if err != nil {
t.Fatal(err)
}
@@ -104,7 +104,7 @@ func TestSignWithPassphrase(t *testing.T) {
t.Fatal("expected account to be locked")
}
if _, err = am.SignWithPassphrase(acc.Address, "invalid passwd", testSigData); err == nil {
if _, err = am.SignWithPassphrase(acc, "invalid passwd", testSigData); err == nil {
t.Fatal("expected SignHash to fail with invalid password")
}
}
@@ -115,6 +115,9 @@ func TestTimedUnlock(t *testing.T) {
pass := "foo"
a1, err := am.NewAccount(pass)
if err != nil {
t.Fatal(err)
}
// Signing without passphrase fails because account is locked
_, err = am.Sign(a1.Address, testSigData)
@@ -147,6 +150,9 @@ func TestOverrideUnlock(t *testing.T) {
pass := "foo"
a1, err := am.NewAccount(pass)
if err != nil {
t.Fatal(err)
}
// Unlock indefinitely.
if err = am.TimedUnlock(a1, pass, 5*time.Minute); err != nil {

View File

@@ -22,6 +22,7 @@ import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"github.com/ethereum/go-ethereum/crypto"
@@ -53,6 +54,9 @@ func decryptPreSaleKey(fileContent []byte, password string) (key *Key, err error
return nil, err
}
encSeedBytes, err := hex.DecodeString(preSaleKeyStruct.EncSeed)
if err != nil {
return nil, errors.New("invalid hex in encSeed")
}
iv := encSeedBytes[:16]
cipherText := encSeedBytes[16:]
/*

View File

@@ -22,8 +22,8 @@ environment:
install:
- rmdir C:\go /s /q
- appveyor DownloadFile https://storage.googleapis.com/golang/go1.7.3.windows-%GETH_ARCH%.zip
- 7z x go1.7.3.windows-%GETH_ARCH%.zip -y -oC:\ > NUL
- appveyor DownloadFile https://storage.googleapis.com/golang/go1.7.4.windows-%GETH_ARCH%.zip
- 7z x go1.7.4.windows-%GETH_ARCH%.zip -y -oC:\ > NUL
- go version
- gcc --version

View File

@@ -24,7 +24,7 @@ Usage: go run ci.go <command> <command flags/arguments>
Available commands are:
install [-arch architecture] [ packages... ] -- builds packages and executables
test [ -coverage ] [ -vet ] [ packages... ] -- runs the tests
test [ -coverage ] [ -vet ] [ -misspell ] [ packages... ] -- runs the tests
archive [-arch architecture] [ -type zip|tar ] [ -signer key-envvar ] [ -upload dest ] -- archives build artefacts
importkeys -- imports signing keys from env
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
@@ -72,9 +72,7 @@ var (
executablePath("abigen"),
executablePath("evm"),
executablePath("geth"),
executablePath("bzzd"),
executablePath("bzzhash"),
executablePath("bzzup"),
executablePath("swarm"),
executablePath("rlpdump"),
}
@@ -93,16 +91,8 @@ var (
Description: "Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode.",
},
{
Name: "bzzd",
Description: "Ethereum Swarm daemon",
},
{
Name: "bzzup",
Description: "Ethereum Swarm command line file/directory uploader",
},
{
Name: "bzzhash",
Description: "Ethereum Swarm file/directory hash calculator",
Name: "swarm",
Description: "Ethereum Swarm daemon and tools",
},
{
Name: "abigen",
@@ -112,7 +102,8 @@ var (
// Distros for which packages are created.
// Note: vivid is unsupported because there is no golang-1.6 package for it.
debDistros = []string{"trusty", "wily", "xenial", "yakkety"}
// Note: wily is unsupported because it was officially deprecated on lanchpad.
debDistros = []string{"trusty", "xenial", "yakkety"}
)
var GOBIN, _ = filepath.Abs(filepath.Join("build", "bin"))
@@ -204,7 +195,7 @@ func doInstall(cmdline []string) {
if err != nil {
log.Fatal(err)
}
for name, _ := range pkgs {
for name := range pkgs {
if name == "main" {
gobuild := goToolArch(*arch, "build", buildFlags(env)...)
gobuild.Args = append(gobuild.Args, "-v")
@@ -271,6 +262,7 @@ func goToolArch(arch string, subcmd string, args ...string) *exec.Cmd {
func doTest(cmdline []string) {
var (
vet = flag.Bool("vet", false, "Whether to run go vet")
misspell = flag.Bool("misspell", false, "Whether to run the spell checker")
coverage = flag.Bool("coverage", false, "Whether to record code coverage")
)
flag.CommandLine.Parse(cmdline)
@@ -296,7 +288,9 @@ func doTest(cmdline []string) {
if *vet {
build.MustRun(goTool("vet", packages...))
}
if *misspell {
spellcheck(packages)
}
// Run the actual tests.
gotest := goTool("test")
// Test a single package at a time. CI builders are slow
@@ -309,6 +303,34 @@ func doTest(cmdline []string) {
build.MustRun(gotest)
}
// spellcheck runs the client9/misspell spellchecker package on all Go, Cgo and
// test files in the requested packages.
func spellcheck(packages []string) {
// Ensure the spellchecker is available
build.MustRun(goTool("get", "github.com/client9/misspell/cmd/misspell"))
// Windows chokes on long argument lists, check packages individualy
for _, pkg := range packages {
// The spell checker doesn't work on packages, gather all .go files for it
out, err := goTool("list", "-f", "{{.Dir}}{{range .GoFiles}}\n{{.}}{{end}}{{range .CgoFiles}}\n{{.}}{{end}}{{range .TestGoFiles}}\n{{.}}{{end}}", pkg).CombinedOutput()
if err != nil {
log.Fatalf("source file listing failed: %v\n%s", err, string(out))
}
// Retrieve the folder and assemble the source list
lines := strings.Split(string(out), "\n")
root := lines[0]
sources := make([]string, 0, len(lines)-1)
for _, line := range lines[1:] {
if line = strings.TrimSpace(line); line != "" {
sources = append(sources, filepath.Join(root, line))
}
}
// Run the spell checker for this particular package
build.MustRunCommand(filepath.Join(GOBIN, "misspell"), append([]string{"-error"}, sources...)...)
}
}
// Release Packaging
func doArchive(cmdline []string) {
@@ -638,6 +660,7 @@ func doWindowsInstaller(cmdline []string) {
build.Render("build/nsis.geth.nsi", filepath.Join(*workdir, "geth.nsi"), 0644, nil)
build.Render("build/nsis.install.nsh", filepath.Join(*workdir, "install.nsh"), 0644, templateData)
build.Render("build/nsis.uninstall.nsh", filepath.Join(*workdir, "uninstall.nsh"), 0644, allTools)
build.Render("build/nsis.pathupdate.nsh", filepath.Join(*workdir, "PathUpdate.nsh"), 0644, nil)
build.Render("build/nsis.envvarupdate.nsh", filepath.Join(*workdir, "EnvVarUpdate.nsh"), 0644, nil)
build.CopyFile(filepath.Join(*workdir, "SimpleFC.dll"), "build/nsis.simplefc.dll", 0755)
build.CopyFile(filepath.Join(*workdir, "COPYING"), "COPYING", 0755)
@@ -800,7 +823,7 @@ func doXCodeFramework(cmdline []string) {
// Build the iOS XCode framework
build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile"))
build.MustRun(gomobileTool("init"))
bind := gomobileTool("bind", "--target", "ios", "--tags", "ios", "--prefix", "GE", "-v", "github.com/ethereum/go-ethereum/mobile")
bind := gomobileTool("bind", "--target", "ios", "--tags", "ios", "-v", "github.com/ethereum/go-ethereum/mobile")
if *local {
// If we're building locally, use the build folder and stop afterwards

View File

@@ -17,8 +17,12 @@
#
# Requirements:
# - NSIS, http://nsis.sourceforge.net/Main_Page
# - NSIS Large Strings build, http://nsis.sourceforge.net/Special_Builds
# - SFP, http://nsis.sourceforge.net/NSIS_Simple_Firewall_Plugin (put dll in NSIS\Plugins\x86-ansi)
#
# After intalling NSIS extra the NSIS Large Strings build zip and replace the makensis.exe and the
# files found in Stub.
#
# based on: http://nsis.sourceforge.net/A_simple_installer_with_start_menu_shortcut_and_uninstaller
#
# TODO:
@@ -37,6 +41,7 @@ RequestExecutionLevel admin
SetCompressor /SOLID lzma
!include LogicLib.nsh
!include PathUpdate.nsh
!include EnvVarUpdate.nsh
!macro VerifyUserIsAdmin

View File

@@ -37,8 +37,9 @@ Section "Geth" GETH_IDX
${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\geth.ipc"
${EnvVarUpdate} $0 "ETHEREUM_SOCKET" "A" "HKLM" "\\.\pipe\geth.ipc"
# Add geth to PATH
${EnvVarUpdate} $0 "PATH" "A" "HKLM" $INSTDIR
# Add instdir to PATH
Push "$INSTDIR"
Call AddToPath
SectionEnd
# Install optional develop tools.

153
build/nsis.pathupdate.nsh Normal file
View File

@@ -0,0 +1,153 @@
!include "WinMessages.nsh"
; see https://support.microsoft.com/en-us/kb/104011
!define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"'
; HKEY_LOCAL_MACHINE = 0x80000002
; AddToPath - Appends dir to PATH
; (does not work on Win9x/ME)
;
; Usage:
; Push "dir"
; Call AddToPath
Function AddToPath
Exch $0
Push $1
Push $2
Push $3
Push $4
; NSIS ReadRegStr returns empty string on string overflow
; Native calls are used here to check actual length of PATH
; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", &$3)
System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4"
IntCmp $4 0 0 done done
; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2))
; RegCloseKey($3)
System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4"
System::Call "advapi32::RegCloseKey(i $3)"
IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA
DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}"
MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}"
Goto done
IntCmp $4 0 +5 ; $4 != NO_ERROR
IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND
DetailPrint "AddToPath: unexpected error code $4"
Goto done
StrCpy $1 ""
; Check if already in PATH
Push "$1;"
Push "$0;"
Call StrStr
Pop $2
StrCmp $2 "" 0 done
Push "$1;"
Push "$0\;"
Call StrStr
Pop $2
StrCmp $2 "" 0 done
; Prevent NSIS string overflow
StrLen $2 $0
StrLen $3 $1
IntOp $2 $2 + $3
IntOp $2 $2 + 2 ; $2 = strlen(dir) + strlen(PATH) + sizeof(";")
IntCmp $2 ${NSIS_MAX_STRLEN} +4 +4 0
DetailPrint "AddToPath: new length $2 > ${NSIS_MAX_STRLEN}"
MessageBox MB_OK "PATH not updated, new length $2 > ${NSIS_MAX_STRLEN}."
Goto done
; Append dir to PATH
DetailPrint "Add to PATH: $0"
StrCpy $2 $1 1 -1
StrCmp $2 ";" 0 +2
StrCpy $1 $1 -1 ; remove trailing ';'
StrCmp $1 "" +2 ; no leading ';'
StrCpy $0 "$1;$0"
WriteRegExpandStr ${Environ} "PATH" $0
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
done:
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd
; RemoveFromPath - Removes dir from PATH
;
; Usage:
; Push "dir"
; Call RemoveFromPath
Function un.RemoveFromPath
Exch $0
Push $1
Push $2
Push $3
Push $4
Push $5
Push $6
; NSIS ReadRegStr returns empty string on string overflow
; Native calls are used here to check actual length of PATH
; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\CurrentControlSet\Control\Session Manager\Environment", &$3)
System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4"
IntCmp $4 0 0 done done
; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2))
; RegCloseKey($3)
System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4"
System::Call "advapi32::RegCloseKey(i $3)"
IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA
DetailPrint "RemoveFromPath: original length $2 > ${NSIS_MAX_STRLEN}"
MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}"
Goto done
IntCmp $4 0 +5 ; $4 != NO_ERROR
IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND
DetailPrint "RemoveFromPath: unexpected error code $4"
Goto done
StrCpy $1 ""
; length < ${NSIS_MAX_STRLEN} -> ReadRegStr can be used
ReadRegStr $1 ${Environ} "PATH"
StrCpy $5 $1 1 -1
StrCmp $5 ";" +2
StrCpy $1 "$1;" ; ensure trailing ';'
Push $1
Push "$0;"
Call un.StrStr
Pop $2 ; pos of our dir
StrCmp $2 "" done
DetailPrint "Remove from PATH: $0"
StrLen $3 "$0;"
StrLen $4 $2
StrCpy $5 $1 -$4 ; $5 is now the part before the path to remove
StrCpy $6 $2 "" $3 ; $6 is now the part after the path to remove
StrCpy $3 "$5$6"
StrCpy $5 $3 1 -1
StrCmp $5 ";" 0 +2
StrCpy $3 $3 -1 ; remove trailing ';'
WriteRegExpandStr ${Environ} "PATH" $3
SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000
done:
Pop $6
Pop $5
Pop $4
Pop $3
Pop $2
Pop $1
Pop $0
FunctionEnd

View File

@@ -25,7 +25,8 @@ Section "Uninstall"
${un.EnvVarUpdate} $0 "ETHEREUM_SOCKET" "R" "HKLM" "\\.\pipe\geth.ipc"
# Remove install directory from PATH
${un.EnvVarUpdate} $0 "PATH" "R" "HKLM" $INSTDIR
Push "$INSTDIR"
Call un.RemoveFromPath
# Cleanup registry (deletes all sub keys)
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${GROUPNAME} ${APPNAME}"

View File

@@ -185,7 +185,7 @@ func getFiles() []string {
files = append(files, line)
})
if err != nil {
log.Fatalf("error getting files:", err)
log.Fatal("error getting files:", err)
}
return files
}
@@ -294,7 +294,7 @@ func getInfo(files <-chan string, out chan<- *info, wg *sync.WaitGroup) {
wg.Done()
}
// fileInfo finds the lowest year in which the given file was commited.
// fileInfo finds the lowest year in which the given file was committed.
func fileInfo(file string) (*info, error) {
info := &info{file: file, Year: int64(time.Now().Year())}
cmd := exec.Command("git", "log", "--follow", "--find-renames=80", "--find-copies=80", "--pretty=format:%ai", "--", file)

View File

@@ -1,161 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
// Command bzzup uploads files to the swarm HTTP API.
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"mime"
"net/http"
"os"
"path/filepath"
"strings"
)
func main() {
var (
bzzapiFlag = flag.String("bzzapi", "http://127.0.0.1:8500", "Swarm HTTP endpoint")
recursiveFlag = flag.Bool("recursive", false, "Upload directories recursively")
manifestFlag = flag.Bool("manifest", true, "Skip automatic manifest upload")
)
log.SetOutput(os.Stderr)
log.SetFlags(0)
flag.Parse()
if flag.NArg() != 1 {
log.Fatal("need filename as the first and only argument")
}
var (
file = flag.Arg(0)
client = &client{api: *bzzapiFlag}
mroot manifest
)
fi, err := os.Stat(file)
if err != nil {
log.Fatal(err)
}
if fi.IsDir() {
if !*recursiveFlag {
log.Fatal("argument is a directory and recursive upload is disabled")
}
mroot, err = client.uploadDirectory(file)
} else {
mroot, err = client.uploadFile(file, fi)
if *manifestFlag {
// Wrap the raw file entry in a proper manifest so both hashes get printed.
mroot = manifest{Entries: []manifest{mroot}}
}
}
if err != nil {
log.Fatalln("upload failed:", err)
}
if *manifestFlag {
hash, err := client.uploadManifest(mroot)
if err != nil {
log.Fatalln("manifest upload failed:", err)
}
mroot.Hash = hash
}
// Print the manifest. This is the only output to stdout.
mrootJSON, _ := json.MarshalIndent(mroot, "", " ")
fmt.Println(string(mrootJSON))
}
// client wraps interaction with the swarm HTTP gateway.
type client struct {
api string
}
// manifest is the JSON representation of a swarm manifest.
type manifest struct {
Hash string `json:"hash,omitempty"`
ContentType string `json:"contentType,omitempty"`
Path string `json:"path,omitempty"`
Entries []manifest `json:"entries,omitempty"`
}
func (c *client) uploadFile(file string, fi os.FileInfo) (manifest, error) {
hash, err := c.uploadFileContent(file, fi)
m := manifest{
Hash: hash,
ContentType: mime.TypeByExtension(filepath.Ext(fi.Name())),
}
return m, err
}
func (c *client) uploadDirectory(dir string) (manifest, error) {
dirm := manifest{}
prefix := filepath.ToSlash(filepath.Clean(dir)) + "/"
err := filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
if err != nil || fi.IsDir() {
return err
}
if !strings.HasPrefix(path, dir) {
return fmt.Errorf("path %s outside directory %s", path, dir)
}
entry, err := c.uploadFile(path, fi)
entry.Path = strings.TrimPrefix(filepath.ToSlash(filepath.Clean(path)), prefix)
dirm.Entries = append(dirm.Entries, entry)
return err
})
return dirm, err
}
func (c *client) uploadFileContent(file string, fi os.FileInfo) (string, error) {
fd, err := os.Open(file)
if err != nil {
return "", err
}
defer fd.Close()
log.Printf("uploading file %s (%d bytes)", file, fi.Size())
return c.postRaw("application/octet-stream", fi.Size(), fd)
}
func (c *client) uploadManifest(m manifest) (string, error) {
jsm, err := json.Marshal(m)
if err != nil {
panic(err)
}
log.Println("uploading manifest")
return c.postRaw("application/json", int64(len(jsm)), ioutil.NopCloser(bytes.NewReader(jsm)))
}
func (c *client) postRaw(mimetype string, size int64, body io.ReadCloser) (string, error) {
req, err := http.NewRequest("POST", c.api+"/bzzr:/", body)
if err != nil {
return "", err
}
req.Header.Set("content-type", mimetype)
req.ContentLength = size
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
return "", fmt.Errorf("bad status: %s", resp.Status)
}
content, err := ioutil.ReadAll(resp.Body)
return string(content), err
}

View File

@@ -18,11 +18,12 @@
package main
import (
"encoding/hex"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
)
@@ -32,20 +33,28 @@ func main() {
fmt.Println(err)
os.Exit(1)
}
code = common.Hex2Bytes(string(code[:len(code)-1]))
code, err = hex.DecodeString(strings.TrimSpace(string(code[:])))
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("%x\n", code)
for pc := uint64(0); pc < uint64(len(code)); pc++ {
op := vm.OpCode(code[pc])
fmt.Printf("%-5d %v", pc, op)
switch op {
case vm.PUSH1, vm.PUSH2, vm.PUSH3, vm.PUSH4, vm.PUSH5, vm.PUSH6, vm.PUSH7, vm.PUSH8, vm.PUSH9, vm.PUSH10, vm.PUSH11, vm.PUSH12, vm.PUSH13, vm.PUSH14, vm.PUSH15, vm.PUSH16, vm.PUSH17, vm.PUSH18, vm.PUSH19, vm.PUSH20, vm.PUSH21, vm.PUSH22, vm.PUSH23, vm.PUSH24, vm.PUSH25, vm.PUSH26, vm.PUSH27, vm.PUSH28, vm.PUSH29, vm.PUSH30, vm.PUSH31, vm.PUSH32:
a := uint64(op) - uint64(vm.PUSH1) + 1
fmt.Printf(" => %x", code[pc+1:pc+1+a])
u := pc + 1 + a
if uint64(len(code)) <= pc || uint64(len(code)) < u {
fmt.Printf("Error: incomplete push instruction at %v\n", pc)
return
}
fmt.Printf("%-5d %v => %x\n", pc, op, code[pc+1:u])
pc += a
default:
fmt.Printf("%-5d %v\n", pc, op)
}
fmt.Println()
}
}

View File

@@ -88,12 +88,7 @@ func runTestWithReader(test string, r io.Reader) error {
default:
err = fmt.Errorf("Invalid test type specified: %v", test)
}
if err != nil {
return err
}
return nil
return err
}
func getFiles(path string) ([]string, error) {

View File

@@ -20,21 +20,18 @@ package main
import (
"fmt"
"io/ioutil"
"math/big"
"os"
"runtime"
goruntime "runtime"
"time"
"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/core/vm"
"github.com/ethereum/go-ethereum/core/vm/runtime"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
"gopkg.in/urfave/cli.v1"
)
@@ -47,14 +44,6 @@ var (
Name: "debug",
Usage: "output full trace logs",
}
ForceJitFlag = cli.BoolFlag{
Name: "forcejit",
Usage: "forces jit compilation",
}
DisableJitFlag = cli.BoolFlag{
Name: "nojit",
Usage: "disabled jit compilation",
}
CodeFlag = cli.StringFlag{
Name: "code",
Usage: "EVM code",
@@ -98,6 +87,10 @@ var (
Name: "create",
Usage: "indicates the action should be create rather than call",
}
DisableGasMeteringFlag = cli.BoolFlag{
Name: "nogasmetering",
Usage: "disable gas metering",
}
)
func init() {
@@ -105,8 +98,6 @@ func init() {
CreateFlag,
DebugFlag,
VerbosityFlag,
ForceJitFlag,
DisableJitFlag,
SysStatFlag,
CodeFlag,
CodeFileFlag,
@@ -115,6 +106,7 @@ func init() {
ValueFlag,
DumpFlag,
InputFlag,
DisableGasMeteringFlag,
}
app.Action = run
}
@@ -129,13 +121,6 @@ func run(ctx *cli.Context) error {
logger := vm.NewStructLogger(nil)
vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name)), vm.Config{
Debug: ctx.GlobalBool(DebugFlag.Name),
ForceJit: ctx.GlobalBool(ForceJitFlag.Name),
EnableJit: !ctx.GlobalBool(DisableJitFlag.Name),
Tracer: logger,
})
tstart := time.Now()
var (
@@ -168,25 +153,32 @@ func run(ctx *cli.Context) error {
if ctx.GlobalBool(CreateFlag.Name) {
input := append(code, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name))...)
ret, _, err = vmenv.Create(
sender,
input,
common.Big(ctx.GlobalString(GasFlag.Name)),
common.Big(ctx.GlobalString(PriceFlag.Name)),
common.Big(ctx.GlobalString(ValueFlag.Name)),
)
ret, _, err = runtime.Create(input, &runtime.Config{
Origin: sender.Address(),
State: statedb,
GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)),
GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)),
Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
EVMConfig: vm.Config{
Tracer: logger,
DisableGasMetering: ctx.GlobalBool(DisableGasMeteringFlag.Name),
},
})
} else {
receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
receiver.SetCode(crypto.Keccak256Hash(code), code)
ret, err = vmenv.Call(
sender,
receiver.Address(),
common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)),
common.Big(ctx.GlobalString(GasFlag.Name)),
common.Big(ctx.GlobalString(PriceFlag.Name)),
common.Big(ctx.GlobalString(ValueFlag.Name)),
)
ret, err = runtime.Call(receiver.Address(), common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtime.Config{
Origin: sender.Address(),
State: statedb,
GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)),
GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)),
Value: common.Big(ctx.GlobalString(ValueFlag.Name)),
EVMConfig: vm.Config{
Tracer: logger,
DisableGasMetering: ctx.GlobalBool(DisableGasMeteringFlag.Name),
},
})
}
vmdone := time.Since(tstart)
@@ -197,8 +189,8 @@ func run(ctx *cli.Context) error {
vm.StdErrFormat(logger.StructLogs())
if ctx.GlobalBool(SysStatFlag.Name) {
var mem runtime.MemStats
runtime.ReadMemStats(&mem)
var mem goruntime.MemStats
goruntime.ReadMemStats(&mem)
fmt.Printf("vm took %v\n", vmdone)
fmt.Printf(`alloc: %d
tot alloc: %d
@@ -223,87 +215,3 @@ func main() {
os.Exit(1)
}
}
type VMEnv struct {
state *state.StateDB
block *types.Block
transactor *common.Address
value *big.Int
depth int
Gas *big.Int
time *big.Int
logs []vm.StructLog
evm *vm.EVM
}
func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg vm.Config) *VMEnv {
env := &VMEnv{
state: state,
transactor: &transactor,
value: value,
time: big.NewInt(time.Now().Unix()),
}
env.evm = vm.New(env, cfg)
return env
}
// ruleSet implements vm.ChainConfig and will always default to the homestead rule set.
type ruleSet struct{}
func (ruleSet) IsHomestead(*big.Int) bool { return true }
func (ruleSet) GasTable(*big.Int) params.GasTable {
return params.GasTableHomesteadGasRepriceFork
}
func (self *VMEnv) ChainConfig() *params.ChainConfig { return params.TestChainConfig }
func (self *VMEnv) Vm() vm.Vm { return self.evm }
func (self *VMEnv) Db() vm.Database { return self.state }
func (self *VMEnv) SnapshotDatabase() int { return self.state.Snapshot() }
func (self *VMEnv) RevertToSnapshot(snap int) { self.state.RevertToSnapshot(snap) }
func (self *VMEnv) Origin() common.Address { return *self.transactor }
func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
func (self *VMEnv) Coinbase() common.Address { return *self.transactor }
func (self *VMEnv) Time() *big.Int { return self.time }
func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
func (self *VMEnv) Value() *big.Int { return self.value }
func (self *VMEnv) GasLimit() *big.Int { return big.NewInt(1000000000) }
func (self *VMEnv) VmType() vm.Type { return vm.StdVmTy }
func (self *VMEnv) Depth() int { return 0 }
func (self *VMEnv) SetDepth(i int) { self.depth = i }
func (self *VMEnv) GetHash(n uint64) common.Hash {
if self.block.Number().Cmp(big.NewInt(int64(n))) == 0 {
return self.block.Hash()
}
return common.Hash{}
}
func (self *VMEnv) AddLog(log *vm.Log) {
self.state.AddLog(log)
}
func (self *VMEnv) CanTransfer(from common.Address, balance *big.Int) bool {
return self.state.GetBalance(from).Cmp(balance) >= 0
}
func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) {
core.Transfer(from, to, amount)
}
func (self *VMEnv) Call(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
self.Gas = gas
return core.Call(self, caller, addr, data, gas, price, value)
}
func (self *VMEnv) CallCode(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
return core.CallCode(self, caller, addr, data, gas, price, value)
}
func (self *VMEnv) DelegateCall(caller vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) {
return core.DelegateCall(self, caller, addr, data, gas, price)
}
func (self *VMEnv) Create(caller vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) {
return core.Create(self, caller, data, gas, price, value)
}

View File

@@ -148,7 +148,7 @@ Passphrase: {{.InputLine "foobar"}}
"Unlocked account f466859ead1932d743d622cb74fc058882e8648a",
}
for _, m := range wantMessages {
if strings.Index(geth.stderrText(), m) == -1 {
if !strings.Contains(geth.stderrText(), m) {
t.Errorf("stderr text does not contain %q", m)
}
}
@@ -193,7 +193,7 @@ Passphrase: {{.InputLine "foobar"}}
"Unlocked account 289d485d9771714cce91d3393d764e1311907acc",
}
for _, m := range wantMessages {
if strings.Index(geth.stderrText(), m) == -1 {
if !strings.Contains(geth.stderrText(), m) {
t.Errorf("stderr text does not contain %q", m)
}
}
@@ -212,7 +212,7 @@ func TestUnlockFlagPasswordFile(t *testing.T) {
"Unlocked account 289d485d9771714cce91d3393d764e1311907acc",
}
for _, m := range wantMessages {
if strings.Index(geth.stderrText(), m) == -1 {
if !strings.Contains(geth.stderrText(), m) {
t.Errorf("stderr text does not contain %q", m)
}
}
@@ -260,7 +260,7 @@ In order to avoid this warning, you need to remove the following duplicate key f
"Unlocked account f466859ead1932d743d622cb74fc058882e8648a",
}
for _, m := range wantMessages {
if strings.Index(geth.stderrText(), m) == -1 {
if !strings.Contains(geth.stderrText(), m) {
t.Errorf("stderr text does not contain %q", m)
}
}

View File

@@ -32,6 +32,7 @@ import (
"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/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/trie"
"github.com/syndtr/goleveldb/leveldb/util"
@@ -39,6 +40,18 @@ import (
)
var (
initCommand = cli.Command{
Action: initGenesis,
Name: "init",
Usage: "Bootstrap and initialize a new genesis block",
ArgsUsage: "<genesisPath>",
Category: "BLOCKCHAIN COMMANDS",
Description: `
The init command initializes a new genesis block and definition for the network.
This is a destructive action and changes the network in which you will be
participating.
`,
}
importCommand = cli.Command{
Action: importChain,
Name: "import",
@@ -95,6 +108,30 @@ Use "ethereum dump 0" to dump the genesis block.
}
)
// initGenesis will initialise the given JSON format genesis file and writes it as
// the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
func initGenesis(ctx *cli.Context) error {
genesisPath := ctx.Args().First()
if len(genesisPath) == 0 {
utils.Fatalf("must supply path to genesis JSON file")
}
stack := makeFullNode(ctx)
chaindb := utils.MakeChainDatabase(ctx, stack)
genesisFile, err := os.Open(genesisPath)
if err != nil {
utils.Fatalf("failed to read genesis file: %v", err)
}
block, err := core.WriteGenesisBlock(chaindb, genesisFile)
if err != nil {
utils.Fatalf("failed to write genesis block: %v", err)
}
glog.V(logger.Info).Infof("successfully wrote genesis block and/or chain rule set: %x", block.Hash())
return nil
}
func importChain(ctx *cli.Context) error {
if len(ctx.Args()) != 1 {
utils.Fatalf("This command requires an argument.")

View File

@@ -83,75 +83,28 @@ var daoGenesisForkBlock = big.NewInt(314)
// TestDAOForkBlockNewChain tests that the DAO hard-fork number and the nodes support/opposition is correctly
// set in the database after various initialization procedures and invocations.
func TestDAOForkBlockNewChain(t *testing.T) {
for _, arg := range []struct {
for i, arg := range []struct {
testnet bool
genesis string
votes [][2]bool
expectBlock *big.Int
expectVote bool
}{
// Test DAO Default Mainnet
{false, "", [][2]bool{{false, false}}, params.MainNetDAOForkBlock, true},
// test DAO Support Mainnet
{false, "", [][2]bool{{true, false}}, params.MainNetDAOForkBlock, true},
// test DAO Oppose Mainnet
{false, "", [][2]bool{{false, true}}, params.MainNetDAOForkBlock, false},
// test DAO Switch To Support Mainnet
{false, "", [][2]bool{{false, true}, {true, false}}, params.MainNetDAOForkBlock, true},
// test DAO Switch To Oppose Mainnet
{false, "", [][2]bool{{true, false}, {false, true}}, params.MainNetDAOForkBlock, false},
{false, "", params.MainNetDAOForkBlock, true},
// test DAO Default Testnet
{true, "", [][2]bool{{false, false}}, params.TestNetDAOForkBlock, true},
// test DAO Support Testnet
{true, "", [][2]bool{{true, false}}, params.TestNetDAOForkBlock, true},
// test DAO Oppose Testnet
{true, "", [][2]bool{{false, true}}, params.TestNetDAOForkBlock, false},
// test DAO Switch To Support Testnet
{true, "", [][2]bool{{false, true}, {true, false}}, params.TestNetDAOForkBlock, true},
// test DAO Switch To Oppose Testnet
{true, "", [][2]bool{{true, false}, {false, true}}, params.TestNetDAOForkBlock, false},
{true, "", params.TestNetDAOForkBlock, true},
// test DAO Init Old Privnet
{false, daoOldGenesis, [][2]bool{}, nil, false},
// test DAO Default Old Privnet
{false, daoOldGenesis, [][2]bool{{false, false}}, nil, false},
// test DAO Support Old Privnet
{false, daoOldGenesis, [][2]bool{{true, false}}, nil, true},
// test DAO Oppose Old Privnet
{false, daoOldGenesis, [][2]bool{{false, true}}, nil, false},
// test DAO Switch To Support Old Privnet
{false, daoOldGenesis, [][2]bool{{false, true}, {true, false}}, nil, true},
// test DAO Switch To Oppose Old Privnet
{false, daoOldGenesis, [][2]bool{{true, false}, {false, true}}, nil, false},
// test DAO Init No Fork Privnet
{false, daoNoForkGenesis, [][2]bool{}, daoGenesisForkBlock, false},
{false, daoOldGenesis, nil, false},
// test DAO Default No Fork Privnet
{false, daoNoForkGenesis, [][2]bool{{false, false}}, daoGenesisForkBlock, false},
// test DAO Support No Fork Privnet
{false, daoNoForkGenesis, [][2]bool{{true, false}}, daoGenesisForkBlock, true},
// test DAO Oppose No Fork Privnet
{false, daoNoForkGenesis, [][2]bool{{false, true}}, daoGenesisForkBlock, false},
// test DAO Switch To Support No Fork Privnet
{false, daoNoForkGenesis, [][2]bool{{false, true}, {true, false}}, daoGenesisForkBlock, true},
// test DAO Switch To Oppose No Fork Privnet
{false, daoNoForkGenesis, [][2]bool{{true, false}, {false, true}}, daoGenesisForkBlock, false},
// test DAO Init Pro Fork Privnet
{false, daoProForkGenesis, [][2]bool{}, daoGenesisForkBlock, true},
{false, daoNoForkGenesis, daoGenesisForkBlock, false},
// test DAO Default Pro Fork Privnet
{false, daoProForkGenesis, [][2]bool{{false, false}}, daoGenesisForkBlock, true},
// test DAO Support Pro Fork Privnet
{false, daoProForkGenesis, [][2]bool{{true, false}}, daoGenesisForkBlock, true},
// test DAO Oppose Pro Fork Privnet
{false, daoProForkGenesis, [][2]bool{{false, true}}, daoGenesisForkBlock, false},
// test DAO Switch To Support Pro Fork Privnet
{false, daoProForkGenesis, [][2]bool{{false, true}, {true, false}}, daoGenesisForkBlock, true},
// test DAO Switch To Oppose Pro Fork Privnet
{false, daoProForkGenesis, [][2]bool{{true, false}, {false, true}}, daoGenesisForkBlock, false},
{false, daoProForkGenesis, daoGenesisForkBlock, true},
} {
testDAOForkBlockNewChain(t, arg.testnet, arg.genesis, arg.votes, arg.expectBlock, arg.expectVote)
testDAOForkBlockNewChain(t, i, arg.testnet, arg.genesis, arg.expectBlock, arg.expectVote)
}
}
func testDAOForkBlockNewChain(t *testing.T, testnet bool, genesis string, votes [][2]bool, expectBlock *big.Int, expectVote bool) {
func testDAOForkBlockNewChain(t *testing.T, test int, testnet bool, genesis string, expectBlock *big.Int, expectVote bool) {
// Create a temporary data directory to use and inspect later
datadir := tmpdir(t)
defer os.RemoveAll(datadir)
@@ -160,21 +113,15 @@ func testDAOForkBlockNewChain(t *testing.T, testnet bool, genesis string, votes
if genesis != "" {
json := filepath.Join(datadir, "genesis.json")
if err := ioutil.WriteFile(json, []byte(genesis), 0600); err != nil {
t.Fatalf("failed to write genesis file: %v", err)
t.Fatalf("test %d: failed to write genesis file: %v", test, err)
}
runGeth(t, "--datadir", datadir, "init", json).cmd.Wait()
}
for _, vote := range votes {
} else {
// Force chain initialization
args := []string{"--port", "0", "--maxpeers", "0", "--nodiscover", "--nat", "none", "--ipcdisable", "--datadir", datadir}
if testnet {
args = append(args, "--testnet")
}
if vote[0] {
args = append(args, "--support-dao-fork")
}
if vote[1] {
args = append(args, "--oppose-dao-fork")
}
geth := runGeth(t, append(args, []string{"--exec", "2+2", "console"}...)...)
geth.cmd.Wait()
}
@@ -185,7 +132,7 @@ func testDAOForkBlockNewChain(t *testing.T, testnet bool, genesis string, votes
}
db, err := ethdb.NewLDBDatabase(path, 0, 0)
if err != nil {
t.Fatalf("failed to open test database: %v", err)
t.Fatalf("test %d: failed to open test database: %v", test, err)
}
defer db.Close()
@@ -198,20 +145,20 @@ func testDAOForkBlockNewChain(t *testing.T, testnet bool, genesis string, votes
}
config, err := core.GetChainConfig(db, genesisHash)
if err != nil {
t.Errorf("failed to retrieve chain config: %v", err)
t.Errorf("test %d: failed to retrieve chain config: %v", test, err)
return // we want to return here, the other checks can't make it past this point (nil panic).
}
// Validate the DAO hard-fork block number against the expected value
if config.DAOForkBlock == nil {
if expectBlock != nil {
t.Errorf("dao hard-fork block mismatch: have nil, want %v", expectBlock)
t.Errorf("test %d: dao hard-fork block mismatch: have nil, want %v", test, expectBlock)
}
} else if expectBlock == nil {
t.Errorf("dao hard-fork block mismatch: have %v, want nil", config.DAOForkBlock)
t.Errorf("test %d: dao hard-fork block mismatch: have %v, want nil", test, config.DAOForkBlock)
} else if config.DAOForkBlock.Cmp(expectBlock) != 0 {
t.Errorf("dao hard-fork block mismatch: have %v, want %v", config.DAOForkBlock, expectBlock)
t.Errorf("test %d: dao hard-fork block mismatch: have %v, want %v", test, config.DAOForkBlock, expectBlock)
}
if config.DAOForkSupport != expectVote {
t.Errorf("dao hard-fork support mismatch: have %v, want %v", config.DAOForkSupport, expectVote)
t.Errorf("test %d: dao hard-fork support mismatch: have %v, want %v", test, config.DAOForkSupport, expectVote)
}
}

View File

@@ -1,24 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
// Simple wrapper to translate the API exposed methods and types to inthernal
// Go versions of the same types.
#include "_cgo_export.h"
int run(const char* args) {
return doRun((char*)args);
}

View File

@@ -1,46 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
// Contains a simple library definition to allow creating a Geth instance from
// straight C code.
package main
// #ifdef __cplusplus
// extern "C" {
// #endif
//
// extern int run(const char*);
//
// #ifdef __cplusplus
// }
// #endif
import "C"
import (
"fmt"
"os"
"strings"
)
//export doRun
func doRun(args *C.char) C.int {
// This is equivalent to geth.main, just modified to handle the function arg passing
if err := app.Run(strings.Split("geth "+C.GoString(args), " ")); err != nil {
fmt.Fprintln(os.Stderr, err)
return -1
}
return 0
}

View File

@@ -1,56 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
// Contains specialized code for running Geth on Android.
package main
// #include <android/log.h>
// #cgo LDFLAGS: -llog
import "C"
import (
"bufio"
"os"
)
func init() {
// Redirect the standard output and error to logcat
oldStdout, oldStderr := os.Stdout, os.Stderr
outRead, outWrite, _ := os.Pipe()
errRead, errWrite, _ := os.Pipe()
os.Stdout = outWrite
os.Stderr = errWrite
go func() {
scanner := bufio.NewScanner(outRead)
for scanner.Scan() {
line := scanner.Text()
C.__android_log_write(C.ANDROID_LOG_INFO, C.CString("Stdout"), C.CString(line))
oldStdout.WriteString(line + "\n")
}
}()
go func() {
scanner := bufio.NewScanner(errRead)
for scanner.Scan() {
line := scanner.Text()
C.__android_log_write(C.ANDROID_LOG_INFO, C.CString("Stderr"), C.CString(line))
oldStderr.WriteString(line + "\n")
}
}()
}

View File

@@ -20,20 +20,15 @@ package main
import (
"encoding/hex"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/console"
"github.com/ethereum/go-ethereum/contracts/release"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/internal/debug"
"github.com/ethereum/go-ethereum/logger"
@@ -64,59 +59,26 @@ func init() {
app.HideVersion = true // we have a command to print the version
app.Copyright = "Copyright 2013-2016 The go-ethereum Authors"
app.Commands = []cli.Command{
// See chaincmd.go:
initCommand,
importCommand,
exportCommand,
upgradedbCommand,
removedbCommand,
dumpCommand,
// See monitorcmd.go:
monitorCommand,
// See accountcmd.go:
accountCommand,
walletCommand,
// See consolecmd.go:
consoleCommand,
attachCommand,
javascriptCommand,
{
Action: makedag,
Name: "makedag",
Usage: "Generate ethash DAG (for testing)",
ArgsUsage: "<blockNum> <outputDir>",
Category: "MISCELLANEOUS COMMANDS",
Description: `
The makedag command generates an ethash DAG in /tmp/dag.
This command exists to support the system testing project.
Regular users do not need to execute it.
`,
},
{
Action: version,
Name: "version",
Usage: "Print version numbers",
ArgsUsage: " ",
Category: "MISCELLANEOUS COMMANDS",
Description: `
The output of this command is supposed to be machine-readable.
`,
},
{
Action: initGenesis,
Name: "init",
Usage: "Bootstrap and initialize a new genesis block",
ArgsUsage: "<genesisPath>",
Category: "BLOCKCHAIN COMMANDS",
Description: `
The init command initializes a new genesis block and definition for the network.
This is a destructive action and changes the network in which you will be
participating.
`,
},
{
Action: license,
Name: "license",
Usage: "Display license information",
ArgsUsage: " ",
Category: "MISCELLANEOUS COMMANDS",
},
// See misccmd.go:
makedagCommand,
versionCommand,
licenseCommand,
}
app.Flags = []cli.Flag{
@@ -126,7 +88,6 @@ participating.
utils.BootnodesFlag,
utils.DataDirFlag,
utils.KeyStoreDirFlag,
utils.OlympicFlag,
utils.FastSyncFlag,
utils.LightModeFlag,
utils.LightServFlag,
@@ -140,8 +101,6 @@ participating.
utils.MaxPendingPeersFlag,
utils.EtherbaseFlag,
utils.GasPriceFlag,
utils.SupportDAOFork,
utils.OpposeDAOFork,
utils.MinerThreadsFlag,
utils.MiningEnabledFlag,
utils.AutoDAGFlag,
@@ -208,7 +167,6 @@ participating.
}
app.After = func(ctx *cli.Context) error {
logger.Flush()
debug.Exit()
console.Stdin.Close() // Resets terminal mode.
return nil
@@ -232,30 +190,6 @@ func geth(ctx *cli.Context) error {
return nil
}
// initGenesis will initialise the given JSON format genesis file and writes it as
// the zero'd block (i.e. genesis) or will fail hard if it can't succeed.
func initGenesis(ctx *cli.Context) error {
genesisPath := ctx.Args().First()
if len(genesisPath) == 0 {
utils.Fatalf("must supply path to genesis JSON file")
}
stack := makeFullNode(ctx)
chaindb := utils.MakeChainDatabase(ctx, stack)
genesisFile, err := os.Open(genesisPath)
if err != nil {
utils.Fatalf("failed to read genesis file: %v", err)
}
block, err := core.WriteGenesisBlock(chaindb, genesisFile)
if err != nil {
utils.Fatalf("failed to write genesis block: %v", err)
}
glog.V(logger.Info).Infof("successfully wrote genesis block and/or chain rule set: %x", block.Hash())
return nil
}
func makeFullNode(ctx *cli.Context) *node.Node {
// Create the default extradata and construct the base node
var clientInfo = struct {
@@ -330,65 +264,3 @@ func startNode(ctx *cli.Context, stack *node.Node) {
}
}
}
func makedag(ctx *cli.Context) error {
args := ctx.Args()
wrongArgs := func() {
utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`)
}
switch {
case len(args) == 2:
blockNum, err := strconv.ParseUint(args[0], 0, 64)
dir := args[1]
if err != nil {
wrongArgs()
} else {
dir = filepath.Clean(dir)
// seems to require a trailing slash
if !strings.HasSuffix(dir, "/") {
dir = dir + "/"
}
_, err = ioutil.ReadDir(dir)
if err != nil {
utils.Fatalf("Can't find dir")
}
fmt.Println("making DAG, this could take awhile...")
ethash.MakeDAG(blockNum, dir)
}
default:
wrongArgs()
}
return nil
}
func version(ctx *cli.Context) error {
fmt.Println(strings.Title(clientIdentifier))
fmt.Println("Version:", params.Version)
if gitCommit != "" {
fmt.Println("Git Commit:", gitCommit)
}
fmt.Println("Protocol Versions:", eth.ProtocolVersions)
fmt.Println("Network Id:", ctx.GlobalInt(utils.NetworkIdFlag.Name))
fmt.Println("Go Version:", runtime.Version())
fmt.Println("OS:", runtime.GOOS)
fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH"))
fmt.Printf("GOROOT=%s\n", runtime.GOROOT())
return nil
}
func license(_ *cli.Context) error {
fmt.Println(`Geth is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Geth is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with geth. If not, see <http://www.gnu.org/licenses/>.
`)
return nil
}

128
cmd/geth/misccmd.go Normal file
View File

@@ -0,0 +1,128 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/params"
"gopkg.in/urfave/cli.v1"
)
var (
makedagCommand = cli.Command{
Action: makedag,
Name: "makedag",
Usage: "Generate ethash DAG (for testing)",
ArgsUsage: "<blockNum> <outputDir>",
Category: "MISCELLANEOUS COMMANDS",
Description: `
The makedag command generates an ethash DAG in /tmp/dag.
This command exists to support the system testing project.
Regular users do not need to execute it.
`,
}
versionCommand = cli.Command{
Action: version,
Name: "version",
Usage: "Print version numbers",
ArgsUsage: " ",
Category: "MISCELLANEOUS COMMANDS",
Description: `
The output of this command is supposed to be machine-readable.
`,
}
licenseCommand = cli.Command{
Action: license,
Name: "license",
Usage: "Display license information",
ArgsUsage: " ",
Category: "MISCELLANEOUS COMMANDS",
}
)
func makedag(ctx *cli.Context) error {
args := ctx.Args()
wrongArgs := func() {
utils.Fatalf(`Usage: geth makedag <block number> <outputdir>`)
}
switch {
case len(args) == 2:
blockNum, err := strconv.ParseUint(args[0], 0, 64)
dir := args[1]
if err != nil {
wrongArgs()
} else {
dir = filepath.Clean(dir)
// seems to require a trailing slash
if !strings.HasSuffix(dir, "/") {
dir = dir + "/"
}
_, err = ioutil.ReadDir(dir)
if err != nil {
utils.Fatalf("Can't find dir")
}
fmt.Println("making DAG, this could take awhile...")
ethash.MakeDAG(blockNum, dir)
}
default:
wrongArgs()
}
return nil
}
func version(ctx *cli.Context) error {
fmt.Println(strings.Title(clientIdentifier))
fmt.Println("Version:", params.Version)
if gitCommit != "" {
fmt.Println("Git Commit:", gitCommit)
}
fmt.Println("Protocol Versions:", eth.ProtocolVersions)
fmt.Println("Network Id:", ctx.GlobalInt(utils.NetworkIdFlag.Name))
fmt.Println("Go Version:", runtime.Version())
fmt.Println("OS:", runtime.GOOS)
fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH"))
fmt.Printf("GOROOT=%s\n", runtime.GOROOT())
return nil
}
func license(_ *cli.Context) error {
fmt.Println(`Geth is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Geth is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with geth. If not, see <http://www.gnu.org/licenses/>.
`)
return nil
}

View File

@@ -236,8 +236,9 @@ func expandMetrics(metrics map[string]interface{}, path string) []string {
// fetchMetric iterates over the metrics map and retrieves a specific one.
func fetchMetric(metrics map[string]interface{}, metric string) float64 {
parts, found := strings.Split(metric, "/"), true
parts := strings.Split(metric, "/")
for _, part := range parts[:len(parts)-1] {
var found bool
metrics, found = metrics[part].(map[string]interface{})
if !found {
return 0

View File

@@ -67,7 +67,6 @@ var AppHelpFlagGroups = []flagGroup{
utils.DataDirFlag,
utils.KeyStoreDirFlag,
utils.NetworkIdFlag,
utils.OlympicFlag,
utils.TestNetFlag,
utils.DevModeFlag,
utils.IdentityFlag,

View File

@@ -19,22 +19,21 @@ package main
import (
"fmt"
"log"
"os"
"runtime"
"github.com/ethereum/go-ethereum/swarm/storage"
"gopkg.in/urfave/cli.v1"
)
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
if len(os.Args) < 2 {
fmt.Println("Usage: bzzhash <file name>")
os.Exit(0)
func hash(ctx *cli.Context) {
args := ctx.Args()
if len(args) < 1 {
log.Fatal("Usage: swarm hash <file name>")
}
f, err := os.Open(os.Args[1])
f, err := os.Open(args[0])
if err != nil {
fmt.Println("Error opening file " + os.Args[1])
fmt.Println("Error opening file " + args[1])
os.Exit(1)
}
@@ -42,7 +41,7 @@ func main() {
chunker := storage.NewTreeChunker(storage.NewChunkerParams())
key, err := chunker.Split(f, stat.Size(), nil, nil, nil)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
log.Fatalf("%v\n", err)
} else {
fmt.Printf("%v\n", key)
}

View File

@@ -43,11 +43,21 @@ import (
"gopkg.in/urfave/cli.v1"
)
const clientIdentifier = "bzzd"
const (
clientIdentifier = "swarm"
versionString = "0.2"
)
var (
gitCommit string // Git SHA1 commit hash of the release (set via linker flags)
app = utils.NewApp(gitCommit, "Ethereum Swarm server daemon")
gitCommit string // Git SHA1 commit hash of the release (set via linker flags)
app = utils.NewApp(gitCommit, "Ethereum Swarm")
testbetBootNodes = []string{
"enode://ec8ae764f7cb0417bdfb009b9d0f18ab3818a3a4e8e7c67dd5f18971a93510a2e6f43cd0b69a27e439a9629457ea804104f37c85e41eed057d3faabbf7744cdf@13.74.157.139:30429",
"enode://c2e1fceb3bf3be19dff71eec6cccf19f2dbf7567ee017d130240c670be8594bc9163353ca55dd8df7a4f161dd94b36d0615c17418b5a3cdcbb4e9d99dfa4de37@13.74.157.139:30430",
"enode://fe29b82319b734ce1ec68b84657d57145fee237387e63273989d354486731e59f78858e452ef800a020559da22dcca759536e6aa5517c53930d29ce0b1029286@13.74.157.139:30431",
"enode://1d7187e7bde45cf0bee489ce9852dd6d1a0d9aa67a33a6b8e6db8a4fbc6fcfa6f0f1a5419343671521b863b187d1c73bad3603bae66421d157ffef357669ddb8@13.74.157.139:30432",
"enode://0e4cba800f7b1ee73673afa6a4acead4018f0149d2e3216be3f133318fd165b324cd71b81fbe1e80deac8dbf56e57a49db7be67f8b9bc81bd2b7ee496434fb5d@13.74.157.139:30433",
}
)
var (
@@ -65,30 +75,49 @@ var (
}
SwarmNetworkIdFlag = cli.IntFlag{
Name: "bzznetworkid",
Usage: "Network identifier (integer, default 322=swarm testnet)",
Usage: "Network identifier (integer, default 3=swarm testnet)",
Value: network.NetworkId,
}
SwarmConfigPathFlag = cli.StringFlag{
Name: "bzzconfig",
Usage: "Swarm config file path (datadir/bzz)",
}
SwarmSwapEnabled = cli.BoolFlag{
SwarmSwapEnabledFlag = cli.BoolFlag{
Name: "swap",
Usage: "Swarm SWAP enabled (default false)",
}
SwarmSyncEnabled = cli.BoolTFlag{
SwarmSyncEnabledFlag = cli.BoolTFlag{
Name: "sync",
Usage: "Swarm Syncing enabled (default true)",
}
EthAPI = cli.StringFlag{
EthAPIFlag = cli.StringFlag{
Name: "ethapi",
Usage: "URL of the Ethereum API provider",
Value: node.DefaultIPCEndpoint("geth"),
}
SwarmApiFlag = cli.StringFlag{
Name: "bzzapi",
Usage: "Swarm HTTP endpoint",
Value: "http://127.0.0.1:8500",
}
SwarmRecursiveUploadFlag = cli.BoolFlag{
Name: "recursive",
Usage: "Upload directories recursively",
}
SwarmWantManifestFlag = cli.BoolTFlag{
Name: "manifest",
Usage: "Automatic manifest upload",
}
SwarmUploadDefaultPath = cli.StringFlag{
Name: "defaultpath",
Usage: "path to file served for empty url path (none)",
}
CorsStringFlag = cli.StringFlag{
Name: "corsdomain",
Usage: "Domain on which to send Access-Control-Allow-Origin header (multiple domains can be supplied separated by a ',')",
}
)
var defaultBootnodes = []string{}
func init() {
// Override flag defaults so bzzd can run alongside geth.
utils.ListenPortFlag.Value = 30399
@@ -96,8 +125,39 @@ func init() {
utils.IPCApiFlag.Value = "admin, bzz, chequebook, debug, rpc, web3"
// Set up the cli app.
app.Commands = nil
app.Action = bzzd
app.HideVersion = true // we have a command to print the version
app.Copyright = "Copyright 2013-2016 The go-ethereum Authors"
app.Commands = []cli.Command{
{
Action: version,
Name: "version",
Usage: "Print version numbers",
ArgsUsage: " ",
Description: `
The output of this command is supposed to be machine-readable.
`,
},
{
Action: upload,
Name: "up",
Usage: "upload a file or directory to swarm using the HTTP API",
ArgsUsage: " <file>",
Description: `
"upload a file or directory to swarm using the HTTP API and prints the root hash",
`,
},
{
Action: hash,
Name: "hash",
Usage: "print the swarm hash of a file or directory",
ArgsUsage: " <file>",
Description: `
Prints the swarm hash of file or directory.
`,
},
}
app.Flags = []cli.Flag{
utils.IdentityFlag,
utils.DataDirFlag,
@@ -115,14 +175,20 @@ func init() {
utils.IPCApiFlag,
utils.IPCPathFlag,
// bzzd-specific flags
EthAPI,
CorsStringFlag,
EthAPIFlag,
SwarmConfigPathFlag,
SwarmSwapEnabled,
SwarmSyncEnabled,
SwarmSwapEnabledFlag,
SwarmSyncEnabledFlag,
SwarmPortFlag,
SwarmAccountFlag,
SwarmNetworkIdFlag,
ChequebookAddrFlag,
// upload flags
SwarmApiFlag,
SwarmRecursiveUploadFlag,
SwarmWantManifestFlag,
SwarmUploadDefaultPath,
}
app.Flags = append(app.Flags, debug.Flags...)
app.Before = func(ctx *cli.Context) error {
@@ -142,17 +208,33 @@ func main() {
}
}
func version(ctx *cli.Context) error {
fmt.Println(strings.Title(clientIdentifier))
fmt.Println("Version:", versionString)
if gitCommit != "" {
fmt.Println("Git Commit:", gitCommit)
}
fmt.Println("Network Id:", ctx.GlobalInt(utils.NetworkIdFlag.Name))
fmt.Println("Go Version:", runtime.Version())
fmt.Println("OS:", runtime.GOOS)
fmt.Printf("GOPATH=%s\n", os.Getenv("GOPATH"))
fmt.Printf("GOROOT=%s\n", runtime.GOROOT())
return nil
}
func bzzd(ctx *cli.Context) error {
stack := utils.MakeNode(ctx, clientIdentifier, gitCommit)
registerBzzService(ctx, stack)
utils.StartNode(stack)
networkId := ctx.GlobalUint64(SwarmNetworkIdFlag.Name)
// Add bootnodes as initial peers.
if ctx.GlobalIsSet(utils.BootnodesFlag.Name) {
bootnodes := strings.Split(ctx.GlobalString(utils.BootnodesFlag.Name), ",")
injectBootnodes(stack.Server(), bootnodes)
} else {
injectBootnodes(stack.Server(), defaultBootnodes)
if networkId == 3 {
injectBootnodes(stack.Server(), testbetBootNodes)
}
}
stack.Wait()
@@ -175,22 +257,21 @@ func registerBzzService(ctx *cli.Context, stack *node.Node) {
if len(bzzport) > 0 {
bzzconfig.Port = bzzport
}
swapEnabled := ctx.GlobalBool(SwarmSwapEnabled.Name)
syncEnabled := ctx.GlobalBoolT(SwarmSyncEnabled.Name)
swapEnabled := ctx.GlobalBool(SwarmSwapEnabledFlag.Name)
syncEnabled := ctx.GlobalBoolT(SwarmSyncEnabledFlag.Name)
ethapi := ctx.GlobalString(EthAPI.Name)
ethapi := ctx.GlobalString(EthAPIFlag.Name)
cors := ctx.GlobalString(CorsStringFlag.Name)
boot := func(ctx *node.ServiceContext) (node.Service, error) {
var client *ethclient.Client
if ethapi == "" {
err = fmt.Errorf("use ethapi flag to connect to a an eth client and talk to the blockchain")
} else {
if len(ethapi) > 0 {
client, err = ethclient.Dial(ethapi)
if err != nil {
utils.Fatalf("Can't connect: %v", err)
}
}
if err != nil {
utils.Fatalf("Can't connect: %v", err)
}
return swarm.NewSwarm(ctx, client, bzzconfig, swapEnabled, syncEnabled)
return swarm.NewSwarm(ctx, client, bzzconfig, swapEnabled, syncEnabled, cors)
}
if err := stack.Register(boot); err != nil {
utils.Fatalf("Failed to register the Swarm service: %v", err)

231
cmd/swarm/upload.go Normal file
View File

@@ -0,0 +1,231 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
// Command bzzup uploads files to the swarm HTTP API.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"mime"
"net/http"
"os"
"os/user"
"path"
"path/filepath"
"strings"
"gopkg.in/urfave/cli.v1"
)
func upload(ctx *cli.Context) {
args := ctx.Args()
var (
bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
recursive = ctx.GlobalBool(SwarmRecursiveUploadFlag.Name)
wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
defaultPath = ctx.GlobalString(SwarmUploadDefaultPath.Name)
)
if len(args) != 1 {
log.Fatal("need filename as the first and only argument")
}
var (
file = args[0]
client = &client{api: bzzapi}
)
fi, err := os.Stat(expandPath(file))
if err != nil {
log.Fatal(err)
}
if fi.IsDir() {
if !recursive {
log.Fatal("argument is a directory and recursive upload is disabled")
}
if !wantManifest {
log.Fatal("manifest is required for directory uploads")
}
mhash, err := client.uploadDirectory(file, defaultPath)
if err != nil {
log.Fatal(err)
}
fmt.Println(mhash)
return
}
entry, err := client.uploadFile(file, fi)
if err != nil {
log.Fatalln("upload failed:", err)
}
mroot := manifest{[]manifestEntry{entry}}
if !wantManifest {
// Print the manifest. This is the only output to stdout.
mrootJSON, _ := json.MarshalIndent(mroot, "", " ")
fmt.Println(string(mrootJSON))
return
}
hash, err := client.uploadManifest(mroot)
if err != nil {
log.Fatalln("manifest upload failed:", err)
}
fmt.Println(hash)
}
// Expands a file path
// 1. replace tilde with users home dir
// 2. expands embedded environment variables
// 3. cleans the path, e.g. /a/b/../c -> /a/c
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
func expandPath(p string) string {
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
if home := homeDir(); home != "" {
p = home + p[1:]
}
}
return path.Clean(os.ExpandEnv(p))
}
func homeDir() string {
if home := os.Getenv("HOME"); home != "" {
return home
}
if usr, err := user.Current(); err == nil {
return usr.HomeDir
}
return ""
}
// client wraps interaction with the swarm HTTP gateway.
type client struct {
api string
}
// manifest is the JSON representation of a swarm manifest.
type manifestEntry struct {
Hash string `json:"hash,omitempty"`
ContentType string `json:"contentType,omitempty"`
Path string `json:"path,omitempty"`
}
// manifest is the JSON representation of a swarm manifest.
type manifest struct {
Entries []manifestEntry `json:"entries,omitempty"`
}
func (c *client) uploadDirectory(dir string, defaultPath string) (string, error) {
mhash, err := c.postRaw("application/json", 2, ioutil.NopCloser(bytes.NewReader([]byte("{}"))))
if err != nil {
return "", fmt.Errorf("failed to upload empty manifest")
}
if len(defaultPath) > 0 {
fi, err := os.Stat(defaultPath)
if err != nil {
return "", err
}
mhash, err = c.uploadToManifest(mhash, "", defaultPath, fi)
if err != nil {
return "", err
}
}
prefix := filepath.ToSlash(filepath.Clean(dir)) + "/"
err = filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
if err != nil || fi.IsDir() {
return err
}
if !strings.HasPrefix(path, dir) {
return fmt.Errorf("path %s outside directory %s", path, dir)
}
uripath := strings.TrimPrefix(filepath.ToSlash(filepath.Clean(path)), prefix)
mhash, err = c.uploadToManifest(mhash, uripath, path, fi)
return err
})
return mhash, err
}
func (c *client) uploadFile(file string, fi os.FileInfo) (manifestEntry, error) {
hash, err := c.uploadFileContent(file, fi)
m := manifestEntry{
Hash: hash,
ContentType: mime.TypeByExtension(filepath.Ext(fi.Name())),
}
return m, err
}
func (c *client) uploadFileContent(file string, fi os.FileInfo) (string, error) {
fd, err := os.Open(file)
if err != nil {
return "", err
}
defer fd.Close()
log.Printf("uploading file %s (%d bytes)", file, fi.Size())
return c.postRaw("application/octet-stream", fi.Size(), fd)
}
func (c *client) uploadManifest(m manifest) (string, error) {
jsm, err := json.Marshal(m)
if err != nil {
panic(err)
}
log.Println("uploading manifest")
return c.postRaw("application/json", int64(len(jsm)), ioutil.NopCloser(bytes.NewReader(jsm)))
}
func (c *client) uploadToManifest(mhash string, path string, fpath string, fi os.FileInfo) (string, error) {
fd, err := os.Open(fpath)
if err != nil {
return "", err
}
defer fd.Close()
log.Printf("uploading file %s (%d bytes) and adding path %v", fpath, fi.Size(), path)
req, err := http.NewRequest("PUT", c.api+"/bzz:/"+mhash+"/"+path, fd)
if err != nil {
return "", err
}
req.Header.Set("content-type", mime.TypeByExtension(filepath.Ext(fi.Name())))
req.ContentLength = fi.Size()
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
return "", fmt.Errorf("bad status: %s", resp.Status)
}
content, err := ioutil.ReadAll(resp.Body)
return string(content), err
}
func (c *client) postRaw(mimetype string, size int64, body io.ReadCloser) (string, error) {
req, err := http.NewRequest("POST", c.api+"/bzzr:/", body)
if err != nil {
return "", err
}
req.Header.Set("content-type", mimetype)
req.ContentLength = size
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode >= 400 {
return "", fmt.Errorf("bad status: %s", resp.Status)
}
content, err := ioutil.ReadAll(resp.Body)
return string(content), err
}

View File

@@ -18,12 +18,14 @@
package utils
import (
"compress/gzip"
"fmt"
"io"
"os"
"os/signal"
"regexp"
"runtime"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
@@ -65,7 +67,6 @@ func Fatalf(format string, args ...interface{}) {
}
}
fmt.Fprintf(w, "Fatal: "+format+"\n", args...)
logger.Flush()
os.Exit(1)
}
@@ -93,7 +94,7 @@ func StartNode(stack *node.Node) {
func FormatTransactionData(data string) []byte {
d := common.StringToByteFunc(data, func(s string) (ret []byte) {
slice := regexp.MustCompile("\\n|\\s").Split(s, 1000000000)
slice := regexp.MustCompile(`\n|\s`).Split(s, 1000000000)
for _, dataItem := range slice {
d := common.FormatData(dataItem)
ret = append(ret, d...)
@@ -133,7 +134,15 @@ func ImportChain(chain *core.BlockChain, fn string) error {
return err
}
defer fh.Close()
stream := rlp.NewStream(fh, 0)
var reader io.Reader = fh
if strings.HasSuffix(fn, ".gz") {
if reader, err = gzip.NewReader(reader); err != nil {
return err
}
}
stream := rlp.NewStream(reader, 0)
// Run actual the import.
blocks := make(types.Blocks, importBatchSize)
@@ -195,10 +204,18 @@ func ExportChain(blockchain *core.BlockChain, fn string) error {
return err
}
defer fh.Close()
if err := blockchain.Export(fh); err != nil {
var writer io.Writer = fh
if strings.HasSuffix(fn, ".gz") {
writer = gzip.NewWriter(writer)
defer writer.(*gzip.Writer).Close()
}
if err := blockchain.Export(writer); err != nil {
return err
}
glog.Infoln("Exported blockchain to ", fn)
return nil
}
@@ -210,7 +227,14 @@ func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, las
return err
}
defer fh.Close()
if err := blockchain.ExportN(fh, first, last); err != nil {
var writer io.Writer = fh
if strings.HasSuffix(fn, ".gz") {
writer = gzip.NewWriter(writer)
defer writer.(*gzip.Writer).Close()
}
if err := blockchain.ExportN(writer, first, last); err != nil {
return err
}
glog.Infoln("Exported blockchain to ", fn)

View File

@@ -23,8 +23,6 @@ import (
"os/user"
"path"
"strings"
"gopkg.in/urfave/cli.v1"
)
// Custom type which is registered in the flags library which cli uses for
@@ -46,7 +44,6 @@ func (self *DirectoryString) Set(value string) error {
// Custom cli.Flag type which expand the received string to an absolute path.
// e.g. ~/.ethereum -> /home/username/.ethereum
type DirectoryFlag struct {
cli.GenericFlag
Name string
Value DirectoryString
Usage string
@@ -54,15 +51,10 @@ type DirectoryFlag struct {
}
func (self DirectoryFlag) String() string {
var fmtString string
fmtString = "%s %v\t%v"
fmtString := "%s %v\t%v"
if len(self.Value.Value) > 0 {
fmtString = "%s \"%v\"\t%v"
} else {
fmtString = "%s %v\t%v"
}
return withEnvHint(self.EnvVar, fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage))
}
@@ -122,7 +114,7 @@ func withEnvHint(envVar, str string) string {
return str + envText
}
func (self DirectoryFlag) getName() string {
func (self DirectoryFlag) GetName() string {
return self.Name
}

View File

@@ -21,7 +21,6 @@ import (
"crypto/ecdsa"
"fmt"
"io/ioutil"
"math"
"math/big"
"os"
"path/filepath"
@@ -116,16 +115,12 @@ var (
}
NetworkIdFlag = cli.IntFlag{
Name: "networkid",
Usage: "Network identifier (integer, 0=Olympic (disused), 1=Frontier, 2=Morden (disused), 3=Ropsten)",
Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten)",
Value: eth.NetworkId,
}
OlympicFlag = cli.BoolFlag{
Name: "olympic",
Usage: "Olympic network: pre-configured pre-release test network",
}
TestNetFlag = cli.BoolFlag{
Name: "testnet",
Usage: "Morden network: pre-configured test network with modified starting nonces (replay protection)",
Usage: "Ropsten network: pre-configured test network",
}
DevModeFlag = cli.BoolFlag{
Name: "dev",
@@ -177,15 +172,6 @@ var (
Usage: "Number of trie node generations to keep in memory",
Value: int(state.MaxTrieCacheGen),
}
// Fork settings
SupportDAOFork = cli.BoolFlag{
Name: "support-dao-fork",
Usage: "Updates the chain rules to support the DAO hard-fork",
}
OpposeDAOFork = cli.BoolFlag{
Name: "oppose-dao-fork",
Usage: "Updates the chain rules to oppose the DAO hard-fork",
}
// Miner settings
MiningEnabledFlag = cli.BoolFlag{
Name: "mine",
@@ -494,17 +480,15 @@ func makeNodeUserIdent(ctx *cli.Context) string {
// MakeBootstrapNodes creates a list of bootstrap nodes from the command line
// flags, reverting to pre-configured ones if none have been specified.
func MakeBootstrapNodes(ctx *cli.Context) []*discover.Node {
// Return pre-configured nodes if none were manually requested
if !ctx.GlobalIsSet(BootnodesFlag.Name) {
if ctx.GlobalBool(TestNetFlag.Name) {
return params.TestnetBootnodes
}
return params.MainnetBootnodes
urls := params.MainnetBootnodes
if ctx.GlobalIsSet(BootnodesFlag.Name) {
urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
} else if ctx.GlobalBool(TestNetFlag.Name) {
urls = params.TestnetBootnodes
}
// Otherwise parse and use the CLI bootstrap nodes
bootnodes := []*discover.Node{}
for _, url := range strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") {
bootnodes := make([]*discover.Node, 0, len(urls))
for _, url := range urls {
node, err := discover.ParseNode(url)
if err != nil {
glog.V(logger.Error).Infof("Bootstrap URL %s: %v\n", url, err)
@@ -518,14 +502,13 @@ func MakeBootstrapNodes(ctx *cli.Context) []*discover.Node {
// MakeBootstrapNodesV5 creates a list of bootstrap nodes from the command line
// flags, reverting to pre-configured ones if none have been specified.
func MakeBootstrapNodesV5(ctx *cli.Context) []*discv5.Node {
// Return pre-configured nodes if none were manually requested
if !ctx.GlobalIsSet(BootnodesFlag.Name) {
return params.DiscoveryV5Bootnodes
urls := params.DiscoveryV5Bootnodes
if ctx.GlobalIsSet(BootnodesFlag.Name) {
urls = strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",")
}
// Otherwise parse and use the CLI bootstrap nodes
bootnodes := []*discv5.Node{}
for _, url := range strings.Split(ctx.GlobalString(BootnodesFlag.Name), ",") {
bootnodes := make([]*discv5.Node, 0, len(urls))
for _, url := range urls {
node, err := discv5.ParseNode(url)
if err != nil {
glog.V(logger.Error).Infof("Bootstrap URL %s: %v\n", url, err)
@@ -724,7 +707,7 @@ func MakeNode(ctx *cli.Context, name, gitCommit string) *node.Node {
// given node.
func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
// Avoid conflicting network flags
networks, netFlags := 0, []cli.BoolFlag{DevModeFlag, TestNetFlag, OlympicFlag}
networks, netFlags := 0, []cli.BoolFlag{DevModeFlag, TestNetFlag}
for _, flag := range netFlags {
if ctx.GlobalBool(flag.Name) {
networks++
@@ -762,12 +745,6 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
// Override any default configs in dev mode or the test net
switch {
case ctx.GlobalBool(OlympicFlag.Name):
if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
ethConf.NetworkId = 1
}
ethConf.Genesis = core.OlympicGenesisBlock()
case ctx.GlobalBool(TestNetFlag.Name):
if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
ethConf.NetworkId = 3
@@ -775,7 +752,7 @@ func RegisterEthService(ctx *cli.Context, stack *node.Node, extra []byte) {
ethConf.Genesis = core.DefaultTestnetGenesisBlock()
case ctx.GlobalBool(DevModeFlag.Name):
ethConf.Genesis = core.OlympicGenesisBlock()
ethConf.Genesis = core.DevGenesisBlock()
if !ctx.GlobalIsSet(GasPriceFlag.Name) {
ethConf.GasPrice = new(big.Int)
}
@@ -832,16 +809,6 @@ func RegisterEthStatsService(stack *node.Node, url string) {
// SetupNetwork configures the system for either the main net or some test network.
func SetupNetwork(ctx *cli.Context) {
switch {
case ctx.GlobalBool(OlympicFlag.Name):
params.DurationLimit = big.NewInt(8)
params.GenesisGasLimit = big.NewInt(3141592)
params.MinGasLimit = big.NewInt(125000)
params.MaximumExtraDataSize = big.NewInt(1024)
NetworkIdFlag.Value = 0
core.BlockReward = big.NewInt(1.5e+18)
core.ExpDiffPeriod = big.NewInt(math.MaxInt64)
}
params.TargetGasLimit = common.String2Big(ctx.GlobalString(TargetGasLimitFlag.Name))
}
@@ -901,13 +868,6 @@ func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *params.ChainCon
config.ChainId = params.MainNetChainID
}
}
// Force override any existing configs if explicitly requested
switch {
case ctx.GlobalBool(SupportDAOFork.Name):
config.DAOForkSupport = true
case ctx.GlobalBool(OpposeDAOFork.Name):
config.DAOForkSupport = false
}
return config
}
@@ -939,12 +899,13 @@ func MakeChain(ctx *cli.Context, stack *node.Node) (chain *core.BlockChain, chai
var err error
chainDb = MakeChainDatabase(ctx, stack)
if ctx.GlobalBool(OlympicFlag.Name) {
if ctx.GlobalBool(TestNetFlag.Name) {
_, err := core.WriteTestNetGenesisBlock(chainDb)
if err != nil {
glog.Fatalln(err)
}
}
chainConfig := MakeChainConfigFromDb(ctx, chainDb)
pow := pow.PoW(core.FakePow{})

View File

@@ -27,7 +27,7 @@ func TestMisc(t *testing.T) {
c := []byte{1, 2, 3, 4}
z := BitTest(a, 1)
if z != true {
if !z {
t.Error("Expected true got", z)
}
@@ -79,11 +79,11 @@ func TestBigCopy(t *testing.T) {
z := BigToBytes(c, 16)
zbytes := []byte{232, 212, 165, 16, 0}
if bytes.Compare(y, ybytes) != 0 {
if !bytes.Equal(y, ybytes) {
t.Error("Got", ybytes)
}
if bytes.Compare(z, zbytes) != 0 {
if !bytes.Equal(z, zbytes) {
t.Error("Got", zbytes)
}
}

View File

@@ -143,7 +143,7 @@ func Hex2BytesFixed(str string, flen int) []byte {
return h
} else {
if len(h) > flen {
return h[len(h)-flen : len(h)]
return h[len(h)-flen:]
} else {
hh := make([]byte, flen)
copy(hh[flen-len(h):flen], h[:])

View File

@@ -181,7 +181,7 @@ func TestFromHex(t *testing.T) {
input := "0x01"
expected := []byte{1}
result := FromHex(input)
if bytes.Compare(expected, result) != 0 {
if !bytes.Equal(expected, result) {
t.Errorf("Expected % x got % x", expected, result)
}
}
@@ -190,7 +190,7 @@ func TestFromHexOddLength(t *testing.T) {
input := "0x1"
expected := []byte{1}
result := FromHex(input)
if bytes.Compare(expected, result) != 0 {
if !bytes.Equal(expected, result) {
t.Errorf("Expected % x got % x", expected, result)
}
}

View File

@@ -22,9 +22,7 @@ import (
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"regexp"
"strings"
@@ -34,7 +32,7 @@ import (
)
var (
versionRegexp = regexp.MustCompile("[0-9]+\\.[0-9]+\\.[0-9]+")
versionRegexp = regexp.MustCompile(`[0-9]+\.[0-9]+\.[0-9]+`)
solcParams = []string{
"--combined-json", "bin,abi,userdoc,devdoc",
"--add-std", // include standard lib contracts
@@ -96,27 +94,16 @@ func CompileSolidityString(solc, source string) (map[string]*Contract, error) {
if solc == "" {
solc = "solc"
}
// Write source to a temporary file. Compiling stdin used to be supported
// but seems to produce an exception with solc 0.3.5.
infile, err := ioutil.TempFile("", "geth-compile-solidity")
if err != nil {
return nil, err
}
defer os.Remove(infile.Name())
if _, err := io.WriteString(infile, source); err != nil {
return nil, err
}
if err := infile.Close(); err != nil {
return nil, err
}
return CompileSolidity(solc, infile.Name())
args := append(solcParams, "--")
cmd := exec.Command(solc, append(args, "-")...)
cmd.Stdin = strings.NewReader(source)
return runsolc(cmd, source)
}
// CompileSolidity compiles all given Solidity source files.
func CompileSolidity(solc string, sourcefiles ...string) (map[string]*Contract, error) {
if len(sourcefiles) == 0 {
return nil, errors.New("solc: no source ")
return nil, errors.New("solc: no source files")
}
source, err := slurpFiles(sourcefiles)
if err != nil {
@@ -125,10 +112,13 @@ func CompileSolidity(solc string, sourcefiles ...string) (map[string]*Contract,
if solc == "" {
solc = "solc"
}
var stderr, stdout bytes.Buffer
args := append(solcParams, "--")
cmd := exec.Command(solc, append(args, sourcefiles...)...)
return runsolc(cmd, source)
}
func runsolc(cmd *exec.Cmd, source string) (map[string]*Contract, error) {
var stderr, stdout bytes.Buffer
cmd.Stderr = &stderr
cmd.Stdout = &stdout
if err := cmd.Run(); err != nil {

View File

@@ -20,6 +20,7 @@ import (
"encoding/json"
"io/ioutil"
"os"
"os/exec"
"path"
"testing"
@@ -27,8 +28,7 @@ import (
)
const (
supportedSolcVersion = "0.3.5"
testSource = `
testSource = `
contract test {
/// @notice Will multiply ` + "`a`" + ` by 7.
function multiply(uint a) returns(uint d) {
@@ -36,23 +36,18 @@ contract test {
}
}
`
testCode = "0x6060604052602a8060106000396000f3606060405260e060020a6000350463c6888fa18114601a575b005b6007600435026060908152602090f3"
testInfo = `{"source":"\ncontract test {\n /// @notice Will multiply ` + "`a`" + ` by 7.\n function multiply(uint a) returns(uint d) {\n return a * 7;\n }\n}\n","language":"Solidity","languageVersion":"0.1.1","compilerVersion":"0.1.1","compilerOptions":"--binary file --json-abi file --natspec-user file --natspec-dev file --add-std 1","abiDefinition":[{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"type":"function"}],"userDoc":{"methods":{"multiply(uint256)":{"notice":"Will multiply ` + "`a`" + ` by 7."}}},"developerDoc":{"methods":{}}}`
)
func skipUnsupported(t *testing.T) {
sol, err := SolidityVersion("")
if err != nil {
func skipWithoutSolc(t *testing.T) {
if _, err := exec.LookPath("solc"); err != nil {
t.Skip(err)
return
}
if sol.Version != supportedSolcVersion {
t.Skipf("unsupported version of solc found (%v, expect %v)", sol.Version, supportedSolcVersion)
}
}
func TestCompiler(t *testing.T) {
skipUnsupported(t)
skipWithoutSolc(t)
contracts, err := CompileSolidityString("", testSource)
if err != nil {
t.Fatalf("error compiling source. result %v: %v", contracts, err)
@@ -64,19 +59,20 @@ func TestCompiler(t *testing.T) {
if !ok {
t.Fatal("info for contract 'test' not present in result")
}
if c.Code != testCode {
t.Errorf("wrong code: expected\n%s, got\n%s", testCode, c.Code)
if c.Code == "" {
t.Error("empty code")
}
if c.Info.Source != testSource {
t.Error("wrong source")
}
if c.Info.CompilerVersion != supportedSolcVersion {
t.Errorf("wrong version: expected %q, got %q", supportedSolcVersion, c.Info.CompilerVersion)
if c.Info.CompilerVersion == "" {
t.Error("empty version")
}
}
func TestCompileError(t *testing.T) {
skipUnsupported(t)
skipWithoutSolc(t)
contracts, err := CompileSolidityString("", testSource[4:])
if err == nil {
t.Errorf("error expected compiling source. got none. result %v", contracts)

View File

@@ -27,7 +27,7 @@ import (
// the unnecessary precision off from the formatted textual representation.
type PrettyDuration time.Duration
var prettyDurationRe = regexp.MustCompile("\\.[0-9]+")
var prettyDurationRe = regexp.MustCompile(`\.[0-9]+`)
// String implements the Stringer interface, allowing pretty printing of duration
// values rounded to three decimals.

View File

@@ -169,12 +169,7 @@ func EncodeBig(bigint *big.Int) string {
if nbits == 0 {
return "0x0"
}
enc := make([]byte, 2, (nbits/8)*2+2)
copy(enc, "0x")
for i := len(bigint.Bits()) - 1; i >= 0; i-- {
enc = strconv.AppendUint(enc, uint64(bigint.Bits()[i]), 16)
}
return string(enc)
return fmt.Sprintf("0x%x", bigint)
}
func has0xPrefix(input string) bool {

View File

@@ -46,6 +46,7 @@ var (
{referenceBig("1"), "0x1"},
{referenceBig("ff"), "0xff"},
{referenceBig("112233445566778899aabbccddeeff"), "0x112233445566778899aabbccddeeff"},
{referenceBig("80a7f2c1bcc396c00"), "0x80a7f2c1bcc396c00"},
}
encodeUint64Tests = []marshalTest{

View File

@@ -109,13 +109,8 @@ func (b *Big) MarshalJSON() ([]byte, error) {
if nbits == 0 {
return jsonZero, nil
}
enc := make([]byte, 3, (nbits/8)*2+4)
copy(enc, `"0x`)
for i := len(bigint.Bits()) - 1; i >= 0; i-- {
enc = strconv.AppendUint(enc, uint64(bigint.Bits()[i]), 16)
}
enc = append(enc, '"')
return enc, nil
enc := fmt.Sprintf(`"0x%x"`, bigint)
return []byte(enc), nil
}
// UnmarshalJSON implements json.Unmarshaler.
@@ -237,7 +232,7 @@ func checkJSON(input []byte) (raw []byte, err error) {
return nil, errNonString
}
if len(input) == 2 {
return nil, ErrEmptyString
return nil, nil // empty strings are allowed
}
if !bytesHave0xPrefix(input[1:]) {
return nil, ErrMissingPrefix
@@ -255,7 +250,7 @@ func checkNumberJSON(input []byte) (raw []byte, err error) {
}
input = input[1 : len(input)-1]
if len(input) == 0 {
return nil, ErrEmptyString
return nil, nil // empty strings are allowed
}
if !bytesHave0xPrefix(input) {
return nil, ErrMissingPrefix

View File

@@ -60,13 +60,13 @@ var unmarshalBytesTests = []unmarshalTest{
{input: "", wantErr: errNonString},
{input: "null", wantErr: errNonString},
{input: "10", wantErr: errNonString},
{input: `""`, wantErr: ErrEmptyString},
{input: `"0"`, wantErr: ErrMissingPrefix},
{input: `"0x0"`, wantErr: ErrOddLength},
{input: `"0xxx"`, wantErr: ErrSyntax},
{input: `"0x01zz01"`, wantErr: ErrSyntax},
// valid encoding
{input: `""`, want: referenceBytes("")},
{input: `"0x"`, want: referenceBytes("")},
{input: `"0x02"`, want: referenceBytes("02")},
{input: `"0X02"`, want: referenceBytes("02")},
@@ -125,7 +125,6 @@ var unmarshalBigTests = []unmarshalTest{
{input: "", wantErr: errNonString},
{input: "null", wantErr: errNonString},
{input: "10", wantErr: errNonString},
{input: `""`, wantErr: ErrEmptyString},
{input: `"0"`, wantErr: ErrMissingPrefix},
{input: `"0x"`, wantErr: ErrEmptyNumber},
{input: `"0x01"`, wantErr: ErrLeadingZero},
@@ -133,6 +132,7 @@ var unmarshalBigTests = []unmarshalTest{
{input: `"0x1zz01"`, wantErr: ErrSyntax},
// valid encoding
{input: `""`, want: big.NewInt(0)},
{input: `"0x0"`, want: big.NewInt(0)},
{input: `"0x2"`, want: big.NewInt(0x2)},
{input: `"0x2F2"`, want: big.NewInt(0x2f2)},
@@ -198,7 +198,6 @@ var unmarshalUint64Tests = []unmarshalTest{
{input: "", wantErr: errNonString},
{input: "null", wantErr: errNonString},
{input: "10", wantErr: errNonString},
{input: `""`, wantErr: ErrEmptyString},
{input: `"0"`, wantErr: ErrMissingPrefix},
{input: `"0x"`, wantErr: ErrEmptyNumber},
{input: `"0x01"`, wantErr: ErrLeadingZero},
@@ -207,6 +206,7 @@ var unmarshalUint64Tests = []unmarshalTest{
{input: `"0x1zz01"`, wantErr: ErrSyntax},
// valid encoding
{input: `""`, want: uint64(0)},
{input: `"0x0"`, want: uint64(0)},
{input: `"0x2"`, want: uint64(0x2)},
{input: `"0x2F2"`, want: uint64(0x2f2)},

View File

@@ -41,24 +41,24 @@ func TestSum(t *testing.T) {
func TestDist(t *testing.T) {
var vectors = []Vector{
Vector{big.NewInt(1000), big.NewInt(1234)},
Vector{big.NewInt(500), big.NewInt(10023)},
Vector{big.NewInt(1034), big.NewInt(1987)},
Vector{big.NewInt(1034), big.NewInt(1987)},
Vector{big.NewInt(8983), big.NewInt(1977)},
Vector{big.NewInt(98382), big.NewInt(1887)},
Vector{big.NewInt(12398), big.NewInt(1287)},
Vector{big.NewInt(12398), big.NewInt(1487)},
Vector{big.NewInt(12398), big.NewInt(1987)},
Vector{big.NewInt(12398), big.NewInt(128)},
Vector{big.NewInt(12398), big.NewInt(1987)},
Vector{big.NewInt(1398), big.NewInt(187)},
Vector{big.NewInt(12328), big.NewInt(1927)},
Vector{big.NewInt(12398), big.NewInt(1987)},
Vector{big.NewInt(22398), big.NewInt(1287)},
Vector{big.NewInt(1370), big.NewInt(1981)},
Vector{big.NewInt(12398), big.NewInt(1957)},
Vector{big.NewInt(42198), big.NewInt(1987)},
{big.NewInt(1000), big.NewInt(1234)},
{big.NewInt(500), big.NewInt(10023)},
{big.NewInt(1034), big.NewInt(1987)},
{big.NewInt(1034), big.NewInt(1987)},
{big.NewInt(8983), big.NewInt(1977)},
{big.NewInt(98382), big.NewInt(1887)},
{big.NewInt(12398), big.NewInt(1287)},
{big.NewInt(12398), big.NewInt(1487)},
{big.NewInt(12398), big.NewInt(1987)},
{big.NewInt(12398), big.NewInt(128)},
{big.NewInt(12398), big.NewInt(1987)},
{big.NewInt(1398), big.NewInt(187)},
{big.NewInt(12328), big.NewInt(1927)},
{big.NewInt(12398), big.NewInt(1987)},
{big.NewInt(22398), big.NewInt(1287)},
{big.NewInt(1370), big.NewInt(1981)},
{big.NewInt(12398), big.NewInt(1957)},
{big.NewInt(42198), big.NewInt(1987)},
}
VectorsBy(GasSort).Sort(vectors)

View File

@@ -76,9 +76,9 @@ func compressChunk(dat []byte) (ret []byte, n int) {
}
return []byte{token, byte(j + 2)}, j
case len(dat) >= 32:
if dat[0] == empty[0] && bytes.Compare(dat[:32], empty) == 0 {
if dat[0] == empty[0] && bytes.Equal(dat[:32], empty) {
return []byte{token, emptyShaToken}, 32
} else if dat[0] == emptyList[0] && bytes.Compare(dat[:32], emptyList) == 0 {
} else if dat[0] == emptyList[0] && bytes.Equal(dat[:32], emptyList) {
return []byte{token, emptyListShaToken}, 32
}
fallthrough

View File

@@ -46,7 +46,7 @@ func newBridge(client *rpc.Client, prompter UserPrompter, printer io.Writer) *br
}
// NewAccount is a wrapper around the personal.newAccount RPC method that uses a
// non-echoing password prompt to aquire the passphrase and executes the original
// non-echoing password prompt to acquire the passphrase and executes the original
// RPC method (saved in jeth.newAccount) with it to actually execute the RPC call.
func (b *bridge) NewAccount(call otto.FunctionCall) (response otto.Value) {
var (
@@ -75,7 +75,7 @@ func (b *bridge) NewAccount(call otto.FunctionCall) (response otto.Value) {
default:
throwJSException("expected 0 or 1 string argument")
}
// Password aquired, execute the call and return
// Password acquired, execute the call and return
ret, err := call.Otto.Call("jeth.newAccount", nil, password)
if err != nil {
throwJSException(err.Error())
@@ -84,7 +84,7 @@ func (b *bridge) NewAccount(call otto.FunctionCall) (response otto.Value) {
}
// UnlockAccount is a wrapper around the personal.unlockAccount RPC method that
// uses a non-echoing password prompt to aquire the passphrase and executes the
// uses a non-echoing password prompt to acquire the passphrase and executes the
// original RPC method (saved in jeth.unlockAccount) with it to actually execute
// the RPC call.
func (b *bridge) UnlockAccount(call otto.FunctionCall) (response otto.Value) {
@@ -127,7 +127,7 @@ func (b *bridge) UnlockAccount(call otto.FunctionCall) (response otto.Value) {
}
// Sign is a wrapper around the personal.sign RPC method that uses a non-echoing password
// prompt to aquire the passphrase and executes the original RPC method (saved in
// prompt to acquire the passphrase and executes the original RPC method (saved in
// jeth.sign) with it to actually execute the RPC call.
func (b *bridge) Sign(call otto.FunctionCall) (response otto.Value) {
var (
@@ -270,18 +270,15 @@ func (b *bridge) Send(call otto.FunctionCall) (response otto.Value) {
} else {
resultVal, err := JSON.Call("parse", string(result))
if err != nil {
resp = newErrorResponse(call, -32603, err.Error(), &req.Id).Object()
setError(resp, -32603, err.Error())
} else {
resp.Set("result", resultVal)
}
}
case rpc.Error:
resp.Set("error", map[string]interface{}{
"code": err.ErrorCode(),
"message": err.Error(),
})
setError(resp, err.ErrorCode(), err.Error())
default:
resp = newErrorResponse(call, -32603, err.Error(), &req.Id).Object()
setError(resp, -32603, err.Error())
}
resps.Call("push", resp)
}
@@ -300,12 +297,8 @@ func (b *bridge) Send(call otto.FunctionCall) (response otto.Value) {
return response
}
func newErrorResponse(call otto.FunctionCall, code int, msg string, id interface{}) otto.Value {
// Bundle the error into a JSON RPC call response
m := map[string]interface{}{"version": "2.0", "id": id, "error": map[string]interface{}{"code": code, msg: msg}}
res, _ := json.Marshal(m)
val, _ := call.Otto.Run("(" + string(res) + ")")
return val
func setError(resp *otto.Object, code int, msg string) {
resp.Set("error", map[string]interface{}{"code": code, "message": msg})
}
// throwJSException panics on an otto.Value. The Otto VM will recover from the

View File

@@ -36,9 +36,9 @@ import (
)
var (
passwordRegexp = regexp.MustCompile("personal.[nus]")
onlyWhitespace = regexp.MustCompile("^\\s*$")
exit = regexp.MustCompile("^\\s*exit\\s*;*\\s*$")
passwordRegexp = regexp.MustCompile(`personal.[nus]`)
onlyWhitespace = regexp.MustCompile(`^\s*$`)
exit = regexp.MustCompile(`^\s*exit\s*;*\s*$`)
)
// HistoryFile is the file within the data directory to store input scrollback.
@@ -226,8 +226,8 @@ func (c *Console) AutoCompleteInput(line string, pos int) (string, []string, str
}
// Chunck data to relevant part for autocompletion
// E.g. in case of nested lines eth.getBalance(eth.coinb<tab><tab>
start := 0
for start = pos - 1; start > 0; start-- {
start := pos - 1
for ; start > 0; start-- {
// Skip all methods and namespaces (i.e. including te dot)
if line[start] == '.' || (line[start] >= 'a' && line[start] <= 'z') || (line[start] >= 'A' && line[start] <= 'Z') {
continue
@@ -275,10 +275,7 @@ func (c *Console) Evaluate(statement string) error {
fmt.Fprintf(c.printer, "[native] error: %v\n", r)
}
}()
if err := c.jsre.Evaluate(statement, c.printer); err != nil {
return err
}
return nil
return c.jsre.Evaluate(statement, c.printer)
}
// Interactive starts an interactive user session, where input is propted from

View File

@@ -44,7 +44,7 @@ type UserPrompter interface {
PromptConfirm(prompt string) (bool, error)
// SetHistory sets the the input scrollback history that the prompter will allow
// the user to scoll back to.
// the user to scroll back to.
SetHistory(history []string)
// AppendHistory appends an entry to the scrollback history. It should be called
@@ -147,7 +147,7 @@ func (p *terminalPrompter) PromptConfirm(prompt string) (bool, error) {
}
// SetHistory sets the the input scrollback history that the prompter will allow
// the user to scoll back to.
// the user to scroll back to.
func (p *terminalPrompter) SetHistory(history []string) {
p.State.ReadHistory(strings.NewReader(strings.Join(history, "\n")))
}

View File

@@ -252,7 +252,7 @@ func (self *Chequebook) Issue(beneficiary common.Address, amount *big.Int) (ch *
return nil, fmt.Errorf("amount must be greater than zero (%v)", amount)
}
if self.balance.Cmp(amount) < 0 {
err = fmt.Errorf("insufficent funds to issue cheque for amount: %v. balance: %v", amount, self.balance)
err = fmt.Errorf("insufficient funds to issue cheque for amount: %v. balance: %v", amount, self.balance)
} else {
var sig []byte
sent, found := self.sent[beneficiary]
@@ -277,7 +277,7 @@ func (self *Chequebook) Issue(beneficiary common.Address, amount *big.Int) (ch *
}
// auto deposit if threshold is set and balance is less then threshold
// note this is called even if issueing cheque fails
// note this is called even if issuing cheque fails
// so we reattempt depositing
if self.threshold != nil {
if self.balance.Cmp(self.threshold) < 0 {

View File

@@ -73,8 +73,8 @@ func TestIssueAndReceive(t *testing.T) {
}
chbook.sent[addr1] = new(big.Int).SetUint64(42)
amount := common.Big1
ch, err := chbook.Issue(addr1, amount)
if err == nil {
if _, err = chbook.Issue(addr1, amount); err == nil {
t.Fatalf("expected insufficient funds error, got none")
}
@@ -83,7 +83,7 @@ func TestIssueAndReceive(t *testing.T) {
t.Fatalf("expected: %v, got %v", "0", chbook.Balance())
}
ch, err = chbook.Issue(addr1, amount)
ch, err := chbook.Issue(addr1, amount)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
@@ -128,8 +128,8 @@ func TestCheckbookFile(t *testing.T) {
t.Errorf("expected: %v, got %v", "0", chbook.Balance())
}
ch, err := chbook.Issue(addr1, common.Big1)
if err != nil {
var ch *Cheque
if ch, err = chbook.Issue(addr1, common.Big1); err != nil {
t.Fatalf("expected no error, got %v", err)
}
if ch.Amount.Cmp(new(big.Int).SetUint64(43)) != 0 {
@@ -155,7 +155,7 @@ func TestVerifyErrors(t *testing.T) {
}
path1 := filepath.Join(os.TempDir(), "chequebook-test-1.json")
contr1, err := deploy(key1, common.Big2, backend)
contr1, _ := deploy(key1, common.Big2, backend)
chbook1, err := NewChequebook(path1, contr1, key1, backend)
if err != nil {
t.Errorf("expected no error, got %v", err)
@@ -223,7 +223,8 @@ func TestVerifyErrors(t *testing.T) {
func TestDeposit(t *testing.T) {
path0 := filepath.Join(os.TempDir(), "chequebook-test-0.json")
backend := newTestBackend()
contr0, err := deploy(key0, new(big.Int), backend)
contr0, _ := deploy(key0, new(big.Int), backend)
chbook, err := NewChequebook(path0, contr0, key0, backend)
if err != nil {
t.Errorf("expected no error, got %v", err)
@@ -361,7 +362,8 @@ func TestDeposit(t *testing.T) {
func TestCash(t *testing.T) {
path := filepath.Join(os.TempDir(), "chequebook-test.json")
backend := newTestBackend()
contr0, err := deploy(key0, common.Big2, backend)
contr0, _ := deploy(key0, common.Big2, backend)
chbook, err := NewChequebook(path, contr0, key0, backend)
if err != nil {
t.Errorf("expected no error, got %v", err)
@@ -380,11 +382,12 @@ func TestCash(t *testing.T) {
}
// cashing latest cheque
_, err = chbox.Receive(ch)
if err != nil {
if _, err = chbox.Receive(ch); err != nil {
t.Fatalf("expected no error, got %v", err)
}
_, err = ch.Cash(chbook.session)
if _, err = ch.Cash(chbook.session); err != nil {
t.Fatal("Cash failed:", err)
}
backend.Commit()
chbook.balance = new(big.Int).Set(common.Big3)

View File

@@ -29,7 +29,7 @@ import (
var (
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
name = "my name on ENS"
hash = crypto.Sha3Hash([]byte("my content"))
hash = crypto.Keccak256Hash([]byte("my content"))
addr = crypto.PubkeyToAddress(key.PublicKey)
)

View File

@@ -78,7 +78,7 @@ contract ReleaseOracle {
}
// signers is an accessor method to retrieve all te signers (public accessor
// generates an indexed one, not a retreive-all version).
// generates an indexed one, not a retrieve-all version).
function signers() constant returns(address[]) {
return voters;
}
@@ -178,7 +178,7 @@ contract ReleaseOracle {
voters[i] = voters[voters.length - 1];
voters.length--;
delete verProp; // Nuke any version proposal (no suprise releases!)
delete verProp; // Nuke any version proposal (no surprise releases!)
break;
}
}

View File

@@ -83,7 +83,7 @@ func genValueTx(nbytes int) func(int, *BlockGen) {
toaddr := common.Address{}
data := make([]byte, nbytes)
gas := IntrinsicGas(data, false, false)
tx, _ := types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data).SignECDSA(types.HomesteadSigner{}, benchRootKey)
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(benchRootAddr), toaddr, big.NewInt(1), gas, nil, data), types.HomesteadSigner{}, benchRootKey)
gen.AddTx(tx)
}
}
@@ -123,7 +123,7 @@ func genTxRing(naccounts int) func(int, *BlockGen) {
nil,
nil,
)
tx, _ = tx.SignECDSA(types.HomesteadSigner{}, ringKeys[from])
tx, _ = types.SignTx(tx, types.HomesteadSigner{}, ringKeys[from])
gen.AddTx(tx)
from = to
}

View File

@@ -24,11 +24,9 @@ import (
"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/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow/ezp"
)
func testChainConfig() *params.ChainConfig {
@@ -49,20 +47,19 @@ func proc() (Validator, *BlockChain) {
}
func TestNumber(t *testing.T) {
pow := ezp.New()
_, chain := proc()
statedb, _ := state.New(chain.Genesis().Root(), chain.chainDb)
cfg := testChainConfig()
header := makeHeader(cfg, chain.Genesis(), statedb)
header.Number = big.NewInt(3)
err := ValidateHeader(cfg, pow, header, chain.Genesis().Header(), false, false)
err := ValidateHeader(cfg, FakePow{}, header, chain.Genesis().Header(), false, false)
if err != BlockNumberErr {
t.Errorf("expected block number error, got %q", err)
}
header = makeHeader(cfg, chain.Genesis(), statedb)
err = ValidateHeader(cfg, pow, header, chain.Genesis().Header(), false, false)
err = ValidateHeader(cfg, FakePow{}, header, chain.Genesis().Header(), false, false)
if err == BlockNumberErr {
t.Errorf("didn't expect block number error")
}
@@ -77,7 +74,7 @@ func TestPutReceipt(t *testing.T) {
hash[0] = 2
receipt := new(types.Receipt)
receipt.Logs = vm.Logs{&vm.Log{
receipt.Logs = []*types.Log{{
Address: addr,
Topics: []common.Hash{hash},
Data: []byte("hi"),

View File

@@ -29,6 +29,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
@@ -46,9 +47,6 @@ import (
)
var (
chainlogger = logger.NewLogger("CHAIN")
jsonlogger = logger.NewJsonLogger()
blockInsertTimer = metrics.NewTimer("chain/inserts")
ErrNoGenesis = errors.New("Genesis not found in chain")
@@ -150,7 +148,7 @@ func NewBlockChain(chainDb ethdb.Database, config *params.ChainConfig, pow pow.P
return nil, err
}
// 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 BadHashes {
for hash := range BadHashes {
if header := bc.GetHeaderByHash(hash); header != nil {
// get the canonical block corresponding to the offending header's number
headerByNumber := bc.GetHeaderByNumber(header.Number.Uint64())
@@ -402,10 +400,7 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) {
// Export writes the active chain to the given writer.
func (self *BlockChain) Export(w io.Writer) error {
if err := self.ExportN(w, uint64(0), self.currentBlock.NumberU64()); err != nil {
return err
}
return nil
return self.ExportN(w, uint64(0), self.currentBlock.NumberU64())
}
// ExportN writes a subset of the active chain to the given writer.
@@ -601,7 +596,11 @@ func (self *BlockChain) procFutureBlocks() {
}
if len(blocks) > 0 {
types.BlockBy(types.Number).Sort(blocks)
self.InsertChain(blocks)
// Insert one by one as chain insertion needs contiguous ancestry between blocks
for i := range blocks {
self.InsertChain(blocks[i : i+1])
}
}
}
@@ -675,6 +674,18 @@ func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts ty
// transaction and receipt data.
// XXX should this be moved to the test?
func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
// Do a sanity check that the provided chain is actually ordered and linked
for i := 1; i < len(blockChain); i++ {
if blockChain[i].NumberU64() != blockChain[i-1].NumberU64()+1 || blockChain[i].ParentHash() != blockChain[i-1].Hash() {
// Chain broke ancestry, log a messge (programming error) and skip insertion
failure := fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, blockChain[i-1].NumberU64(),
blockChain[i-1].Hash().Bytes()[:4], i, blockChain[i].NumberU64(), blockChain[i].Hash().Bytes()[:4], blockChain[i].ParentHash().Bytes()[:4])
glog.V(logger.Error).Info(failure.Error())
return 0, failure
}
}
// Pre-checks passed, start the block body and receipt imports
self.wg.Add(1)
defer self.wg.Done()
@@ -789,7 +800,7 @@ func (self *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain
if stats.ignored > 0 {
ignored = fmt.Sprintf(" (%d ignored)", stats.ignored)
}
glog.V(logger.Info).Infof("imported %d receipts in %9v. #%d [%x… / %x…]%s", stats.processed, common.PrettyDuration(time.Since(start)), last.Number(), first.Hash().Bytes()[:4], last.Hash().Bytes()[:4], ignored)
glog.V(logger.Info).Infof("imported %4d receipts in %9v. #%d [%x… / %x…]%s", stats.processed, common.PrettyDuration(time.Since(start)), last.Number(), first.Hash().Bytes()[:4], last.Hash().Bytes()[:4], ignored)
return 0, nil
}
@@ -843,6 +854,18 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status WriteStatus, err
// InsertChain will attempt to insert the given chain in to the canonical chain or, otherwise, create a fork. It an error is returned
// it will return the index number of the failing block as well an error describing what went wrong (for possible errors see core/errors.go).
func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
// Do a sanity check that the provided chain is actually ordered and linked
for i := 1; i < len(chain); i++ {
if chain[i].NumberU64() != chain[i-1].NumberU64()+1 || chain[i].ParentHash() != chain[i-1].Hash() {
// Chain broke ancestry, log a messge (programming error) and skip insertion
failure := fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])",
i-1, chain[i-1].NumberU64(), chain[i-1].Hash().Bytes()[:4], i, chain[i].NumberU64(), chain[i].Hash().Bytes()[:4], chain[i].ParentHash().Bytes()[:4])
glog.V(logger.Error).Info(failure.Error())
return 0, failure
}
}
// Pre-checks passed, start the full block imports
self.wg.Add(1)
defer self.wg.Done()
@@ -853,9 +876,9 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
// faster than direct delivery and requires much less mutex
// acquiring.
var (
stats = insertStats{startTime: time.Now()}
stats = insertStats{startTime: mclock.Now()}
events = make([]interface{}, 0, len(chain))
coalescedLogs vm.Logs
coalescedLogs []*types.Log
nonceChecked = make([]bool, len(chain))
)
@@ -916,10 +939,8 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
}
self.reportBlock(block, nil, err)
return i, err
}
// Create a new statedb using the parent block and report an
// error if it fails.
switch {
@@ -988,7 +1009,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
glog.Infof("inserted forked block #%d [%x…] (TD=%v) in %9v: %3d txs %d uncles.", block.Number(), block.Hash().Bytes()[0:4], block.Difficulty(), common.PrettyDuration(time.Since(bstart)), len(block.Transactions()), len(block.Uncles()))
}
blockInsertTimer.UpdateSince(bstart)
events = append(events, ChainSideEvent{block, logs})
events = append(events, ChainSideEvent{block})
case SplitStatTy:
events = append(events, ChainSplitEvent{block, logs})
@@ -1011,7 +1032,7 @@ type insertStats struct {
queued, processed, ignored int
usedGas uint64
lastIndex int
startTime time.Time
startTime mclock.AbsTime
}
// statsReportLimit is the time limit during import after which we always print
@@ -1023,28 +1044,24 @@ const statsReportLimit = 8 * time.Second
func (st *insertStats) report(chain []*types.Block, index int) {
// Fetch the timings for the batch
var (
now = time.Now()
elapsed = now.Sub(st.startTime)
now = mclock.Now()
elapsed = time.Duration(now) - time.Duration(st.startTime)
)
if elapsed == 0 { // Yes Windows, I'm looking at you
elapsed = 1
}
// If we're at the last block of the batch or report period reached, log
if index == len(chain)-1 || elapsed >= statsReportLimit {
start, end := chain[st.lastIndex], chain[index]
txcount := countTransactions(chain[st.lastIndex : index+1])
extra := ""
var hashes, extra string
if st.queued > 0 || st.ignored > 0 {
extra = fmt.Sprintf(" (%d queued %d ignored)", st.queued, st.ignored)
}
hashes := ""
if st.processed > 1 {
hashes = fmt.Sprintf("%x… / %x…", start.Hash().Bytes()[:4], end.Hash().Bytes()[:4])
} else {
hashes = fmt.Sprintf("%x…", end.Hash().Bytes()[:4])
}
glog.Infof("imported %d blocks, %5d txs (%7.3f Mg) in %9v (%6.3f Mg/s). #%v [%s]%s", st.processed, txcount, float64(st.usedGas)/1000000, common.PrettyDuration(elapsed), float64(st.usedGas)*1000/float64(elapsed), end.Number(), hashes, extra)
glog.Infof("imported %4d blocks, %5d txs (%7.3f Mg) in %9v (%6.3f Mg/s). #%v [%s]%s", st.processed, txcount, float64(st.usedGas)/1000000, common.PrettyDuration(elapsed), float64(st.usedGas)*1000/float64(elapsed), end.Number(), hashes, extra)
*st = insertStats{startTime: now, lastIndex: index}
}
@@ -1062,24 +1079,25 @@ func countTransactions(chain []*types.Block) (c int) {
// event about them
func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
var (
newChain types.Blocks
oldChain types.Blocks
commonBlock *types.Block
oldStart = oldBlock
newStart = newBlock
deletedTxs types.Transactions
deletedLogs vm.Logs
deletedLogsByHash = make(map[common.Hash]vm.Logs)
newChain types.Blocks
oldChain types.Blocks
commonBlock *types.Block
oldStart = oldBlock
newStart = newBlock
deletedTxs types.Transactions
deletedLogs []*types.Log
// collectLogs collects the logs that were generated during the
// processing of the block that corresponds with the given hash.
// These logs are later announced as deleted.
collectLogs = func(h common.Hash) {
// Coalesce logs
// Coalesce logs and set 'Removed'.
receipts := GetBlockReceipts(self.chainDb, h, self.hc.GetBlockNumber(h))
for _, receipt := range receipts {
deletedLogs = append(deletedLogs, receipt.Logs...)
deletedLogsByHash[h] = receipt.Logs
for _, log := range receipt.Logs {
del := *log
del.Removed = true
deletedLogs = append(deletedLogs, &del)
}
}
}
)
@@ -1173,7 +1191,7 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
if len(oldChain) > 0 {
go func() {
for _, block := range oldChain {
self.eventMux.Post(ChainSideEvent{Block: block, Logs: deletedLogsByHash[block.Hash()]})
self.eventMux.Post(ChainSideEvent{Block: block})
}
}()
}
@@ -1183,7 +1201,7 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error {
// postChainEvents iterates over the events generated by a chain insertion and
// posts them into the event mux.
func (self *BlockChain) postChainEvents(events []interface{}, logs vm.Logs) {
func (self *BlockChain) postChainEvents(events []interface{}, logs []*types.Log) {
// post event logs for further processing
self.eventMux.Post(logs)
for _, event := range events {

View File

@@ -435,7 +435,7 @@ func (bproc) ValidateHeader(*types.Header, *types.Header, bool) error { return n
func (bproc) ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas *big.Int) error {
return nil
}
func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
func (bproc) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) {
return nil, nil, new(big.Int), nil
}
@@ -719,7 +719,7 @@ func TestFastVsFullChains(t *testing.T) {
// If the block number is multiple of 3, send a few bonus transactions to the miner
if i%3 == 2 {
for j := 0; j < i%4+1; j++ {
tx, err := types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key)
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, nil, nil), signer, key)
if err != nil {
panic(err)
}
@@ -883,8 +883,8 @@ func TestChainTxReorgs(t *testing.T) {
// Create two transactions shared between the chains:
// - postponed: transaction included at a later block in the forked chain
// - swapped: transaction included at the same block number in the forked chain
postponed, _ := types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key1)
swapped, _ := types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key1)
postponed, _ := types.SignTx(types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
swapped, _ := types.SignTx(types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
// Create two transactions that will be dropped by the forked chain:
// - pastDrop: transaction dropped retroactively from a past block
@@ -900,13 +900,13 @@ func TestChainTxReorgs(t *testing.T) {
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {
switch i {
case 0:
pastDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key2)
pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point
gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork
case 2:
freshDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key2)
freshDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point
gen.AddTx(swapped) // This transaction will be swapped out at the exact height
@@ -925,18 +925,18 @@ func TestChainTxReorgs(t *testing.T) {
chain, _ = GenerateChain(params.TestChainConfig, genesis, db, 5, func(i int, gen *BlockGen) {
switch i {
case 0:
pastAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key3)
pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
gen.AddTx(pastAdd) // This transaction needs to be injected during reorg
case 2:
gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain
gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain
freshAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key3)
freshAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time
case 3:
futureAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key3)
futureAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key3)
gen.AddTx(futureAdd) // This transaction will be added after a full reorg
}
})
@@ -995,7 +995,7 @@ func TestLogReorgs(t *testing.T) {
subs := evmux.Subscribe(RemovedLogsEvent{})
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 2, func(i int, gen *BlockGen) {
if i == 1 {
tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), code).SignECDSA(signer, key1)
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), code), signer, key1)
if err != nil {
t.Fatalf("failed to create tx: %v", err)
}
@@ -1035,7 +1035,7 @@ func TestReorgSideEvent(t *testing.T) {
}
replacementBlocks, _ := GenerateChain(params.TestChainConfig, genesis, db, 4, func(i int, gen *BlockGen) {
tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil).SignECDSA(signer, key1)
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil), signer, key1)
if i == 2 {
gen.OffsetTime(-1)
}
@@ -1107,7 +1107,7 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *BlockGen) {})
for i, _ := range chain {
for i := range chain {
go func(block *types.Block) {
// try to retrieve a block by its canonical hash and see if the block data can be retrieved.
for {
@@ -1152,7 +1152,7 @@ func TestEIP155Transition(t *testing.T) {
tx *types.Transaction
err error
basicTx = func(signer types.Signer) (*types.Transaction, error) {
return types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil).SignECDSA(signer, key)
return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
}
)
switch i {
@@ -1215,7 +1215,7 @@ func TestEIP155Transition(t *testing.T) {
tx *types.Transaction
err error
basicTx = func(signer types.Signer) (*types.Transaction, error) {
return types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil).SignECDSA(signer, key)
return types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{}, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
}
)
switch i {
@@ -1260,11 +1260,11 @@ func TestEIP161AccountRemoval(t *testing.T) {
)
switch i {
case 0:
tx, err = types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil).SignECDSA(signer, key)
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
case 1:
tx, err = types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil).SignECDSA(signer, key)
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
case 2:
tx, err = types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil).SignECDSA(signer, key)
tx, err = types.SignTx(types.NewTransaction(block.TxNonce(address), theAddr, new(big.Int), big.NewInt(21000), new(big.Int), nil), signer, key)
}
if err != nil {
t.Fatal(err)

View File

@@ -108,7 +108,7 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
b.SetCoinbase(common.Address{})
}
b.statedb.StartRecord(tx.Hash(), common.Hash{}, len(b.txs))
receipt, _, _, err := ApplyTransaction(b.config, nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
receipt, _, err := ApplyTransaction(b.config, nil, b.gasPool, b.statedb, b.header, tx, b.header.GasUsed, vm.Config{})
if err != nil {
panic(err)
}

View File

@@ -55,13 +55,13 @@ func ExampleGenerateChain() {
switch i {
case 0:
// In block 1, addr1 sends addr2 some ether.
tx, _ := types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil).SignECDSA(signer, key1)
tx, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(10000), params.TxGas, nil, nil), signer, key1)
gen.AddTx(tx)
case 1:
// In block 2, addr1 sends some more ether to addr2.
// addr2 passes it on to addr3.
tx1, _ := types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key1)
tx2, _ := types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(signer, key2)
tx1, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr1), addr2, big.NewInt(1000), params.TxGas, nil, nil), signer, key1)
tx2, _ := types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr3, big.NewInt(1000), params.TxGas, nil, nil), signer, key2)
gen.AddTx(tx1)
gen.AddTx(tx2)
case 2:

View File

@@ -45,11 +45,11 @@ func ValidateDAOHeaderExtraData(config *params.ChainConfig, header *types.Header
}
// Depending whether we support or oppose the fork, validate the extra-data contents
if config.DAOForkSupport {
if bytes.Compare(header.Extra, params.DAOForkBlockExtra) != 0 {
if !bytes.Equal(header.Extra, params.DAOForkBlockExtra) {
return ValidationError("DAO pro-fork bad block extra-data: 0x%x", header.Extra)
}
} else {
if bytes.Compare(header.Extra, params.DAOForkBlockExtra) == 0 {
if bytes.Equal(header.Extra, params.DAOForkBlockExtra) {
return ValidationError("DAO no-fork bad block extra-data: 0x%x", header.Extra)
}
}

View File

@@ -23,6 +23,7 @@ import (
"errors"
"fmt"
"math/big"
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
@@ -63,6 +64,8 @@ var (
oldBlockHashPrefix = []byte("block-hash-") // [deprecated by the header/block split, remove eventually]
ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
mipmapBloomMu sync.Mutex // protect against race condition when updating mipmap blooms
)
// encodeBlockNumber encodes a block number as big endian uint64
@@ -564,6 +567,9 @@ func mipmapKey(num, level uint64) []byte {
// WriteMapmapBloom writes each address included in the receipts' logs to the
// MIP bloom bin.
func WriteMipmapBloom(db ethdb.Database, number uint64, receipts types.Receipts) error {
mipmapBloomMu.Lock()
defer mipmapBloomMu.Unlock()
batch := db.NewBatch()
for _, level := range MIPMapLevels {
key := mipmapKey(number, level)

View File

@@ -26,7 +26,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/ethdb"
@@ -393,9 +392,9 @@ func TestReceiptStorage(t *testing.T) {
receipt1 := &types.Receipt{
PostState: []byte{0x01},
CumulativeGasUsed: big.NewInt(1),
Logs: vm.Logs{
&vm.Log{Address: common.BytesToAddress([]byte{0x11})},
&vm.Log{Address: common.BytesToAddress([]byte{0x01, 0x11})},
Logs: []*types.Log{
{Address: common.BytesToAddress([]byte{0x11})},
{Address: common.BytesToAddress([]byte{0x01, 0x11})},
},
TxHash: common.BytesToHash([]byte{0x11, 0x11}),
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
@@ -404,9 +403,9 @@ func TestReceiptStorage(t *testing.T) {
receipt2 := &types.Receipt{
PostState: []byte{0x02},
CumulativeGasUsed: big.NewInt(2),
Logs: vm.Logs{
&vm.Log{Address: common.BytesToAddress([]byte{0x22})},
&vm.Log{Address: common.BytesToAddress([]byte{0x02, 0x22})},
Logs: []*types.Log{
{Address: common.BytesToAddress([]byte{0x22})},
{Address: common.BytesToAddress([]byte{0x02, 0x22})},
},
TxHash: common.BytesToHash([]byte{0x22, 0x22}),
ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
@@ -431,7 +430,7 @@ func TestReceiptStorage(t *testing.T) {
rlpHave, _ := rlp.EncodeToBytes(r)
rlpWant, _ := rlp.EncodeToBytes(receipt)
if bytes.Compare(rlpHave, rlpWant) != 0 {
if !bytes.Equal(rlpHave, rlpWant) {
t.Fatalf("receipt #%d [%x]: receipt mismatch: have %v, want %v", i, receipt.TxHash, r, receipt)
}
}
@@ -452,9 +451,9 @@ func TestBlockReceiptStorage(t *testing.T) {
receipt1 := &types.Receipt{
PostState: []byte{0x01},
CumulativeGasUsed: big.NewInt(1),
Logs: vm.Logs{
&vm.Log{Address: common.BytesToAddress([]byte{0x11})},
&vm.Log{Address: common.BytesToAddress([]byte{0x01, 0x11})},
Logs: []*types.Log{
{Address: common.BytesToAddress([]byte{0x11})},
{Address: common.BytesToAddress([]byte{0x01, 0x11})},
},
TxHash: common.BytesToHash([]byte{0x11, 0x11}),
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
@@ -463,9 +462,9 @@ func TestBlockReceiptStorage(t *testing.T) {
receipt2 := &types.Receipt{
PostState: []byte{0x02},
CumulativeGasUsed: big.NewInt(2),
Logs: vm.Logs{
&vm.Log{Address: common.BytesToAddress([]byte{0x22})},
&vm.Log{Address: common.BytesToAddress([]byte{0x02, 0x22})},
Logs: []*types.Log{
{Address: common.BytesToAddress([]byte{0x22})},
{Address: common.BytesToAddress([]byte{0x02, 0x22})},
},
TxHash: common.BytesToHash([]byte{0x22, 0x22}),
ContractAddress: common.BytesToAddress([]byte{0x02, 0x22, 0x22}),
@@ -489,7 +488,7 @@ func TestBlockReceiptStorage(t *testing.T) {
rlpHave, _ := rlp.EncodeToBytes(rs[i])
rlpWant, _ := rlp.EncodeToBytes(receipts[i])
if bytes.Compare(rlpHave, rlpWant) != 0 {
if !bytes.Equal(rlpHave, rlpWant) {
t.Fatalf("receipt #%d: receipt mismatch: have %v, want %v", i, rs[i], receipts[i])
}
}
@@ -505,14 +504,14 @@ func TestMipmapBloom(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
receipt1 := new(types.Receipt)
receipt1.Logs = vm.Logs{
&vm.Log{Address: common.BytesToAddress([]byte("test"))},
&vm.Log{Address: common.BytesToAddress([]byte("address"))},
receipt1.Logs = []*types.Log{
{Address: common.BytesToAddress([]byte("test"))},
{Address: common.BytesToAddress([]byte("address"))},
}
receipt2 := new(types.Receipt)
receipt2.Logs = vm.Logs{
&vm.Log{Address: common.BytesToAddress([]byte("test"))},
&vm.Log{Address: common.BytesToAddress([]byte("address1"))},
receipt2.Logs = []*types.Log{
{Address: common.BytesToAddress([]byte("test"))},
{Address: common.BytesToAddress([]byte("address1"))},
}
WriteMipmapBloom(db, 1, types.Receipts{receipt1})
@@ -528,14 +527,14 @@ func TestMipmapBloom(t *testing.T) {
// reset
db, _ = ethdb.NewMemDatabase()
receipt := new(types.Receipt)
receipt.Logs = vm.Logs{
&vm.Log{Address: common.BytesToAddress([]byte("test"))},
receipt.Logs = []*types.Log{
{Address: common.BytesToAddress([]byte("test"))},
}
WriteMipmapBloom(db, 999, types.Receipts{receipt1})
receipt = new(types.Receipt)
receipt.Logs = vm.Logs{
&vm.Log{Address: common.BytesToAddress([]byte("test 1"))},
receipt.Logs = []*types.Log{
{Address: common.BytesToAddress([]byte("test 1"))},
}
WriteMipmapBloom(db, 1000, types.Receipts{receipt})
@@ -568,17 +567,12 @@ func TestMipmapChain(t *testing.T) {
switch i {
case 1:
receipt := types.NewReceipt(nil, new(big.Int))
receipt.Logs = vm.Logs{
&vm.Log{
Address: addr,
Topics: []common.Hash{hash1},
},
}
receipt.Logs = []*types.Log{{Address: addr, Topics: []common.Hash{hash1}}}
gen.AddUncheckedReceipt(receipt)
receipts = types.Receipts{receipt}
case 1000:
receipt := types.NewReceipt(nil, new(big.Int))
receipt.Logs = vm.Logs{&vm.Log{Address: addr2}}
receipt.Logs = []*types.Log{{Address: addr2}}
gen.AddUncheckedReceipt(receipt)
receipts = types.Receipts{receipt}

File diff suppressed because one or more lines are too long

View File

@@ -21,7 +21,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
)
// TxPreEvent is posted when a transaction enters the transaction pool.
@@ -32,7 +31,7 @@ type TxPostEvent struct{ Tx *types.Transaction }
// PendingLogsEvent is posted pre mining and notifies of pending logs.
type PendingLogsEvent struct {
Logs vm.Logs
Logs []*types.Log
}
// PendingStateEvent is posted pre mining and notifies of pending state changes.
@@ -45,28 +44,27 @@ type NewMinedBlockEvent struct{ Block *types.Block }
type RemovedTransactionEvent struct{ Txs types.Transactions }
// RemovedLogEvent is posted when a reorg happens
type RemovedLogsEvent struct{ Logs vm.Logs }
type RemovedLogsEvent struct{ Logs []*types.Log }
// ChainSplit is posted when a new head is detected
type ChainSplitEvent struct {
Block *types.Block
Logs vm.Logs
Logs []*types.Log
}
type ChainEvent struct {
Block *types.Block
Hash common.Hash
Logs vm.Logs
Logs []*types.Log
}
type ChainSideEvent struct {
Block *types.Block
Logs vm.Logs
}
type PendingBlockEvent struct {
Block *types.Block
Logs vm.Logs
Logs []*types.Log
}
type ChainUncleEvent struct {

73
core/evm.go Normal file
View File

@@ -0,0 +1,73 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
)
// BlockFetcher retrieves headers by their hash
type HeaderFetcher interface {
// GetHeader returns the hash corresponding to their hash
GetHeader(common.Hash, uint64) *types.Header
}
// NewEVMContext creates a new context for use in the EVM.
func NewEVMContext(msg Message, header *types.Header, chain HeaderFetcher) vm.Context {
return vm.Context{
CanTransfer: CanTransfer,
Transfer: Transfer,
GetHash: GetHashFn(header, chain),
Origin: msg.From(),
Coinbase: header.Coinbase,
BlockNumber: new(big.Int).Set(header.Number),
Time: new(big.Int).Set(header.Time),
Difficulty: new(big.Int).Set(header.Difficulty),
GasLimit: new(big.Int).Set(header.GasLimit),
GasPrice: new(big.Int).Set(msg.GasPrice()),
}
}
// GetHashFn returns a GetHashFunc which retrieves header hashes by number
func GetHashFn(ref *types.Header, chain HeaderFetcher) func(n uint64) common.Hash {
return func(n uint64) common.Hash {
for header := chain.GetHeader(ref.ParentHash, ref.Number.Uint64()-1); header != nil; header = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) {
if header.Number.Uint64() == n {
return header.Hash()
}
}
return common.Hash{}
}
}
// CanTransfer checks wether there are enough funds in the address' account to make a transfer.
// This does not take the necessary gas in to account to make the transfer valid.
func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool {
return db.GetBalance(addr).Cmp(amount) >= 0
}
// Transfer subtracts amount from sender and adds amount to recipient using the given Db
func Transfer(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {
db.SubBalance(sender, amount)
db.AddBalance(recipient, amount)
}

View File

@@ -1,217 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)
// Call executes within the given contract
func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(gas, gasPrice)
return nil, vm.DepthError
}
if !env.CanTransfer(caller.Address(), value) {
caller.ReturnGas(gas, gasPrice)
return nil, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.Db().GetBalance(caller.Address()))
}
snapshotPreTransfer := env.SnapshotDatabase()
var (
from = env.Db().GetAccount(caller.Address())
to vm.Account
)
if !env.Db().Exist(addr) {
if vm.Precompiled[addr.Str()] == nil && env.ChainConfig().IsEIP158(env.BlockNumber()) && value.BitLen() == 0 {
caller.ReturnGas(gas, gasPrice)
return nil, nil
}
to = env.Db().CreateAccount(addr)
} else {
to = env.Db().GetAccount(addr)
}
env.Transfer(from, to, value)
// initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped environment for this execution context
// only.
contract := vm.NewContract(caller, to, value, gas, gasPrice)
contract.SetCallCode(&addr, env.Db().GetCodeHash(addr), env.Db().GetCode(addr))
defer contract.Finalise()
ret, err = env.Vm().Run(contract, input)
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in homestead this also counts for code storage gas errors.
if err != nil {
contract.UseGas(contract.Gas)
env.RevertToSnapshot(snapshotPreTransfer)
}
return ret, err
}
// CallCode executes the given address' code as the given contract address
func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(gas, gasPrice)
return nil, vm.DepthError
}
if !env.CanTransfer(caller.Address(), value) {
caller.ReturnGas(gas, gasPrice)
return nil, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.Db().GetBalance(caller.Address()))
}
var (
snapshotPreTransfer = env.SnapshotDatabase()
to = env.Db().GetAccount(caller.Address())
)
// initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped environment for this execution context
// only.
contract := vm.NewContract(caller, to, value, gas, gasPrice)
contract.SetCallCode(&addr, env.Db().GetCodeHash(addr), env.Db().GetCode(addr))
defer contract.Finalise()
ret, err = env.Vm().Run(contract, input)
if err != nil {
contract.UseGas(contract.Gas)
env.RevertToSnapshot(snapshotPreTransfer)
}
return ret, err
}
// Create creates a new contract with the given code
func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) {
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(gas, gasPrice)
return nil, common.Address{}, vm.DepthError
}
if !env.CanTransfer(caller.Address(), value) {
caller.ReturnGas(gas, gasPrice)
return nil, common.Address{}, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.Db().GetBalance(caller.Address()))
}
// Create a new account on the state
nonce := env.Db().GetNonce(caller.Address())
env.Db().SetNonce(caller.Address(), nonce+1)
snapshotPreTransfer := env.SnapshotDatabase()
var (
addr = crypto.CreateAddress(caller.Address(), nonce)
from = env.Db().GetAccount(caller.Address())
to = env.Db().CreateAccount(addr)
)
if env.ChainConfig().IsEIP158(env.BlockNumber()) {
env.Db().SetNonce(addr, 1)
}
env.Transfer(from, to, value)
// initialise a new contract and set the code that is to be used by the
// EVM. The contract is a scoped environment for this execution context
// only.
contract := vm.NewContract(caller, to, value, gas, gasPrice)
contract.SetCallCode(&addr, crypto.Keccak256Hash(code), code)
defer contract.Finalise()
ret, err = env.Vm().Run(contract, nil)
// check whether the max code size has been exceeded
maxCodeSizeExceeded := len(ret) > params.MaxCodeSize
// if the contract creation ran successfully and no errors were returned
// calculate the gas required to store the code. If the code could not
// be stored due to not enough gas set an error and let it be handled
// by the error checking condition below.
if err == nil && !maxCodeSizeExceeded {
dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, params.CreateDataGas)
if contract.UseGas(dataGas) {
env.Db().SetCode(addr, ret)
} else {
err = vm.CodeStoreOutOfGasError
}
}
// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
// when we're in homestead this also counts for code storage gas errors.
if maxCodeSizeExceeded ||
(err != nil && (env.ChainConfig().IsHomestead(env.BlockNumber()) || err != vm.CodeStoreOutOfGasError)) {
contract.UseGas(contract.Gas)
env.RevertToSnapshot(snapshotPreTransfer)
// Nothing should be returned when an error is thrown.
return nil, addr, err
}
return ret, addr, err
}
// DelegateCall is equivalent to CallCode except that sender and value propagates from parent scope to child scope
func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice *big.Int) (ret []byte, err error) {
// Depth check execution. Fail if we're trying to execute above the
// limit.
if env.Depth() > int(params.CallCreateDepth.Int64()) {
caller.ReturnGas(gas, gasPrice)
return nil, vm.DepthError
}
var (
snapshot = env.SnapshotDatabase()
to = env.Db().GetAccount(caller.Address())
)
// Iinitialise a new contract and make initialise the delegate values
contract := vm.NewContract(caller, to, caller.Value(), gas, gasPrice).AsDelegate()
contract.SetCallCode(&addr, env.Db().GetCodeHash(addr), env.Db().GetCode(addr))
defer contract.Finalise()
ret, err = env.Vm().Run(contract, input)
if err != nil {
contract.UseGas(contract.Gas)
env.RevertToSnapshot(snapshot)
}
return ret, err
}
// generic transfer method
func Transfer(from, to vm.Account, amount *big.Int) {
from.SubBalance(amount)
to.AddBalance(amount)
}

View File

@@ -172,18 +172,12 @@ func WriteDefaultGenesisBlock(chainDb ethdb.Database) (*types.Block, error) {
return WriteGenesisBlock(chainDb, strings.NewReader(DefaultGenesisBlock()))
}
// WriteTestNetGenesisBlock assembles the Morden test network genesis block and
// WriteTestNetGenesisBlock assembles the test network genesis block and
// writes it - along with all associated state - into a chain database.
func WriteTestNetGenesisBlock(chainDb ethdb.Database) (*types.Block, error) {
return WriteGenesisBlock(chainDb, strings.NewReader(DefaultTestnetGenesisBlock()))
}
// WriteOlympicGenesisBlock assembles the Olympic genesis block and writes it
// along with all associated state into a chain database.
func WriteOlympicGenesisBlock(db ethdb.Database) (*types.Block, error) {
return WriteGenesisBlock(db, strings.NewReader(OlympicGenesisBlock()))
}
// DefaultGenesisBlock assembles a JSON string representing the default Ethereum
// genesis block.
func DefaultGenesisBlock() string {
@@ -198,6 +192,8 @@ func DefaultGenesisBlock() string {
return string(blob)
}
// DefaultTestnetGenesisBlock assembles a JSON string representing the default Ethereum
// test network genesis block.
func DefaultTestnetGenesisBlock() string {
reader := bzip2.NewReader(base64.NewDecoder(base64.StdEncoding, strings.NewReader(defaultTestnetGenesisBlock)))
blob, err := ioutil.ReadAll(reader)
@@ -207,26 +203,12 @@ func DefaultTestnetGenesisBlock() string {
return string(blob)
}
// OlympicGenesisBlock assembles a JSON string representing the Olympic genesis
// block.
func OlympicGenesisBlock() string {
return fmt.Sprintf(`{
"nonce":"0x%x",
"gasLimit":"0x%x",
"difficulty":"0x%x",
"alloc": {
"0000000000000000000000000000000000000001": {"balance": "1"},
"0000000000000000000000000000000000000002": {"balance": "1"},
"0000000000000000000000000000000000000003": {"balance": "1"},
"0000000000000000000000000000000000000004": {"balance": "1"},
"dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
"e4157b34ea9615cfbde6b4fda419828124b70c78": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
"b9c015918bdaba24b4ff057a92a3873d6eb201be": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
"6c386a4b26f73c802f34673f7248bb118f97424a": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
"cd2a3d9f938e13cd947ec05abc7fe734df8dd826": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
"2ef47100e0787b915105fd5e3f4ff6752079d5cb": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
"e6716f9544a56c530d868e4bfbacb172315bdead": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4": {"balance": "1606938044258990275541962092341162602522202993782792835301376"}
}
}`, types.EncodeNonce(42), params.GenesisGasLimit.Bytes(), params.GenesisDifficulty.Bytes())
// DevGenesisBlock assembles a JSON string representing a local dev genesis block.
func DevGenesisBlock() string {
reader := bzip2.NewReader(base64.NewDecoder(base64.StdEncoding, strings.NewReader(defaultDevnetGenesisBlock)))
blob, err := ioutil.ReadAll(reader)
if err != nil {
panic(fmt.Sprintf("failed to load dev genesis: %v", err))
}
return string(blob)
}

View File

@@ -224,6 +224,17 @@ type WhCallback func(*types.Header) error
// of the header retrieval mechanisms already need to verfy nonces, as well as
// because nonces can be verified sparsely, not needing to check each.
func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, checkFreq int, writeHeader WhCallback) (int, error) {
// Do a sanity check that the provided chain is actually ordered and linked
for i := 1; i < len(chain); i++ {
if chain[i].Number.Uint64() != chain[i-1].Number.Uint64()+1 || chain[i].ParentHash != chain[i-1].Hash() {
// Chain broke ancestry, log a messge (programming error) and skip insertion
failure := fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])",
i-1, chain[i-1].Number.Uint64(), chain[i-1].Hash().Bytes()[:4], i, chain[i].Number.Uint64(), chain[i].Hash().Bytes()[:4], chain[i].ParentHash.Bytes()[:4])
glog.V(logger.Error).Info(failure.Error())
return 0, failure
}
}
// Collect some import statistics to report on
stats := struct{ processed, ignored int }{}
start := time.Now()
@@ -328,7 +339,7 @@ func (hc *HeaderChain) InsertHeaderChain(chain []*types.Header, checkFreq int, w
if stats.ignored > 0 {
ignored = fmt.Sprintf(" (%d ignored)", stats.ignored)
}
glog.V(logger.Info).Infof("imported %d headers%s in %9v. #%v [%x… / %x…]", stats.processed, ignored, common.PrettyDuration(time.Since(start)), last.Number, first.Hash().Bytes()[:4], last.Hash().Bytes()[:4])
glog.V(logger.Info).Infof("imported %4d headers%s in %9v. #%v [%x… / %x…]", stats.processed, ignored, common.PrettyDuration(time.Since(start)), last.Number, first.Hash().Bytes()[:4], last.Hash().Bytes()[:4])
return 0, nil
}

View File

@@ -123,7 +123,7 @@ func (it *NodeIterator) step() error {
if !it.dataIt.Next() {
it.dataIt = nil
}
if bytes.Compare(account.CodeHash, emptyCodeHash) != 0 {
if !bytes.Equal(account.CodeHash, emptyCodeHash) {
it.codeHash = common.BytesToHash(account.CodeHash)
it.code, err = it.state.db.Get(account.CodeHash)
if err != nil {

View File

@@ -41,7 +41,7 @@ func TestNodeIteratorCoverage(t *testing.T) {
}
}
// Cross check the hashes and the database itself
for hash, _ := range hashes {
for hash := range hashes {
if _, err := db.Get(hash.Bytes()); err != nil {
t.Errorf("failed to retrieve reported node %x: %v", hash, err)
}

View File

@@ -52,7 +52,7 @@ func TestRemove(t *testing.T) {
ms, account := create()
nn := make([]bool, 10)
for i, _ := range nn {
for i := range nn {
nn[i] = true
}
account.nonces = append(account.nonces, nn...)
@@ -68,7 +68,7 @@ func TestReuse(t *testing.T) {
ms, account := create()
nn := make([]bool, 10)
for i, _ := range nn {
for i := range nn {
nn[i] = true
}
account.nonces = append(account.nonces, nn...)
@@ -84,16 +84,16 @@ func TestReuse(t *testing.T) {
func TestRemoteNonceChange(t *testing.T) {
ms, account := create()
nn := make([]bool, 10)
for i, _ := range nn {
for i := range nn {
nn[i] = true
}
account.nonces = append(account.nonces, nn...)
nonce := ms.NewNonce(addr)
ms.NewNonce(addr)
ms.StateDB.stateObjects[addr].data.Nonce = 200
nonce = ms.NewNonce(addr)
nonce := ms.NewNonce(addr)
if nonce != 200 {
t.Error("expected nonce after remote update to be", 201, "got", nonce)
t.Error("expected nonce after remote update to be", 200, "got", nonce)
}
ms.NewNonce(addr)
ms.NewNonce(addr)
@@ -101,7 +101,7 @@ func TestRemoteNonceChange(t *testing.T) {
ms.StateDB.stateObjects[addr].data.Nonce = 200
nonce = ms.NewNonce(addr)
if nonce != 204 {
t.Error("expected nonce after remote update to be", 201, "got", nonce)
t.Error("expected nonce after remote update to be", 204, "got", nonce)
}
}

View File

@@ -288,7 +288,7 @@ func (self *StateObject) setBalance(amount *big.Int) {
}
// Return the gas back to the origin. Used by the Virtual machine or Closures
func (c *StateObject) ReturnGas(gas, price *big.Int) {}
func (c *StateObject) ReturnGas(gas *big.Int) {}
func (self *StateObject) deepCopy(db *StateDB, onDirty func(addr common.Address)) *StateObject {
stateObject := newObject(db, self.address, self.data, onDirty)

View File

@@ -24,6 +24,7 @@ import (
"sync"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
@@ -71,7 +72,7 @@ type StateDB struct {
thash, bhash common.Hash
txIndex int
logs map[common.Hash]vm.Logs
logs map[common.Hash][]*types.Log
logSize uint
// Journal of state modifications. This is the backbone of
@@ -97,7 +98,7 @@ func New(root common.Hash, db ethdb.Database) (*StateDB, error) {
stateObjects: make(map[common.Address]*StateObject),
stateObjectsDirty: make(map[common.Address]struct{}),
refund: new(big.Int),
logs: make(map[common.Hash]vm.Logs),
logs: make(map[common.Hash][]*types.Log),
}, nil
}
@@ -118,7 +119,7 @@ func (self *StateDB) New(root common.Hash) (*StateDB, error) {
stateObjects: make(map[common.Address]*StateObject),
stateObjectsDirty: make(map[common.Address]struct{}),
refund: new(big.Int),
logs: make(map[common.Hash]vm.Logs),
logs: make(map[common.Hash][]*types.Log),
}, nil
}
@@ -138,7 +139,7 @@ func (self *StateDB) Reset(root common.Hash) error {
self.thash = common.Hash{}
self.bhash = common.Hash{}
self.txIndex = 0
self.logs = make(map[common.Hash]vm.Logs)
self.logs = make(map[common.Hash][]*types.Log)
self.logSize = 0
self.clearJournalAndRefund()
@@ -175,7 +176,7 @@ func (self *StateDB) StartRecord(thash, bhash common.Hash, ti int) {
self.txIndex = ti
}
func (self *StateDB) AddLog(log *vm.Log) {
func (self *StateDB) AddLog(log *types.Log) {
self.journal = append(self.journal, addLogChange{txhash: self.thash})
log.TxHash = self.thash
@@ -186,12 +187,12 @@ func (self *StateDB) AddLog(log *vm.Log) {
self.logSize++
}
func (self *StateDB) GetLogs(hash common.Hash) vm.Logs {
func (self *StateDB) GetLogs(hash common.Hash) []*types.Log {
return self.logs[hash]
}
func (self *StateDB) Logs() vm.Logs {
var logs vm.Logs
func (self *StateDB) Logs() []*types.Log {
var logs []*types.Log
for _, lgs := range self.logs {
logs = append(logs, lgs...)
}
@@ -209,7 +210,7 @@ func (self *StateDB) Exist(addr common.Address) bool {
return self.GetStateObject(addr) != nil
}
// Empty returns whether the state object is either non-existant
// Empty returns whether the state object is either non-existent
// or empty according to the EIP161 specification (balance = nonce = code = 0)
func (self *StateDB) Empty(addr common.Address) bool {
so := self.GetStateObject(addr)
@@ -293,6 +294,7 @@ func (self *StateDB) HasSuicided(addr common.Address) bool {
* SETTERS
*/
// AddBalance adds amount to the account associated with addr
func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
@@ -300,6 +302,14 @@ func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
}
}
// SubBalance subtracts amount from the account associated with addr
func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
stateObject.SubBalance(amount)
}
}
func (self *StateDB) SetBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil {
@@ -465,16 +475,16 @@ func (self *StateDB) Copy() *StateDB {
stateObjects: make(map[common.Address]*StateObject, len(self.stateObjectsDirty)),
stateObjectsDirty: make(map[common.Address]struct{}, len(self.stateObjectsDirty)),
refund: new(big.Int).Set(self.refund),
logs: make(map[common.Hash]vm.Logs, len(self.logs)),
logs: make(map[common.Hash][]*types.Log, len(self.logs)),
logSize: self.logSize,
}
// Copy the dirty states and logs
for addr, _ := range self.stateObjectsDirty {
for addr := range self.stateObjectsDirty {
state.stateObjects[addr] = self.stateObjects[addr].deepCopy(state, state.MarkStateObjectDirty)
state.stateObjectsDirty[addr] = struct{}{}
}
for hash, logs := range self.logs {
state.logs[hash] = make(vm.Logs, len(logs))
state.logs[hash] = make([]*types.Log, len(logs))
copy(state.logs[hash], logs)
}
return state
@@ -520,7 +530,7 @@ func (self *StateDB) GetRefund() *big.Int {
// It is called in between transactions to get the root hash that
// goes into transaction receipts.
func (s *StateDB) IntermediateRoot(deleteEmptyObjects bool) common.Hash {
for addr, _ := range s.stateObjectsDirty {
for addr := range s.stateObjectsDirty {
stateObject := s.stateObjects[addr]
if stateObject.suicided || (deleteEmptyObjects && stateObject.empty()) {
s.deleteStateObject(stateObject)
@@ -543,7 +553,7 @@ func (s *StateDB) DeleteSuicides() {
// Reset refund so that any used-gas calculations can use this method.
s.clearJournalAndRefund()
for addr, _ := range s.stateObjectsDirty {
for addr := range s.stateObjectsDirty {
stateObject := s.stateObjects[addr]
// If the object has been removed by a suicide

View File

@@ -29,7 +29,7 @@ import (
"testing/quick"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
)
@@ -221,7 +221,7 @@ func newTestAction(addr common.Address, r *rand.Rand) testAction {
fn: func(a testAction, s *StateDB) {
data := make([]byte, 2)
binary.BigEndian.PutUint16(data, uint16(a.args[0]))
s.AddLog(&vm.Log{Address: addr, Data: data})
s.AddLog(&types.Log{Address: addr, Data: data})
},
args: make([]int64, 1),
},

View File

@@ -21,7 +21,6 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
@@ -32,7 +31,7 @@ import (
type StateSync trie.TrieSync
// NewStateSync create a new state trie download scheduler.
func NewStateSync(root common.Hash, database ethdb.Database) *StateSync {
func NewStateSync(root common.Hash, database trie.DatabaseReader) *StateSync {
var syncer *trie.TrieSync
callback := func(leaf []byte, parent common.Hash) error {
@@ -62,8 +61,8 @@ func (s *StateSync) Missing(max int) []common.Hash {
// Process injects a batch of retrieved trie nodes data, returning if something
// was committed to the database and also the index of an entry if processing of
// it failed.
func (s *StateSync) Process(list []trie.SyncResult) (bool, int, error) {
return (*trie.TrieSync)(s).Process(list)
func (s *StateSync) Process(list []trie.SyncResult, dbw trie.DatabaseWriter) (bool, int, error) {
return (*trie.TrieSync)(s).Process(list, dbw)
}
// Pending returns the number of state entries currently pending for download.

View File

@@ -84,7 +84,7 @@ func checkStateAccounts(t *testing.T, db ethdb.Database, root common.Hash, accou
if nonce := state.GetNonce(acc.address); nonce != acc.nonce {
t.Errorf("account %d: nonce mismatch: have %v, want %v", i, nonce, acc.nonce)
}
if code := state.GetCode(acc.address); bytes.Compare(code, acc.code) != 0 {
if code := state.GetCode(acc.address); !bytes.Equal(code, acc.code) {
t.Errorf("account %d: code mismatch: have %x, want %x", i, code, acc.code)
}
}
@@ -138,7 +138,7 @@ func testIterativeStateSync(t *testing.T, batch int) {
}
results[i] = trie.SyncResult{Hash: hash, Data: data}
}
if _, index, err := sched.Process(results); err != nil {
if _, index, err := sched.Process(results, dstDb); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
}
queue = append(queue[:0], sched.Missing(batch)...)
@@ -168,7 +168,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
}
results[i] = trie.SyncResult{Hash: hash, Data: data}
}
if _, index, err := sched.Process(results); err != nil {
if _, index, err := sched.Process(results, dstDb); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
}
queue = append(queue[len(results):], sched.Missing(0)...)
@@ -198,7 +198,7 @@ func testIterativeRandomStateSync(t *testing.T, batch int) {
for len(queue) > 0 {
// Fetch all the queued nodes in a random order
results := make([]trie.SyncResult, 0, len(queue))
for hash, _ := range queue {
for hash := range queue {
data, err := srcDb.Get(hash.Bytes())
if err != nil {
t.Fatalf("failed to retrieve node data for %x: %v", hash, err)
@@ -206,7 +206,7 @@ func testIterativeRandomStateSync(t *testing.T, batch int) {
results = append(results, trie.SyncResult{Hash: hash, Data: data})
}
// Feed the retrieved results back and queue new tasks
if _, index, err := sched.Process(results); err != nil {
if _, index, err := sched.Process(results, dstDb); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
}
queue = make(map[common.Hash]struct{})
@@ -235,7 +235,7 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
for len(queue) > 0 {
// Sync only half of the scheduled nodes, even those in random order
results := make([]trie.SyncResult, 0, len(queue)/2+1)
for hash, _ := range queue {
for hash := range queue {
delete(queue, hash)
data, err := srcDb.Get(hash.Bytes())
@@ -249,7 +249,7 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
}
}
// Feed the retrieved results back and queue new tasks
if _, index, err := sched.Process(results); err != nil {
if _, index, err := sched.Process(results, dstDb); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
}
for _, hash := range sched.Missing(0) {
@@ -283,7 +283,7 @@ func TestIncompleteStateSync(t *testing.T) {
results[i] = trie.SyncResult{Hash: hash, Data: data}
}
// Process each of the state nodes
if _, index, err := sched.Process(results); err != nil {
if _, index, err := sched.Process(results, dstDb); err != nil {
t.Fatalf("failed to process result #%d: %v", index, err)
}
for _, result := range results {
@@ -294,7 +294,7 @@ func TestIncompleteStateSync(t *testing.T) {
// Skim through the accounts and make sure the root hash is not a code node
codeHash := false
for _, acc := range srcAccounts {
if bytes.Compare(root.Bytes(), crypto.Sha3(acc.code)) == 0 {
if root == crypto.Keccak256Hash(acc.code) {
codeHash = true
break
}

View File

@@ -57,13 +57,13 @@ func NewStateProcessor(config *params.ChainConfig, bc *BlockChain) *StateProcess
// Process returns the receipts and logs accumulated during the process and
// returns the amount of gas that was used in the process. If any of the
// transactions failed to execute due to insufficient gas it will return an error.
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error) {
var (
receipts types.Receipts
totalUsedGas = big.NewInt(0)
err error
header = block.Header()
allLogs vm.Logs
allLogs []*types.Log
gp = new(GasPool).AddGas(block.GasLimit())
)
// Mutate the the block and state according to any hard-fork specs
@@ -74,12 +74,12 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
for i, tx := range block.Transactions() {
//fmt.Println("tx:", i)
statedb.StartRecord(tx.Hash(), block.Hash(), i)
receipt, logs, _, err := ApplyTransaction(p.config, p.bc, gp, statedb, header, tx, totalUsedGas, cfg)
receipt, _, err := ApplyTransaction(p.config, p.bc, gp, statedb, header, tx, totalUsedGas, cfg)
if err != nil {
return nil, nil, nil, err
}
receipts = append(receipts, receipt)
allLogs = append(allLogs, logs...)
allLogs = append(allLogs, receipt.Logs...)
}
AccumulateRewards(statedb, header, block.Uncles())
@@ -87,37 +87,44 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
}
// ApplyTransaction attempts to apply a transaction to the given state database
// and uses the input parameters for its environment.
//
// ApplyTransactions returns the generated receipts and vm logs during the
// execution of the state transition phase.
func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) {
// and uses the input parameters for its environment. It returns the receipt
// for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid.
func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, *big.Int, error) {
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
if err != nil {
return nil, nil, nil, err
return nil, nil, err
}
_, gas, err := ApplyMessage(NewEnv(statedb, config, bc, msg, header, cfg), msg, gp)
// Create a new context to be used in the EVM environment
context := NewEVMContext(msg, header, bc)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(context, statedb, config, vm.Config{})
// Apply the transaction to the current state (included in the env)
_, gas, err := ApplyMessage(vmenv, msg, gp)
if err != nil {
return nil, nil, nil, err
return nil, nil, err
}
// Update the state with pending changes
usedGas.Add(usedGas, gas)
// Create a new receipt for the transaction, storing the intermediate root and gas used by the tx
// based on the eip phase, we're passing wether the root touch-delete accounts.
receipt := types.NewReceipt(statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes(), usedGas)
receipt.TxHash = tx.Hash()
receipt.GasUsed = new(big.Int).Set(gas)
if MessageCreatesContract(msg) {
receipt.ContractAddress = crypto.CreateAddress(msg.From(), tx.Nonce())
// if the transaction created a contract, store the creation address in the receipt.
if msg.To() == nil {
receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce())
}
logs := statedb.GetLogs(tx.Hash())
receipt.Logs = logs
// Set the receipt logs and create a bloom for filtering
receipt.Logs = statedb.GetLogs(tx.Hash())
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
glog.V(logger.Debug).Infoln(receipt)
return receipt, logs, gas, err
return receipt, gas, err
}
// AccumulateRewards credits the coinbase of the given block with the

View File

@@ -55,9 +55,9 @@ type StateTransition struct {
initialGas *big.Int
value *big.Int
data []byte
state vm.Database
state vm.StateDB
env vm.Environment
env *vm.EVM
}
// Message represents a message sent to a contract.
@@ -106,7 +106,7 @@ func IntrinsicGas(data []byte, contractCreation, homestead bool) *big.Int {
}
// NewStateTransition initialises and returns a new state transition object.
func NewStateTransition(env vm.Environment, msg Message, gp *GasPool) *StateTransition {
func NewStateTransition(env *vm.EVM, msg Message, gp *GasPool) *StateTransition {
return &StateTransition{
gp: gp,
env: env,
@@ -116,7 +116,7 @@ func NewStateTransition(env vm.Environment, msg Message, gp *GasPool) *StateTran
initialGas: new(big.Int),
value: msg.Value(),
data: msg.Data(),
state: env.Db(),
state: env.StateDB,
}
}
@@ -127,7 +127,7 @@ func NewStateTransition(env vm.Environment, msg Message, gp *GasPool) *StateTran
// the gas used (which includes gas refunds) and an error if it failed. An error always
// indicates a core error meaning that the message would always fail for that particular
// state and would never be accepted within a block.
func ApplyMessage(env vm.Environment, msg Message, gp *GasPool) ([]byte, *big.Int, error) {
func ApplyMessage(env *vm.EVM, msg Message, gp *GasPool) ([]byte, *big.Int, error) {
st := NewStateTransition(env, msg, gp)
ret, _, gasUsed, err := st.TransitionDb()
@@ -159,7 +159,7 @@ func (self *StateTransition) to() vm.Account {
func (self *StateTransition) useGas(amount *big.Int) error {
if self.gas.Cmp(amount) < 0 {
return vm.OutOfGasError
return vm.ErrOutOfGas
}
self.gas.Sub(self.gas, amount)
@@ -217,47 +217,44 @@ func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *b
msg := self.msg
sender := self.from() // err checked in preCheck
homestead := self.env.ChainConfig().IsHomestead(self.env.BlockNumber())
homestead := self.env.ChainConfig().IsHomestead(self.env.BlockNumber)
contractCreation := MessageCreatesContract(msg)
// Pay intrinsic gas
if err = self.useGas(IntrinsicGas(self.data, contractCreation, homestead)); err != nil {
return nil, nil, nil, InvalidTxError(err)
}
vmenv := self.env
//var addr common.Address
var (
vmenv = self.env
// vm errors do not effect consensus and are therefor
// not assigned to err, except for insufficient balance
// error.
vmerr error
)
if contractCreation {
ret, _, err = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value)
if homestead && err == vm.CodeStoreOutOfGasError {
ret, _, vmerr = vmenv.Create(sender, self.data, self.gas, self.value)
if homestead && err == vm.ErrCodeStoreOutOfGas {
self.gas = Big0
}
if err != nil {
ret = nil
glog.V(logger.Core).Infoln("VM create err:", err)
}
} else {
// Increment the nonce for the next transaction
self.state.SetNonce(sender.Address(), self.state.GetNonce(sender.Address())+1)
ret, err = vmenv.Call(sender, self.to().Address(), self.data, self.gas, self.gasPrice, self.value)
if err != nil {
glog.V(logger.Core).Infoln("VM call err:", err)
ret, vmerr = vmenv.Call(sender, self.to().Address(), self.data, self.gas, self.value)
}
if vmerr != nil {
glog.V(logger.Core).Infoln("vm returned with error:", err)
// The only possible consensus-error would be if there wasn't
// sufficient balance to make the transfer happen. The first
// balance transfer may never fail.
if vmerr == vm.ErrInsufficientBalance {
return nil, nil, nil, InvalidTxError(vmerr)
}
}
if err != nil && IsValueTransferErr(err) {
return nil, nil, nil, InvalidTxError(err)
}
// We aren't interested in errors here. Errors returned by the VM are non-consensus errors and therefor shouldn't bubble up
if err != nil {
err = nil
}
requiredGas = new(big.Int).Set(self.gasUsed())
self.refundGas()
self.state.AddBalance(self.env.Coinbase(), new(big.Int).Mul(self.gasUsed(), self.gasPrice))
self.state.AddBalance(self.env.Coinbase, new(big.Int).Mul(self.gasUsed(), self.gasPrice))
return ret, requiredGas, self.gasUsed(), err
}

View File

@@ -110,7 +110,7 @@ func (m *txSortedMap) Filter(filter func(*types.Transaction) bool) types.Transac
// If transactions were removed, the heap and cache are ruined
if len(removed) > 0 {
*m.index = make([]uint64, 0, len(m.items))
for nonce, _ := range m.items {
for nonce := range m.items {
*m.index = append(*m.index, nonce)
}
heap.Init(m.index)
@@ -216,7 +216,7 @@ func (m *txSortedMap) Flatten() types.Transactions {
// txList is a "list" of transactions belonging to an account, sorted by account
// nonce. The same type can be used both for storing contiguous transactions for
// the executable/pending queue; and for storing gapped transactions for the non-
// executable/future queue, with minor behavoiral changes.
// executable/future queue, with minor behavioral changes.
type txList struct {
strict bool // Whether nonces are strictly continuous or not
txs *txSortedMap // Heap indexed sorted hash map of the transactions

View File

@@ -37,15 +37,14 @@ import (
var (
// Transaction Pool Errors
ErrInvalidSender = errors.New("Invalid sender")
ErrNonce = errors.New("Nonce too low")
ErrCheap = errors.New("Gas price too low for acceptance")
ErrBalance = errors.New("Insufficient balance")
ErrNonExistentAccount = errors.New("Account does not exist or account balance too low")
ErrInsufficientFunds = errors.New("Insufficient funds for gas * price + value")
ErrIntrinsicGas = errors.New("Intrinsic gas too low")
ErrGasLimit = errors.New("Exceeds block gas limit")
ErrNegativeValue = errors.New("Negative value")
ErrInvalidSender = errors.New("Invalid sender")
ErrNonce = errors.New("Nonce too low")
ErrCheap = errors.New("Gas price too low for acceptance")
ErrBalance = errors.New("Insufficient balance")
ErrInsufficientFunds = errors.New("Insufficient funds for gas * price + value")
ErrIntrinsicGas = errors.New("Intrinsic gas too low")
ErrGasLimit = errors.New("Exceeds block gas limit")
ErrNegativeValue = errors.New("Negative value")
)
var (
@@ -124,6 +123,8 @@ func NewTxPool(config *params.ChainConfig, eventMux *event.TypeMux, currentState
quit: make(chan struct{}),
}
pool.resetState()
pool.wg.Add(2)
go pool.eventLoop()
go pool.expirationLoop()
@@ -176,7 +177,7 @@ func (pool *TxPool) resetState() {
// any transactions that have been included in the block or
// have been invalidated because of another transaction (e.g.
// higher gas price)
pool.demoteUnexecutables()
pool.demoteUnexecutables(currentState)
// Update all accounts to the latest known pending nonce
for addr, list := range pool.pending {
@@ -185,7 +186,7 @@ func (pool *TxPool) resetState() {
}
// Check the queue and move transactions over to the pending if possible
// or remove those that have become invalid
pool.promoteExecutables()
pool.promoteExecutables(currentState)
}
func (pool *TxPool) Stop() {
@@ -237,21 +238,26 @@ func (pool *TxPool) Content() (map[common.Address]types.Transactions, map[common
// Pending retrieves all currently processable transactions, groupped by origin
// account and sorted by nonce. The returned transaction set is a copy and can be
// freely modified by calling code.
func (pool *TxPool) Pending() map[common.Address]types.Transactions {
func (pool *TxPool) Pending() (map[common.Address]types.Transactions, error) {
pool.mu.Lock()
defer pool.mu.Unlock()
state, err := pool.currentState()
if err != nil {
return nil, err
}
// check queue first
pool.promoteExecutables()
pool.promoteExecutables(state)
// invalidate any txs
pool.demoteUnexecutables()
pool.demoteUnexecutables(state)
pending := make(map[common.Address]types.Transactions)
for addr, list := range pool.pending {
pending[addr] = list.Flatten()
}
return pending
return pending, nil
}
// SetLocal marks a transaction as local, skipping gas price
@@ -280,13 +286,6 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
if err != nil {
return ErrInvalidSender
}
// Make sure the account exist. Non existent accounts
// haven't got funds and well therefor never pass.
if !currentState.Exist(from) {
return ErrNonExistentAccount
}
// Last but not least check for nonce errors
if currentState.GetNonce(from) > tx.Nonce() {
return ErrNonce
@@ -322,7 +321,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
// add validates a transaction and inserts it into the non-executable queue for
// later pending promotion and execution.
func (pool *TxPool) add(tx *types.Transaction) error {
// If the transaction is alreayd known, discard it
// If the transaction is already known, discard it
hash := tx.Hash()
if pool.all[hash] != nil {
return fmt.Errorf("Known transaction: %x", hash[:4])
@@ -372,10 +371,6 @@ func (pool *TxPool) enqueueTx(hash common.Hash, tx *types.Transaction) {
//
// Note, this method assumes the pool lock is held!
func (pool *TxPool) promoteTx(addr common.Address, hash common.Hash, tx *types.Transaction) {
// Init delayed since tx pool could have been started before any state sync
if pool.pendingState == nil {
pool.resetState()
}
// Try to insert the transaction into the pending queue
if pool.pending[addr] == nil {
pool.pending[addr] = newTxList(true)
@@ -410,13 +405,19 @@ func (pool *TxPool) Add(tx *types.Transaction) error {
if err := pool.add(tx); err != nil {
return err
}
pool.promoteExecutables()
state, err := pool.currentState()
if err != nil {
return err
}
pool.promoteExecutables(state)
return nil
}
// AddBatch attempts to queue a batch of transactions.
func (pool *TxPool) AddBatch(txs []*types.Transaction) {
func (pool *TxPool) AddBatch(txs []*types.Transaction) error {
pool.mu.Lock()
defer pool.mu.Unlock()
@@ -425,7 +426,15 @@ func (pool *TxPool) AddBatch(txs []*types.Transaction) {
glog.V(logger.Debug).Infoln("tx error:", err)
}
}
pool.promoteExecutables()
state, err := pool.currentState()
if err != nil {
return err
}
pool.promoteExecutables(state)
return nil
}
// Get returns a transaction if it is contained in the pool
@@ -499,17 +508,7 @@ func (pool *TxPool) removeTx(hash common.Hash) {
// promoteExecutables moves transactions that have become processable from the
// future queue to the set of pending transactions. During this process, all
// invalidated transactions (low nonce, low balance) are deleted.
func (pool *TxPool) promoteExecutables() {
// Init delayed since tx pool could have been started before any state sync
if pool.pendingState == nil {
pool.resetState()
}
// Retrieve the current state to allow nonce and balance checking
state, err := pool.currentState()
if err != nil {
glog.Errorf("Could not get current state: %v", err)
return
}
func (pool *TxPool) promoteExecutables(state *state.StateDB) {
// Iterate over all accounts and promote any executable transactions
queued := uint64(0)
for addr, list := range pool.queue {
@@ -610,7 +609,7 @@ func (pool *TxPool) promoteExecutables() {
if queued > maxQueuedInTotal {
// Sort all accounts with queued transactions by heartbeat
addresses := make(addresssByHeartbeat, 0, len(pool.queue))
for addr, _ := range pool.queue {
for addr := range pool.queue {
addresses = append(addresses, addressByHeartbeat{addr, pool.beats[addr]})
}
sort.Sort(addresses)
@@ -645,13 +644,7 @@ func (pool *TxPool) promoteExecutables() {
// demoteUnexecutables removes invalid and processed transactions from the pools
// executable/pending queue and any subsequent transactions that become unexecutable
// are moved back into the future queue.
func (pool *TxPool) demoteUnexecutables() {
// Retrieve the current state to allow nonce and balance checking
state, err := pool.currentState()
if err != nil {
glog.V(logger.Info).Infoln("failed to get current state: %v", err)
return
}
func (pool *TxPool) demoteUnexecutables(state *state.StateDB) {
// Iterate over all accounts and demote any non-executable transactions
for addr, list := range pool.pending {
nonce := state.GetNonce(addr)

View File

@@ -32,7 +32,7 @@ import (
)
func transaction(nonce uint64, gaslimit *big.Int, key *ecdsa.PrivateKey) *types.Transaction {
tx, _ := types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, big.NewInt(1), nil).SignECDSA(types.HomesteadSigner{}, key)
tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), gaslimit, big.NewInt(1), nil), types.HomesteadSigner{}, key)
return tx
}
@@ -51,14 +51,84 @@ func deriveSender(tx *types.Transaction) (common.Address, error) {
return types.Sender(types.HomesteadSigner{}, tx)
}
// This test simulates a scenario where a new block is imported during a
// state reset and tests whether the pending state is in sync with the
// block head event that initiated the resetState().
func TestStateChangeDuringPoolReset(t *testing.T) {
var (
db, _ = ethdb.NewMemDatabase()
key, _ = crypto.GenerateKey()
address = crypto.PubkeyToAddress(key.PublicKey)
mux = new(event.TypeMux)
statedb, _ = state.New(common.Hash{}, db)
trigger = false
)
// setup pool with 2 transaction in it
statedb.SetBalance(address, new(big.Int).Mul(common.Big1, common.Ether))
tx0 := transaction(0, big.NewInt(100000), key)
tx1 := transaction(1, big.NewInt(100000), key)
// stateFunc is used multiple times to reset the pending state.
// when simulate is true it will create a state that indicates
// that tx0 and tx1 are included in the chain.
stateFunc := func() (*state.StateDB, error) {
// delay "state change" by one. The tx pool fetches the
// state multiple times and by delaying it a bit we simulate
// a state change between those fetches.
stdb := statedb
if trigger {
statedb, _ = state.New(common.Hash{}, db)
// simulate that the new head block included tx0 and tx1
statedb.SetNonce(address, 2)
statedb.SetBalance(address, new(big.Int).Mul(common.Big1, common.Ether))
trigger = false
}
return stdb, nil
}
gasLimitFunc := func() *big.Int { return big.NewInt(1000000000) }
txpool := NewTxPool(testChainConfig(), mux, stateFunc, gasLimitFunc)
txpool.resetState()
nonce := txpool.State().GetNonce(address)
if nonce != 0 {
t.Fatalf("Invalid nonce, want 0, got %d", nonce)
}
txpool.AddBatch(types.Transactions{tx0, tx1})
nonce = txpool.State().GetNonce(address)
if nonce != 2 {
t.Fatalf("Invalid nonce, want 2, got %d", nonce)
}
// trigger state change in the background
trigger = true
txpool.resetState()
pendingTx, err := txpool.Pending()
if err != nil {
t.Fatalf("Could not fetch pending transactions: %v", err)
}
for addr, txs := range pendingTx {
t.Logf("%0x: %d\n", addr, len(txs))
}
nonce = txpool.State().GetNonce(address)
if nonce != 2 {
t.Fatalf("Invalid nonce, want 2, got %d", nonce)
}
}
func TestInvalidTransactions(t *testing.T) {
pool, key := setupTxPool()
tx := transaction(0, big.NewInt(100), key)
if err := pool.Add(tx); err != ErrNonExistentAccount {
t.Error("expected", ErrNonExistentAccount)
}
from, _ := deriveSender(tx)
currentState, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1))
@@ -97,9 +167,10 @@ func TestTransactionQueue(t *testing.T) {
from, _ := deriveSender(tx)
currentState, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1000))
pool.resetState()
pool.enqueueTx(tx.Hash(), tx)
pool.promoteExecutables()
pool.promoteExecutables(currentState)
if len(pool.pending) != 1 {
t.Error("expected valid txs to be 1 is", len(pool.pending))
}
@@ -108,7 +179,7 @@ func TestTransactionQueue(t *testing.T) {
from, _ = deriveSender(tx)
currentState.SetNonce(from, 2)
pool.enqueueTx(tx.Hash(), tx)
pool.promoteExecutables()
pool.promoteExecutables(currentState)
if _, ok := pool.pending[from].txs.items[tx.Nonce()]; ok {
t.Error("expected transaction to be in tx pool")
}
@@ -124,11 +195,13 @@ func TestTransactionQueue(t *testing.T) {
from, _ = deriveSender(tx1)
currentState, _ = pool.currentState()
currentState.AddBalance(from, big.NewInt(1000))
pool.resetState()
pool.enqueueTx(tx1.Hash(), tx1)
pool.enqueueTx(tx2.Hash(), tx2)
pool.enqueueTx(tx3.Hash(), tx3)
pool.promoteExecutables()
pool.promoteExecutables(currentState)
if len(pool.pending) != 1 {
t.Error("expected tx pool to be 1, got", len(pool.pending))
@@ -165,7 +238,7 @@ func TestRemoveTx(t *testing.T) {
func TestNegativeValue(t *testing.T) {
pool, key := setupTxPool()
tx, _ := types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil).SignECDSA(types.HomesteadSigner{}, key)
tx, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(-1), big.NewInt(100), big.NewInt(1), nil), types.HomesteadSigner{}, key)
from, _ := deriveSender(tx)
currentState, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1))
@@ -214,9 +287,9 @@ func TestTransactionDoubleNonce(t *testing.T) {
resetState()
signer := types.HomesteadSigner{}
tx1, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), nil).SignECDSA(signer, key)
tx2, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(2), nil).SignECDSA(signer, key)
tx3, _ := types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(1), nil).SignECDSA(signer, key)
tx1, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(100000), big.NewInt(1), nil), signer, key)
tx2, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(2), nil), signer, key)
tx3, _ := types.SignTx(types.NewTransaction(0, common.Address{}, big.NewInt(100), big.NewInt(1000000), big.NewInt(1), nil), signer, key)
// Add the first two transaction, ensure higher priced stays only
if err := pool.add(tx1); err != nil {
@@ -225,7 +298,8 @@ func TestTransactionDoubleNonce(t *testing.T) {
if err := pool.add(tx2); err != nil {
t.Error("didn't expect error", err)
}
pool.promoteExecutables()
state, _ := pool.currentState()
pool.promoteExecutables(state)
if pool.pending[addr].Len() != 1 {
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
}
@@ -236,7 +310,7 @@ func TestTransactionDoubleNonce(t *testing.T) {
if err := pool.add(tx3); err != nil {
t.Error("didn't expect error", err)
}
pool.promoteExecutables()
pool.promoteExecutables(state)
if pool.pending[addr].Len() != 1 {
t.Error("expected 1 pending transactions, got", pool.pending[addr].Len())
}
@@ -295,6 +369,7 @@ func TestRemovedTxEvent(t *testing.T) {
from, _ := deriveSender(tx)
currentState, _ := pool.currentState()
currentState.AddBalance(from, big.NewInt(1000000000000))
pool.resetState()
pool.eventMux.Post(RemovedTransactionEvent{types.Transactions{tx}})
pool.eventMux.Post(ChainHeadEvent{nil})
if pool.pending[from].Len() != 1 {
@@ -452,6 +527,7 @@ func TestTransactionQueueAccountLimiting(t *testing.T) {
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
pool.resetState()
// Keep queuing up transactions and make sure all above a limit are dropped
for i := uint64(1); i <= maxQueuedPerAccount+5; i++ {
@@ -564,6 +640,7 @@ func TestTransactionPendingLimiting(t *testing.T) {
state, _ := pool.currentState()
state.AddBalance(account, big.NewInt(1000000))
pool.resetState()
// Keep queuing up transactions and make sure all above a limit are dropped
for i := uint64(0); i < maxQueuedPerAccount+5; i++ {
@@ -733,7 +810,7 @@ func benchmarkPendingDemotion(b *testing.B, size int) {
// Benchmark the speed of pool validation
b.ResetTimer()
for i := 0; i < b.N; i++ {
pool.demoteUnexecutables()
pool.demoteUnexecutables(state)
}
}
@@ -757,7 +834,7 @@ func benchmarkFuturePromotion(b *testing.B, size int) {
// Benchmark the speed of pool validation
b.ResetTimer()
for i := 0; i < b.N; i++ {
pool.promoteExecutables()
pool.promoteExecutables(state)
}
}

View File

@@ -58,5 +58,5 @@ type HeaderValidator interface {
// of gas used in the process and return an error if any of the internal rules
// failed.
type Processor interface {
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error)
Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, []*types.Log, *big.Int, error)
}

View File

@@ -423,9 +423,9 @@ func CalcUncleHash(uncles []*Header) common.Hash {
// WithMiningResult returns a new block with the data from b
// where nonce and mix digest are set to the provided values.
func (b *Block) WithMiningResult(nonce uint64, mixDigest common.Hash) *Block {
func (b *Block) WithMiningResult(nonce BlockNonce, mixDigest common.Hash) *Block {
cpy := *b.header
binary.BigEndian.PutUint64(cpy.Nonce[:], nonce)
cpy.Nonce = nonce
cpy.MixDigest = mixDigest
return &Block{
header: &cpy,

View File

@@ -53,7 +53,7 @@ func TestBlockEncoding(t *testing.T) {
tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), big.NewInt(50000), big.NewInt(10), nil)
tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b11b"))
tx1, _ = tx1.WithSignature(HomesteadSigner{}, common.Hex2Bytes("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b100"))
fmt.Println(block.Transactions()[0].Hash())
fmt.Println(tx1.data)
fmt.Println(tx1.Hash())

View File

@@ -22,7 +22,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
)
@@ -95,17 +94,11 @@ func CreateBloom(receipts Receipts) Bloom {
return BytesToBloom(bin.Bytes())
}
func LogsBloom(logs vm.Logs) *big.Int {
func LogsBloom(logs []*Log) *big.Int {
bin := new(big.Int)
for _, log := range logs {
data := make([]common.Hash, len(log.Topics))
bin.Or(bin, bloom9(log.Address.Bytes()))
for i, topic := range log.Topics {
data[i] = topic
}
for _, b := range data {
for _, b := range log.Topics {
bin.Or(bin, bloom9(b[:]))
}
}

184
core/types/log.go Normal file
View File

@@ -0,0 +1,184 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package types
import (
"encoding/json"
"errors"
"fmt"
"io"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rlp"
)
var errMissingLogFields = errors.New("missing required JSON log fields")
// Log represents a contract log event. These events are generated by the LOG opcode and
// stored/indexed by the node.
type Log struct {
// Consensus fields.
Address common.Address // address of the contract that generated the event
Topics []common.Hash // list of topics provided by the contract.
Data []byte // supplied by the contract, usually ABI-encoded
// Derived fields. These fields are filled in by the node
// but not secured by consensus.
BlockNumber uint64 // block in which the transaction was included
TxHash common.Hash // hash of the transaction
TxIndex uint // index of the transaction in the block
BlockHash common.Hash // hash of the block in which the transaction was included
Index uint // index of the log in the receipt
// The Removed field is true if this log was reverted due to a chain reorganisation.
// You must pay attention to this field if you receive logs through a filter query.
Removed bool
}
type rlpLog struct {
Address common.Address
Topics []common.Hash
Data []byte
}
type rlpStorageLog struct {
Address common.Address
Topics []common.Hash
Data []byte
BlockNumber uint64
TxHash common.Hash
TxIndex uint
BlockHash common.Hash
Index uint
}
type jsonLog struct {
Address *common.Address `json:"address"`
Topics *[]common.Hash `json:"topics"`
Data *hexutil.Bytes `json:"data"`
BlockNumber *hexutil.Uint64 `json:"blockNumber"`
TxIndex *hexutil.Uint `json:"transactionIndex"`
TxHash *common.Hash `json:"transactionHash"`
BlockHash *common.Hash `json:"blockHash"`
Index *hexutil.Uint `json:"logIndex"`
Removed bool `json:"removed"`
}
// EncodeRLP implements rlp.Encoder.
func (l *Log) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, rlpLog{Address: l.Address, Topics: l.Topics, Data: l.Data})
}
// DecodeRLP implements rlp.Decoder.
func (l *Log) DecodeRLP(s *rlp.Stream) error {
var dec rlpLog
err := s.Decode(&dec)
if err == nil {
l.Address, l.Topics, l.Data = dec.Address, dec.Topics, dec.Data
}
return err
}
func (l *Log) String() string {
return fmt.Sprintf(`log: %x %x %x %x %d %x %d`, l.Address, l.Topics, l.Data, l.TxHash, l.TxIndex, l.BlockHash, l.Index)
}
// MarshalJSON implements json.Marshaler.
func (l *Log) MarshalJSON() ([]byte, error) {
jslog := &jsonLog{
Address: &l.Address,
Topics: &l.Topics,
Data: (*hexutil.Bytes)(&l.Data),
TxIndex: (*hexutil.Uint)(&l.TxIndex),
TxHash: &l.TxHash,
Index: (*hexutil.Uint)(&l.Index),
Removed: l.Removed,
}
// Set block information for mined logs.
if (l.BlockHash != common.Hash{}) {
jslog.BlockHash = &l.BlockHash
jslog.BlockNumber = (*hexutil.Uint64)(&l.BlockNumber)
}
return json.Marshal(jslog)
}
// UnmarshalJSON implements json.Umarshaler.
func (l *Log) UnmarshalJSON(input []byte) error {
var dec jsonLog
if err := json.Unmarshal(input, &dec); err != nil {
return err
}
if dec.Address == nil || dec.Topics == nil || dec.Data == nil ||
dec.TxIndex == nil || dec.TxHash == nil || dec.Index == nil {
return errMissingLogFields
}
declog := Log{
Address: *dec.Address,
Topics: *dec.Topics,
Data: *dec.Data,
TxHash: *dec.TxHash,
TxIndex: uint(*dec.TxIndex),
Index: uint(*dec.Index),
Removed: dec.Removed,
}
// Block information may be missing if the log is received through
// the pending log filter, so it's handled specially here.
if dec.BlockHash != nil && dec.BlockNumber != nil {
declog.BlockHash = *dec.BlockHash
declog.BlockNumber = uint64(*dec.BlockNumber)
}
*l = declog
return nil
}
// LogForStorage is a wrapper around a Log that flattens and parses the entire content of
// a log including non-consensus fields.
type LogForStorage Log
// EncodeRLP implements rlp.Encoder.
func (l *LogForStorage) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, rlpStorageLog{
Address: l.Address,
Topics: l.Topics,
Data: l.Data,
BlockNumber: l.BlockNumber,
TxHash: l.TxHash,
TxIndex: l.TxIndex,
BlockHash: l.BlockHash,
Index: l.Index,
})
}
// DecodeRLP implements rlp.Decoder.
func (l *LogForStorage) DecodeRLP(s *rlp.Stream) error {
var dec rlpStorageLog
err := s.Decode(&dec)
if err == nil {
*l = LogForStorage{
Address: dec.Address,
Topics: dec.Topics,
Data: dec.Data,
BlockNumber: dec.BlockNumber,
TxHash: dec.TxHash,
TxIndex: dec.TxIndex,
BlockHash: dec.BlockHash,
Index: dec.Index,
}
}
return err
}

131
core/types/log_test.go Normal file
View File

@@ -0,0 +1,131 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package types
import (
"encoding/json"
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
var unmarshalLogTests = map[string]struct {
input string
want *Log
wantError error
}{
"ok": {
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","data":"0x000000000000000000000000000000000000000000000001a055690d9db80000","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
want: &Log{
Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"),
BlockHash: common.HexToHash("0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056"),
BlockNumber: 2019236,
Data: hexutil.MustDecode("0x000000000000000000000000000000000000000000000001a055690d9db80000"),
Index: 2,
TxIndex: 3,
TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"),
Topics: []common.Hash{
common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"),
common.HexToHash("0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"),
},
},
},
"empty data": {
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","data":"0x","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
want: &Log{
Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"),
BlockHash: common.HexToHash("0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056"),
BlockNumber: 2019236,
Data: []byte{},
Index: 2,
TxIndex: 3,
TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"),
Topics: []common.Hash{
common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"),
common.HexToHash("0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615"),
},
},
},
"missing block fields (pending logs)": {
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","data":"0x","logIndex":"0x0","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
want: &Log{
Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"),
BlockHash: common.Hash{},
BlockNumber: 0,
Data: []byte{},
Index: 0,
TxIndex: 3,
TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"),
Topics: []common.Hash{
common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"),
},
},
},
"Removed: true": {
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","data":"0x","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3","removed":true}`,
want: &Log{
Address: common.HexToAddress("0xecf8f87f810ecf450940c9f60066b4a7a501d6a7"),
BlockHash: common.HexToHash("0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056"),
BlockNumber: 2019236,
Data: []byte{},
Index: 2,
TxIndex: 3,
TxHash: common.HexToHash("0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e"),
Topics: []common.Hash{
common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"),
},
Removed: true,
},
},
"missing data": {
input: `{"address":"0xecf8f87f810ecf450940c9f60066b4a7a501d6a7","blockHash":"0x656c34545f90a730a19008c0e7a7cd4fb3895064b48d6d69761bd5abad681056","blockNumber":"0x1ecfa4","logIndex":"0x2","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x00000000000000000000000080b2c9d7cbbf30a1b0fc8983c647d754c6525615","0x000000000000000000000000f9dff387dcb5cc4cca5b91adb07a95f54e9f1bb6"],"transactionHash":"0x3b198bfd5d2907285af009e9ae84a0ecd63677110d89d7e030251acb87f6487e","transactionIndex":"0x3"}`,
wantError: errMissingLogFields,
},
}
func TestUnmarshalLog(t *testing.T) {
dumper := spew.ConfigState{DisableMethods: true, Indent: " "}
for name, test := range unmarshalLogTests {
var log *Log
err := json.Unmarshal([]byte(test.input), &log)
checkError(t, name, err, test.wantError)
if test.wantError == nil && err == nil {
if !reflect.DeepEqual(log, test.want) {
t.Errorf("test %q:\nGOT %sWANT %s", name, dumper.Sdump(log), dumper.Sdump(test.want))
}
}
}
}
func checkError(t *testing.T, testname string, got, want error) bool {
if got == nil {
if want != nil {
t.Errorf("test %q: got no error, want %q", testname, want)
return false
}
return true
}
if want == nil {
t.Errorf("test %q: unexpected error %q", testname, got)
} else if got.Error() != want.Error() {
t.Errorf("test %q: got error %q, want %q", testname, got, want)
}
return false
}

View File

@@ -25,7 +25,6 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -40,7 +39,7 @@ type Receipt struct {
PostState []byte
CumulativeGasUsed *big.Int
Bloom Bloom
Logs vm.Logs
Logs []*Log
// Implementation fields (don't reorder!)
TxHash common.Hash
@@ -52,7 +51,7 @@ type jsonReceipt struct {
PostState *common.Hash `json:"root"`
CumulativeGasUsed *hexutil.Big `json:"cumulativeGasUsed"`
Bloom *Bloom `json:"logsBloom"`
Logs *vm.Logs `json:"logs"`
Logs []*Log `json:"logs"`
TxHash *common.Hash `json:"transactionHash"`
ContractAddress *common.Address `json:"contractAddress"`
GasUsed *hexutil.Big `json:"gasUsed"`
@@ -76,7 +75,7 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
PostState []byte
CumulativeGasUsed *big.Int
Bloom Bloom
Logs vm.Logs
Logs []*Log
}
if err := s.Decode(&receipt); err != nil {
return err
@@ -93,7 +92,7 @@ func (r *Receipt) MarshalJSON() ([]byte, error) {
PostState: &root,
CumulativeGasUsed: (*hexutil.Big)(r.CumulativeGasUsed),
Bloom: &r.Bloom,
Logs: &r.Logs,
Logs: r.Logs,
TxHash: &r.TxHash,
ContractAddress: &r.ContractAddress,
GasUsed: (*hexutil.Big)(r.GasUsed),
@@ -120,7 +119,7 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
PostState: (*dec.PostState)[:],
CumulativeGasUsed: (*big.Int)(dec.CumulativeGasUsed),
Bloom: *dec.Bloom,
Logs: *dec.Logs,
Logs: dec.Logs,
TxHash: *dec.TxHash,
GasUsed: (*big.Int)(dec.GasUsed),
}
@@ -142,9 +141,9 @@ type ReceiptForStorage Receipt
// EncodeRLP implements rlp.Encoder, and flattens all content fields of a receipt
// into an RLP stream.
func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
logs := make([]*vm.LogForStorage, len(r.Logs))
logs := make([]*LogForStorage, len(r.Logs))
for i, log := range r.Logs {
logs[i] = (*vm.LogForStorage)(log)
logs[i] = (*LogForStorage)(log)
}
return rlp.Encode(w, []interface{}{r.PostState, r.CumulativeGasUsed, r.Bloom, r.TxHash, r.ContractAddress, logs, r.GasUsed})
}
@@ -158,7 +157,7 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
Bloom Bloom
TxHash common.Hash
ContractAddress common.Address
Logs []*vm.LogForStorage
Logs []*LogForStorage
GasUsed *big.Int
}
if err := s.Decode(&receipt); err != nil {
@@ -166,9 +165,9 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
}
// Assign the consensus fields
r.PostState, r.CumulativeGasUsed, r.Bloom = receipt.PostState, receipt.CumulativeGasUsed, receipt.Bloom
r.Logs = make(vm.Logs, len(receipt.Logs))
r.Logs = make([]*Log, len(receipt.Logs))
for i, log := range receipt.Logs {
r.Logs[i] = (*vm.Log)(log)
r.Logs[i] = (*Log)(log)
}
// Assign the implementation fields
r.TxHash, r.ContractAddress, r.GasUsed = receipt.TxHash, receipt.ContractAddress, receipt.GasUsed

Some files were not shown because too many files have changed in this diff Show More