Merge pull request #3074 from karalabe/release/1.4

Geth 1.4.15 "Come at me bro"
pull/3075/head
Péter Szilágyi 8 years ago committed by GitHub
commit 1639f1174e
  1. 2
      .travis.yml
  2. 28
      Makefile
  3. 2
      VERSION
  4. 29
      build/ci-notes.md
  5. 189
      build/ci.go
  6. 2
      build/deb.changelog
  7. 2
      build/deb.control
  8. 2
      build/deb.rules
  9. 5
      cmd/evm/main.go
  10. 10
      cmd/geth/main.go
  11. 16
      core/execution.go
  12. 32
      core/state/state_object.go
  13. 21
      core/state/state_test.go
  14. 11
      core/state/statedb.go
  15. 9
      core/state/statedb_test.go
  16. 2
      core/state/sync_test.go
  17. 11
      core/vm/contract.go
  18. 3
      core/vm/environment.go
  19. 2
      core/vm/jit_test.go
  20. 2
      core/vm/logger_test.go
  21. 2
      core/vm/runtime/runtime.go
  22. 9
      core/vm/vm.go
  23. 116
      internal/build/env.go
  24. 14
      internal/build/util.go
  25. 3
      light/state_test.go
  26. 3
      tests/block_test_util.go
  27. 5
      tests/util.go
  28. 3
      trie/trie.go
  29. 159
      trie/trie_test.go

@ -27,7 +27,7 @@ matrix:
- debhelper - debhelper
- dput - dput
script: script:
- go run build/ci.go travis-debsrc - go run build/ci.go debsrc -signer "Felix Lange (Geth CI Testing Key) <fjl@twurst.com>" -upload ppa:lp-fjl/geth-ci-testing
install: install:
- go get golang.org/x/tools/cmd/cover - go get golang.org/x/tools/cmd/cover

@ -42,12 +42,12 @@ geth-linux: geth-linux-386 geth-linux-amd64 geth-linux-arm geth-linux-mips64 get
@ls -ld $(GOBIN)/geth-linux-* @ls -ld $(GOBIN)/geth-linux-*
geth-linux-386: geth-linux-386:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/386 -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=linux/386 -v ./cmd/geth
@echo "Linux 386 cross compilation done:" @echo "Linux 386 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep 386 @ls -ld $(GOBIN)/geth-linux-* | grep 386
geth-linux-amd64: geth-linux-amd64:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/amd64 -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=linux/amd64 -v ./cmd/geth
@echo "Linux amd64 cross compilation done:" @echo "Linux amd64 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep amd64 @ls -ld $(GOBIN)/geth-linux-* | grep amd64
@ -56,32 +56,32 @@ geth-linux-arm: geth-linux-arm-5 geth-linux-arm-6 geth-linux-arm-7 geth-linux-ar
@ls -ld $(GOBIN)/geth-linux-* | grep arm @ls -ld $(GOBIN)/geth-linux-* | grep arm
geth-linux-arm-5: geth-linux-arm-5:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/arm-5 -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=linux/arm-5 -v ./cmd/geth
@echo "Linux ARMv5 cross compilation done:" @echo "Linux ARMv5 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep arm-5 @ls -ld $(GOBIN)/geth-linux-* | grep arm-5
geth-linux-arm-6: geth-linux-arm-6:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/arm-6 -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=linux/arm-6 -v ./cmd/geth
@echo "Linux ARMv6 cross compilation done:" @echo "Linux ARMv6 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep arm-6 @ls -ld $(GOBIN)/geth-linux-* | grep arm-6
geth-linux-arm-7: geth-linux-arm-7:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/arm-7 -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=linux/arm-7 -v ./cmd/geth
@echo "Linux ARMv7 cross compilation done:" @echo "Linux ARMv7 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep arm-7 @ls -ld $(GOBIN)/geth-linux-* | grep arm-7
geth-linux-arm64: geth-linux-arm64:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/arm64 -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=linux/arm64 -v ./cmd/geth
@echo "Linux ARM64 cross compilation done:" @echo "Linux ARM64 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep arm64 @ls -ld $(GOBIN)/geth-linux-* | grep arm64
geth-linux-mips64: geth-linux-mips64:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/mips64 -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=linux/mips64 -v ./cmd/geth
@echo "Linux MIPS64 cross compilation done:" @echo "Linux MIPS64 cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep mips64 @ls -ld $(GOBIN)/geth-linux-* | grep mips64
geth-linux-mips64le: geth-linux-mips64le:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=linux/mips64le -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=linux/mips64le -v ./cmd/geth
@echo "Linux MIPS64le cross compilation done:" @echo "Linux MIPS64le cross compilation done:"
@ls -ld $(GOBIN)/geth-linux-* | grep mips64le @ls -ld $(GOBIN)/geth-linux-* | grep mips64le
@ -90,12 +90,12 @@ geth-darwin: geth-darwin-386 geth-darwin-amd64
@ls -ld $(GOBIN)/geth-darwin-* @ls -ld $(GOBIN)/geth-darwin-*
geth-darwin-386: geth-darwin-386:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=darwin/386 -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=darwin/386 -v ./cmd/geth
@echo "Darwin 386 cross compilation done:" @echo "Darwin 386 cross compilation done:"
@ls -ld $(GOBIN)/geth-darwin-* | grep 386 @ls -ld $(GOBIN)/geth-darwin-* | grep 386
geth-darwin-amd64: geth-darwin-amd64:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=darwin/amd64 -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=darwin/amd64 -v ./cmd/geth
@echo "Darwin amd64 cross compilation done:" @echo "Darwin amd64 cross compilation done:"
@ls -ld $(GOBIN)/geth-darwin-* | grep amd64 @ls -ld $(GOBIN)/geth-darwin-* | grep amd64
@ -104,21 +104,21 @@ geth-windows: geth-windows-386 geth-windows-amd64
@ls -ld $(GOBIN)/geth-windows-* @ls -ld $(GOBIN)/geth-windows-*
geth-windows-386: geth-windows-386:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=windows/386 -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=windows/386 -v ./cmd/geth
@echo "Windows 386 cross compilation done:" @echo "Windows 386 cross compilation done:"
@ls -ld $(GOBIN)/geth-windows-* | grep 386 @ls -ld $(GOBIN)/geth-windows-* | grep 386
geth-windows-amd64: geth-windows-amd64:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=windows/amd64 -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=windows/amd64 -v ./cmd/geth
@echo "Windows amd64 cross compilation done:" @echo "Windows amd64 cross compilation done:"
@ls -ld $(GOBIN)/geth-windows-* | grep amd64 @ls -ld $(GOBIN)/geth-windows-* | grep amd64
geth-android: geth-android:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=android-21/aar -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=android-21/aar -v ./cmd/geth
@echo "Android cross compilation done:" @echo "Android cross compilation done:"
@ls -ld $(GOBIN)/geth-android-* @ls -ld $(GOBIN)/geth-android-*
geth-ios: geth-ios:
build/env.sh go run build/ci.go xgo --go=$(GO) --dest=$(GOBIN) --targets=ios-7.0/framework -v ./cmd/geth build/env.sh go run build/ci.go xgo -- --go=$(GO) --dest=$(GOBIN) --targets=ios-7.0/framework -v ./cmd/geth
@echo "iOS framework cross compilation done:" @echo "iOS framework cross compilation done:"
@ls -ld $(GOBIN)/geth-ios-* @ls -ld $(GOBIN)/geth-ios-*

@ -1 +1 @@
1.4.14 1.4.15

@ -1,5 +1,4 @@
Debian Packaging # Debian Packaging
----------------
Tagged releases and develop branch commits are available as installable Debian packages Tagged releases and develop branch commits are available as installable Debian packages
for Ubuntu. Packages are built for the all Ubuntu versions which are supported by for Ubuntu. Packages are built for the all Ubuntu versions which are supported by
@ -8,6 +7,7 @@ Canonical:
- Trusty Tahr (14.04 LTS) - Trusty Tahr (14.04 LTS)
- Wily Werewolf (15.10) - Wily Werewolf (15.10)
- Xenial Xerus (16.04 LTS) - Xenial Xerus (16.04 LTS)
- Yakkety Yak (16.10)
Packages of develop branch commits have suffix -unstable and cannot be installed alongside Packages of develop branch commits have suffix -unstable and cannot be installed alongside
the stable version. Switching between release streams requires user intervention. the stable version. Switching between release streams requires user intervention.
@ -21,6 +21,29 @@ variable which Travis CI makes available to certain builds.
We want to build go-ethereum with the most recent version of Go, irrespective of the Go We want to build go-ethereum with the most recent version of Go, irrespective of the Go
version that is available in the main Ubuntu repository. In order to make this possible, version that is available in the main Ubuntu repository. In order to make this possible,
our PPA depends on the ~gophers/ubuntu/archive PPA. Our source package build-depends on our PPA depends on the ~gophers/ubuntu/archive PPA. Our source package build-depends on
golang-1.6, which is co-installable alongside the regular golang package. PPA dependencies golang-1.7, which is co-installable alongside the regular golang package. PPA dependencies
can be edited at https://launchpad.net/%7Elp-fjl/+archive/ubuntu/geth-ci-testing/+edit-dependencies can be edited at https://launchpad.net/%7Elp-fjl/+archive/ubuntu/geth-ci-testing/+edit-dependencies
## Building Packages Locally (for testing)
You need to run Ubuntu to do test packaging.
Add the gophers PPA and install Go 1.7 and Debian packaging tools:
$ sudo apt-add-repository ppa:gophers/ubuntu/archive
$ sudo apt-get update
$ sudo apt-get install build-essential golang-1.7 devscripts debhelper
Create the source packages:
$ go run build/ci.go debsrc -workdir dist
Then go into the source package directory for your running distribution and build the package:
$ cd dist/ethereum-unstable-1.5.0+xenial
$ dpkg-buildpackage
Built packages are placed in the dist/ directory.
$ cd ..
$ dpkg-deb -c geth-unstable_1.5.0+xenial_amd64.deb

@ -120,8 +120,6 @@ func main() {
doArchive(os.Args[2:]) doArchive(os.Args[2:])
case "debsrc": case "debsrc":
doDebianSource(os.Args[2:]) doDebianSource(os.Args[2:])
case "travis-debsrc":
doTravisDebianSource(os.Args[2:])
case "xgo": case "xgo":
doXgo(os.Args[2:]) doXgo(os.Args[2:])
default: default:
@ -132,8 +130,8 @@ func main() {
// Compiling // Compiling
func doInstall(cmdline []string) { func doInstall(cmdline []string) {
commitHash := flag.String("gitcommit", "", "Git commit hash embedded into binary.")
flag.CommandLine.Parse(cmdline) flag.CommandLine.Parse(cmdline)
env := build.Env()
// Check Go version. People regularly open issues about compilation // Check Go version. People regularly open issues about compilation
// failure with outdated Go. This should save them the trouble. // failure with outdated Go. This should save them the trouble.
@ -150,13 +148,17 @@ func doInstall(cmdline []string) {
packages = flag.Args() packages = flag.Args()
} }
goinstall := goTool("install", makeBuildFlags(*commitHash)...) goinstall := goTool("install", buildFlags(env)...)
goinstall.Args = append(goinstall.Args, "-v") goinstall.Args = append(goinstall.Args, "-v")
goinstall.Args = append(goinstall.Args, packages...) goinstall.Args = append(goinstall.Args, packages...)
build.MustRun(goinstall) build.MustRun(goinstall)
} }
func makeBuildFlags(commitHash string) (flags []string) { func buildFlags(env build.Environment) (flags []string) {
if os.Getenv("GO_OPENCL") != "" {
flags = append(flags, "-tags", "opencl")
}
// Since Go 1.5, the separator char for link time assignments // Since Go 1.5, the separator char for link time assignments
// is '=' and using ' ' prints a warning. However, Go < 1.5 does // is '=' and using ' ' prints a warning. However, Go < 1.5 does
// not support using '='. // not support using '='.
@ -164,26 +166,9 @@ func makeBuildFlags(commitHash string) (flags []string) {
if runtime.Version() > "go1.5" || strings.Contains(runtime.Version(), "devel") { if runtime.Version() > "go1.5" || strings.Contains(runtime.Version(), "devel") {
sep = "=" sep = "="
} }
// Set gitCommit constant via link-time assignment.
if os.Getenv("GO_OPENCL") != "" { if env.Commit != "" {
flags = append(flags, "-tags", "opencl") flags = append(flags, "-ldflags", "-X main.gitCommit"+sep+env.Commit)
}
// Set gitCommit constant via link-time assignment. If this is a git checkout, we can
// just get the current commit hash through git. Otherwise we fall back to the hash
// that was passed as -gitcommit.
//
// -gitcommit is required for Debian package builds. The source package doesn't
// contain .git but we still want to embed the commit hash into the packaged binary.
// The hash is rendered into the debian/rules build script when the source package is
// created.
if _, err := os.Stat(filepath.Join(".git", "HEAD")); !os.IsNotExist(err) {
if c := build.GitCommit(); c != "" {
commitHash = c
}
}
if commitHash != "" {
flags = append(flags, "-ldflags", "-X main.gitCommit"+sep+commitHash)
} }
return flags return flags
} }
@ -253,7 +238,11 @@ func doArchive(cmdline []string) {
default: default:
log.Fatal("unknown archive type: ", atype) log.Fatal("unknown archive type: ", atype)
} }
base := makeArchiveBasename()
env := build.Env()
maybeSkipArchive(env)
base := archiveBasename(env)
if err := build.WriteArchive("geth-"+base, ext, gethArchiveFiles); err != nil { if err := build.WriteArchive("geth-"+base, ext, gethArchiveFiles); err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -262,36 +251,41 @@ func doArchive(cmdline []string) {
} }
} }
func makeArchiveBasename() string { func archiveBasename(env build.Environment) string {
// date := time.Now().UTC().Format("200601021504") // date := time.Now().UTC().Format("200601021504")
platform := runtime.GOOS + "-" + runtime.GOARCH platform := runtime.GOOS + "-" + runtime.GOARCH
archive := platform + "-" + build.VERSION() archive := platform + "-" + build.VERSION()
if commit := build.GitCommit(); commit != "" { if env.Commit != "" {
archive += "-" + commit[:8] archive += "-" + env.Commit[:8]
} }
return archive return archive
} }
// skips archiving for some build configurations.
func maybeSkipArchive(env build.Environment) {
if env.IsPullRequest {
log.Printf("skipping because this is a PR build")
os.Exit(0)
}
if env.Branch != "develop" && !strings.HasPrefix(env.Tag, "v1.") {
log.Printf("skipping because branch %q, tag %q is not on the whitelist", env.Branch, env.Tag)
os.Exit(0)
}
}
// Debian Packaging // Debian Packaging
// CLI entry point for Travis CI. func doDebianSource(cmdline []string) {
func doTravisDebianSource(cmdline []string) { var (
signer = flag.String("signer", "", `Signing key name, also used as package author`)
upload = flag.String("upload", "", `Where to upload the source package (usually "ppa:ethereum/ethereum")`)
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
now = time.Now()
)
flag.CommandLine.Parse(cmdline) flag.CommandLine.Parse(cmdline)
*workdir = makeWorkdir(*workdir)
// Package only whitelisted branches. env := build.Env()
switch { maybeSkipArchive(env)
case os.Getenv("TRAVIS_REPO_SLUG") != "ethereum/go-ethereum":
log.Printf("skipping because this is a fork build")
return
case os.Getenv("TRAVIS_PULL_REQUEST") != "false":
log.Printf("skipping because this is a PR build")
return
case os.Getenv("TRAVIS_BRANCH") != "develop" && !strings.HasPrefix(os.Getenv("TRAVIS_TAG"), "v1."):
log.Printf("skipping because branch %q tag %q is not on the whitelist",
os.Getenv("TRAVIS_BRANCH"),
os.Getenv("TRAVIS_TAG"))
return
}
// Import the signing key. // Import the signing key.
if b64key := os.Getenv("PPA_SIGNING_KEY"); b64key != "" { if b64key := os.Getenv("PPA_SIGNING_KEY"); b64key != "" {
@ -304,46 +298,16 @@ func doTravisDebianSource(cmdline []string) {
build.MustRun(gpg) build.MustRun(gpg)
} }
// Assign unstable status to non-tag builds. // Create the packages.
unstable := "true"
if os.Getenv("TRAVIS_BRANCH") != "develop" && os.Getenv("TRAVIS_TAG") != "" {
unstable = "false"
}
doDebianSource([]string{
"-signer", "Felix Lange (Geth CI Testing Key) <fjl@twurst.com>",
"-buildnum", os.Getenv("TRAVIS_BUILD_NUMBER"),
"-upload", "ppa:lp-fjl/geth-ci-testing",
"-unstable", unstable,
})
}
// CLI entry point for doing packaging locally.
func doDebianSource(cmdline []string) {
var (
signer = flag.String("signer", "", `Signing key name, also used as package author`)
upload = flag.String("upload", "", `Where to upload the source package (usually "ppa:ethereum/ethereum")`)
buildnum = flag.String("buildnum", "", `Build number (included in version)`)
unstable = flag.Bool("unstable", false, `Use package name suffix "-unstable"`)
now = time.Now()
)
flag.CommandLine.Parse(cmdline)
// Create the debian worktree in /tmp.
tmpdir, err := ioutil.TempDir("", "eth-deb-build-")
if err != nil {
log.Fatal(err)
}
for _, distro := range debDistros { for _, distro := range debDistros {
meta := newDebMetadata(distro, *signer, *buildnum, *unstable, now) meta := newDebMetadata(distro, *signer, env, now)
pkgdir := stageDebianSource(tmpdir, meta) pkgdir := stageDebianSource(*workdir, meta)
debuild := exec.Command("debuild", "-S", "-sa", "-us", "-uc") debuild := exec.Command("debuild", "-S", "-sa", "-us", "-uc")
debuild.Dir = pkgdir debuild.Dir = pkgdir
build.MustRun(debuild) build.MustRun(debuild)
changes := fmt.Sprintf("%s_%s_source.changes", meta.Name(), meta.VersionString()) changes := fmt.Sprintf("%s_%s_source.changes", meta.Name(), meta.VersionString())
changes = filepath.Join(tmpdir, changes) changes = filepath.Join(*workdir, changes)
if *signer != "" { if *signer != "" {
build.MustRunCommand("debsign", changes) build.MustRunCommand("debsign", changes)
} }
@ -353,35 +317,53 @@ func doDebianSource(cmdline []string) {
} }
} }
type debExecutable struct { func makeWorkdir(wdflag string) string {
Name, Description string var err error
if wdflag != "" {
err = os.MkdirAll(wdflag, 0744)
} else {
wdflag, err = ioutil.TempDir("", "eth-deb-build-")
}
if err != nil {
log.Fatal(err)
}
return wdflag
}
func isUnstableBuild(env build.Environment) bool {
if env.Branch != "develop" && env.Tag != "" {
return false
}
return true
} }
type debMetadata struct { type debMetadata struct {
Env build.Environment
// go-ethereum version being built. Note that this // go-ethereum version being built. Note that this
// is not the debian package version. The package version // is not the debian package version. The package version
// is constructed by VersionString. // is constructed by VersionString.
Version string Version string
Author string // "name <email>", also selects signing key Author string // "name <email>", also selects signing key
Buildnum string // build number Distro, Time string
Distro, Commit, Time string Executables []debExecutable
Executables []debExecutable
Unstable bool
} }
func newDebMetadata(distro, author, buildnum string, unstable bool, t time.Time) debMetadata { type debExecutable struct {
Name, Description string
}
func newDebMetadata(distro, author string, env build.Environment, t time.Time) debMetadata {
if author == "" { if author == "" {
// No signing key, use default author. // No signing key, use default author.
author = "Ethereum Builds <fjl@ethereum.org>" author = "Ethereum Builds <fjl@ethereum.org>"
} }
return debMetadata{ return debMetadata{
Unstable: unstable, Env: env,
Author: author, Author: author,
Distro: distro, Distro: distro,
Commit: build.GitCommit(),
Version: build.VERSION(), Version: build.VERSION(),
Buildnum: buildnum,
Time: t.Format(time.RFC1123Z), Time: t.Format(time.RFC1123Z),
Executables: debExecutables, Executables: debExecutables,
} }
@ -390,7 +372,7 @@ func newDebMetadata(distro, author, buildnum string, unstable bool, t time.Time)
// Name returns the name of the metapackage that depends // Name returns the name of the metapackage that depends
// on all executable packages. // on all executable packages.
func (meta debMetadata) Name() string { func (meta debMetadata) Name() string {
if meta.Unstable { if isUnstableBuild(meta.Env) {
return "ethereum-unstable" return "ethereum-unstable"
} }
return "ethereum" return "ethereum"
@ -399,8 +381,8 @@ func (meta debMetadata) Name() string {
// VersionString returns the debian version of the packages. // VersionString returns the debian version of the packages.
func (meta debMetadata) VersionString() string { func (meta debMetadata) VersionString() string {
vsn := meta.Version vsn := meta.Version
if meta.Buildnum != "" { if meta.Env.Buildnum != "" {
vsn += "+build" + meta.Buildnum vsn += "+build" + meta.Env.Buildnum
} }
if meta.Distro != "" { if meta.Distro != "" {
vsn += "+" + meta.Distro vsn += "+" + meta.Distro
@ -419,7 +401,7 @@ func (meta debMetadata) ExeList() string {
// ExeName returns the package name of an executable package. // ExeName returns the package name of an executable package.
func (meta debMetadata) ExeName(exe debExecutable) string { func (meta debMetadata) ExeName(exe debExecutable) string {
if meta.Unstable { if isUnstableBuild(meta.Env) {
return exe.Name + "-unstable" return exe.Name + "-unstable"
} }
return exe.Name return exe.Name
@ -428,7 +410,7 @@ func (meta debMetadata) ExeName(exe debExecutable) string {
// ExeConflicts returns the content of the Conflicts field // ExeConflicts returns the content of the Conflicts field
// for executable packages. // for executable packages.
func (meta debMetadata) ExeConflicts(exe debExecutable) string { func (meta debMetadata) ExeConflicts(exe debExecutable) string {
if meta.Unstable { if isUnstableBuild(meta.Env) {
// Set up the conflicts list so that the *-unstable packages // Set up the conflicts list so that the *-unstable packages
// cannot be installed alongside the regular version. // cannot be installed alongside the regular version.
// //
@ -461,8 +443,8 @@ func stageDebianSource(tmpdir string, meta debMetadata) (pkgdir string) {
build.RenderString("8\n", filepath.Join(debian, "compat"), 0644, meta) build.RenderString("8\n", filepath.Join(debian, "compat"), 0644, meta)
build.RenderString("3.0 (native)\n", filepath.Join(debian, "source/format"), 0644, meta) build.RenderString("3.0 (native)\n", filepath.Join(debian, "source/format"), 0644, meta)
for _, exe := range meta.Executables { for _, exe := range meta.Executables {
install := filepath.Join(debian, exe.Name+".install") install := filepath.Join(debian, meta.ExeName(exe)+".install")
docs := filepath.Join(debian, exe.Name+".docs") docs := filepath.Join(debian, meta.ExeName(exe)+".docs")
build.Render("build/deb.install", install, 0644, exe) build.Render("build/deb.install", install, 0644, exe)
build.Render("build/deb.docs", docs, 0644, exe) build.Render("build/deb.docs", docs, 0644, exe)
} }
@ -473,18 +455,19 @@ func stageDebianSource(tmpdir string, meta debMetadata) (pkgdir string) {
// Cross compilation // Cross compilation
func doXgo(cmdline []string) { func doXgo(cmdline []string) {
flag.CommandLine.Parse(cmdline)
env := build.Env()
// Make sure xgo is available for cross compilation // Make sure xgo is available for cross compilation
gogetxgo := goTool("get", "github.com/karalabe/xgo") gogetxgo := goTool("get", "github.com/karalabe/xgo")
build.MustRun(gogetxgo) build.MustRun(gogetxgo)
// Execute the actual cross compilation // Execute the actual cross compilation
pkg := cmdline[len(cmdline)-1] xgo := xgoTool(append(buildFlags(env), flag.Args()...))
args := append(cmdline[:len(cmdline)-1], makeBuildFlags("")...) build.MustRun(xgo)
build.MustRun(xgoTool(append(args, pkg)...))
} }
func xgoTool(args ...string) *exec.Cmd { func xgoTool(args []string) *exec.Cmd {
cmd := exec.Command(filepath.Join(GOBIN, "xgo"), args...) cmd := exec.Command(filepath.Join(GOBIN, "xgo"), args...)
cmd.Env = []string{ cmd.Env = []string{
"GOPATH=" + build.GOPATH(), "GOPATH=" + build.GOPATH(),

@ -1,5 +1,5 @@
{{.Name}} ({{.VersionString}}) {{.Distro}}; urgency=low {{.Name}} ({{.VersionString}}) {{.Distro}}; urgency=low
* git build of {{.Commit}} * git build of {{.Env.Commit}}
-- {{.Author}} {{.Time}} -- {{.Author}} {{.Time}}

@ -2,7 +2,7 @@ Source: {{.Name}}
Section: science Section: science
Priority: extra Priority: extra
Maintainer: {{.Author}} Maintainer: {{.Author}}
Build-Depends: debhelper (>= 8.0.0), golang-1.6 Build-Depends: debhelper (>= 8.0.0), golang-1.7
Standards-Version: 3.9.5 Standards-Version: 3.9.5
Homepage: https://ethereum.org Homepage: https://ethereum.org
Vcs-Git: git://github.com/ethereum/go-ethereum.git Vcs-Git: git://github.com/ethereum/go-ethereum.git

@ -5,7 +5,7 @@
#export DH_VERBOSE=1 #export DH_VERBOSE=1
override_dh_auto_build: override_dh_auto_build:
build/env.sh /usr/lib/go-1.6/bin/go run build/ci.go install -gitcommit {{.Commit}} build/env.sh /usr/lib/go-1.7/bin/go run build/ci.go install -git-commit={{.Env.Commit}} -git-branch={{.Env.Branch}} -git-tag={{.Env.Tag}} -buildnum={{.Env.Buildnum}} -pull-request={{.Env.IsPullRequest}}
override_dh_auto_test: override_dh_auto_test:

@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
@ -141,7 +142,9 @@ func run(ctx *cli.Context) error {
) )
} else { } else {
receiver := statedb.CreateAccount(common.StringToAddress("receiver")) receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
code := common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name))
receiver.SetCode(crypto.Keccak256Hash(code), code)
ret, err = vmenv.Call( ret, err = vmenv.Call(
sender, sender,
receiver.Address(), receiver.Address(),

@ -47,11 +47,11 @@ import (
) )
const ( const (
clientIdentifier = "Geth" // Client identifier to advertise over the network clientIdentifier = "Geth" // Client identifier to advertise over the network
versionMajor = 1 // Major version component of the current release versionMajor = 1 // Major version component of the current release
versionMinor = 4 // Minor version component of the current release versionMinor = 4 // Minor version component of the current release
versionPatch = 14 // Patch version component of the current release versionPatch = 15 // Patch version component of the current release
versionMeta = "prerelease" // Version metadata to append to the version string versionMeta = "stable" // Version metadata to append to the version string
versionOracle = "0xfa7b9770ca4cb04296cac84f37736d4041251cdf" // Ethereum address of the Geth release oracle versionOracle = "0xfa7b9770ca4cb04296cac84f37736d4041251cdf" // Ethereum address of the Geth release oracle
) )

@ -27,14 +27,14 @@ import (
// Call executes within the given contract // 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) { func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
ret, _, err = exec(env, caller, &addr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value) ret, _, err = exec(env, caller, &addr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, value)
return ret, err return ret, err
} }
// CallCode executes the given address' code as the given contract address // 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) { func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
callerAddr := caller.Address() callerAddr := caller.Address()
ret, _, err = exec(env, caller, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, value) ret, _, err = exec(env, caller, &callerAddr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, value)
return ret, err return ret, err
} }
@ -43,13 +43,13 @@ func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address
callerAddr := caller.Address() callerAddr := caller.Address()
originAddr := env.Origin() originAddr := env.Origin()
callerValue := caller.Value() callerValue := caller.Value()
ret, _, err = execDelegateCall(env, caller, &originAddr, &callerAddr, &addr, input, env.Db().GetCode(addr), gas, gasPrice, callerValue) ret, _, err = execDelegateCall(env, caller, &originAddr, &callerAddr, &addr, env.Db().GetCodeHash(addr), input, env.Db().GetCode(addr), gas, gasPrice, callerValue)
return ret, err return ret, err
} }
// Create creates a new contract with the given code // 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) { func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) {
ret, address, err = exec(env, caller, nil, nil, nil, code, gas, gasPrice, value) ret, address, err = exec(env, caller, nil, nil, crypto.Keccak256Hash(code), nil, code, gas, gasPrice, value)
// Here we get an error if we run into maximum stack depth, // Here we get an error if we run into maximum stack depth,
// See: https://github.com/ethereum/yellowpaper/pull/131 // See: https://github.com/ethereum/yellowpaper/pull/131
// and YP definitions for CREATE instruction // and YP definitions for CREATE instruction
@ -59,7 +59,7 @@ func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPric
return ret, address, err return ret, address, err
} }
func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) { func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
evm := env.Vm() evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the // Depth check execution. Fail if we're trying to execute above the
// limit. // limit.
@ -105,7 +105,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
// EVM. The contract is a scoped environment for this execution context // EVM. The contract is a scoped environment for this execution context
// only. // only.
contract := vm.NewContract(caller, to, value, gas, gasPrice) contract := vm.NewContract(caller, to, value, gas, gasPrice)
contract.SetCallCode(codeAddr, code) contract.SetCallCode(codeAddr, codeHash, code)
defer contract.Finalise() defer contract.Finalise()
ret, err = evm.Run(contract, input) ret, err = evm.Run(contract, input)
@ -135,7 +135,7 @@ func exec(env vm.Environment, caller vm.ContractRef, address, codeAddr *common.A
return ret, addr, err return ret, addr, err
} }
func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) { func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toAddr, codeAddr *common.Address, codeHash common.Hash, input, code []byte, gas, gasPrice, value *big.Int) (ret []byte, addr common.Address, err error) {
evm := env.Vm() evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the // Depth check execution. Fail if we're trying to execute above the
// limit. // limit.
@ -155,7 +155,7 @@ func execDelegateCall(env vm.Environment, caller vm.ContractRef, originAddr, toA
// Iinitialise a new contract and make initialise the delegate values // Iinitialise a new contract and make initialise the delegate values
contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate() contract := vm.NewContract(caller, to, value, gas, gasPrice).AsDelegate()
contract.SetCallCode(codeAddr, code) contract.SetCallCode(codeAddr, codeHash, code)
defer contract.Finalise() defer contract.Finalise()
ret, err = evm.Run(contract, input) ret, err = evm.Run(contract, input)

@ -75,9 +75,11 @@ type StateObject struct {
dbErr error dbErr error
// Write caches. // Write caches.
trie *trie.SecureTrie // storage trie, which becomes non-nil on first access trie *trie.SecureTrie // storage trie, which becomes non-nil on first access
code Code // contract bytecode, which gets set when code is loaded code Code // contract bytecode, which gets set when code is loaded
storage Storage // Cached storage (flushed when updated)
cachedStorage Storage // Storage entry cache to avoid duplicate reads
dirtyStorage Storage // Storage entries that need to be flushed to disk
// Cache flags. // Cache flags.
// When an object is marked for deletion it will be delete from the trie // When an object is marked for deletion it will be delete from the trie
@ -105,7 +107,7 @@ func NewObject(address common.Address, data Account, onDirty func(addr common.Ad
if data.CodeHash == nil { if data.CodeHash == nil {
data.CodeHash = emptyCodeHash data.CodeHash = emptyCodeHash
} }
return &StateObject{address: address, data: data, storage: make(Storage), onDirty: onDirty} return &StateObject{address: address, data: data, cachedStorage: make(Storage), dirtyStorage: make(Storage), onDirty: onDirty}
} }
// EncodeRLP implements rlp.Encoder. // EncodeRLP implements rlp.Encoder.
@ -145,7 +147,7 @@ func (c *StateObject) getTrie(db trie.Database) *trie.SecureTrie {
// GetState returns a value in account storage. // GetState returns a value in account storage.
func (self *StateObject) GetState(db trie.Database, key common.Hash) common.Hash { func (self *StateObject) GetState(db trie.Database, key common.Hash) common.Hash {
value, exists := self.storage[key] value, exists := self.cachedStorage[key]
if exists { if exists {
return value return value
} }
@ -155,14 +157,16 @@ func (self *StateObject) GetState(db trie.Database, key common.Hash) common.Hash
rlp.DecodeBytes(tr.Get(key[:]), &ret) rlp.DecodeBytes(tr.Get(key[:]), &ret)
value = common.BytesToHash(ret) value = common.BytesToHash(ret)
if (value != common.Hash{}) { if (value != common.Hash{}) {
self.storage[key] = value self.cachedStorage[key] = value
} }
return value return value
} }
// SetState updates a value in account storage. // SetState updates a value in account storage.
func (self *StateObject) SetState(key, value common.Hash) { func (self *StateObject) SetState(key, value common.Hash) {
self.storage[key] = value self.cachedStorage[key] = value
self.dirtyStorage[key] = value
if self.onDirty != nil { if self.onDirty != nil {
self.onDirty(self.Address()) self.onDirty(self.Address())
self.onDirty = nil self.onDirty = nil
@ -172,7 +176,8 @@ func (self *StateObject) SetState(key, value common.Hash) {
// updateTrie writes cached storage modifications into the object's storage trie. // updateTrie writes cached storage modifications into the object's storage trie.
func (self *StateObject) updateTrie(db trie.Database) { func (self *StateObject) updateTrie(db trie.Database) {
tr := self.getTrie(db) tr := self.getTrie(db)
for key, value := range self.storage { for key, value := range self.dirtyStorage {
delete(self.dirtyStorage, key)
if (value == common.Hash{}) { if (value == common.Hash{}) {
tr.Delete(key[:]) tr.Delete(key[:])
continue continue
@ -241,7 +246,8 @@ func (self *StateObject) Copy(db trie.Database, onDirty func(addr common.Address
stateObject := NewObject(self.address, self.data, onDirty) stateObject := NewObject(self.address, self.data, onDirty)
stateObject.trie = self.trie stateObject.trie = self.trie
stateObject.code = self.code stateObject.code = self.code
stateObject.storage = self.storage.Copy() stateObject.dirtyStorage = self.dirtyStorage.Copy()
stateObject.cachedStorage = self.dirtyStorage.Copy()
stateObject.remove = self.remove stateObject.remove = self.remove
stateObject.dirtyCode = self.dirtyCode stateObject.dirtyCode = self.dirtyCode
stateObject.deleted = self.deleted stateObject.deleted = self.deleted
@ -273,9 +279,9 @@ func (self *StateObject) Code(db trie.Database) []byte {
return code return code
} }
func (self *StateObject) SetCode(code []byte) { func (self *StateObject) SetCode(codeHash common.Hash, code []byte) {
self.code = code self.code = code
self.data.CodeHash = crypto.Keccak256(code) self.data.CodeHash = codeHash[:]
self.dirtyCode = true self.dirtyCode = true
if self.onDirty != nil { if self.onDirty != nil {
self.onDirty(self.Address()) self.onDirty(self.Address())
@ -312,7 +318,7 @@ func (self *StateObject) Value() *big.Int {
func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) { func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) {
// When iterating over the storage check the cache first // When iterating over the storage check the cache first
for h, value := range self.storage { for h, value := range self.cachedStorage {
cb(h, value) cb(h, value)
} }
@ -320,7 +326,7 @@ func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) {
for it.Next() { for it.Next() {
// ignore cached values // ignore cached values
key := common.BytesToHash(self.trie.GetKey(it.Key)) key := common.BytesToHash(self.trie.GetKey(it.Key))
if _, ok := self.storage[key]; !ok { if _, ok := self.cachedStorage[key]; !ok {
cb(key, common.BytesToHash(it.Value)) cb(key, common.BytesToHash(it.Value))
} }
} }

@ -24,6 +24,7 @@ import (
checker "gopkg.in/check.v1" checker "gopkg.in/check.v1"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
) )
@ -40,7 +41,7 @@ func (s *StateSuite) TestDump(c *checker.C) {
obj1 := s.state.GetOrNewStateObject(toAddr([]byte{0x01})) obj1 := s.state.GetOrNewStateObject(toAddr([]byte{0x01}))
obj1.AddBalance(big.NewInt(22)) obj1.AddBalance(big.NewInt(22))
obj2 := s.state.GetOrNewStateObject(toAddr([]byte{0x01, 0x02})) obj2 := s.state.GetOrNewStateObject(toAddr([]byte{0x01, 0x02}))
obj2.SetCode([]byte{3, 3, 3, 3, 3, 3, 3}) obj2.SetCode(crypto.Keccak256Hash([]byte{3, 3, 3, 3, 3, 3, 3}), []byte{3, 3, 3, 3, 3, 3, 3})
obj3 := s.state.GetOrNewStateObject(toAddr([]byte{0x02})) obj3 := s.state.GetOrNewStateObject(toAddr([]byte{0x02}))
obj3.SetBalance(big.NewInt(44)) obj3.SetBalance(big.NewInt(44))
@ -148,7 +149,7 @@ func TestSnapshot2(t *testing.T) {
so0 := state.GetStateObject(stateobjaddr0) so0 := state.GetStateObject(stateobjaddr0)
so0.SetBalance(big.NewInt(42)) so0.SetBalance(big.NewInt(42))
so0.SetNonce(43) so0.SetNonce(43)
so0.SetCode([]byte{'c', 'a', 'f', 'e'}) so0.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e'}), []byte{'c', 'a', 'f', 'e'})
so0.remove = false so0.remove = false
so0.deleted = false so0.deleted = false
state.SetStateObject(so0) state.SetStateObject(so0)
@ -160,7 +161,7 @@ func TestSnapshot2(t *testing.T) {
so1 := state.GetStateObject(stateobjaddr1) so1 := state.GetStateObject(stateobjaddr1)
so1.SetBalance(big.NewInt(52)) so1.SetBalance(big.NewInt(52))
so1.SetNonce(53) so1.SetNonce(53)
so1.SetCode([]byte{'c', 'a', 'f', 'e', '2'}) so1.SetCode(crypto.Keccak256Hash([]byte{'c', 'a', 'f', 'e', '2'}), []byte{'c', 'a', 'f', 'e', '2'})
so1.remove = true so1.remove = true
so1.deleted = true so1.deleted = true
state.SetStateObject(so1) state.SetStateObject(so1)
@ -207,16 +208,16 @@ func compareStateObjects(so0, so1 *StateObject, t *testing.T) {
t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code) t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code)
} }
if len(so1.storage) != len(so0.storage) { if len(so1.cachedStorage) != len(so0.cachedStorage) {
t.Errorf("Storage size mismatch: have %d, want %d", len(so1.storage), len(so0.storage)) t.Errorf("Storage size mismatch: have %d, want %d", len(so1.cachedStorage), len(so0.cachedStorage))
} }
for k, v := range so1.storage { for k, v := range so1.cachedStorage {
if so0.storage[k] != v { if so0.cachedStorage[k] != v {
t.Errorf("Storage key %x mismatch: have %v, want %v", k, so0.storage[k], v) t.Errorf("Storage key %x mismatch: have %v, want %v", k, so0.cachedStorage[k], v)
} }
} }
for k, v := range so0.storage { for k, v := range so0.cachedStorage {
if so1.storage[k] != v { if so1.cachedStorage[k] != v {
t.Errorf("Storage key %x mismatch: have %v, want none.", k, v) t.Errorf("Storage key %x mismatch: have %v, want none.", k, v)
} }
} }

@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
@ -246,6 +247,14 @@ func (self *StateDB) GetCodeSize(addr common.Address) int {
return size return size
} }
func (self *StateDB) GetCodeHash(addr common.Address) common.Hash {
stateObject := self.GetStateObject(addr)
if stateObject == nil {
return common.Hash{}
}
return common.BytesToHash(stateObject.CodeHash())
}
func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash { func (self *StateDB) GetState(a common.Address, b common.Hash) common.Hash {
stateObject := self.GetStateObject(a) stateObject := self.GetStateObject(a)
if stateObject != nil { if stateObject != nil {
@ -283,7 +292,7 @@ func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
func (self *StateDB) SetCode(addr common.Address, code []byte) { func (self *StateDB) SetCode(addr common.Address, code []byte) {
stateObject := self.GetOrNewStateObject(addr) stateObject := self.GetOrNewStateObject(addr)
if stateObject != nil { if stateObject != nil {
stateObject.SetCode(code) stateObject.SetCode(crypto.Keccak256Hash(code), code)
} }
} }

@ -21,6 +21,7 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
) )
@ -40,7 +41,7 @@ func TestUpdateLeaks(t *testing.T) {
obj.SetState(common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i})) obj.SetState(common.BytesToHash([]byte{i, i, i}), common.BytesToHash([]byte{i, i, i, i}))
} }
if i%3 == 0 { if i%3 == 0 {
obj.SetCode([]byte{i, i, i, i, i}) obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i})
} }
state.UpdateStateObject(obj) state.UpdateStateObject(obj)
} }
@ -70,7 +71,7 @@ func TestIntermediateLeaks(t *testing.T) {
obj.SetState(common.BytesToHash([]byte{i, i, i, 0}), common.BytesToHash([]byte{i, i, i, i, 0})) obj.SetState(common.BytesToHash([]byte{i, i, i, 0}), common.BytesToHash([]byte{i, i, i, i, 0}))
} }
if i%3 == 0 { if i%3 == 0 {
obj.SetCode([]byte{i, i, i, i, i, 0}) obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i, 0}), []byte{i, i, i, i, i, 0})
} }
transState.UpdateStateObject(obj) transState.UpdateStateObject(obj)
@ -82,7 +83,7 @@ func TestIntermediateLeaks(t *testing.T) {
obj.SetState(common.BytesToHash([]byte{i, i, i, 1}), common.BytesToHash([]byte{i, i, i, i, 1})) obj.SetState(common.BytesToHash([]byte{i, i, i, 1}), common.BytesToHash([]byte{i, i, i, i, 1}))
} }
if i%3 == 0 { if i%3 == 0 {
obj.SetCode([]byte{i, i, i, i, i, 1}) obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i, 1}), []byte{i, i, i, i, i, 1})
} }
transState.UpdateStateObject(obj) transState.UpdateStateObject(obj)
@ -94,7 +95,7 @@ func TestIntermediateLeaks(t *testing.T) {
obj.SetState(common.BytesToHash([]byte{i, i, i, 1}), common.BytesToHash([]byte{i, i, i, i, 1})) obj.SetState(common.BytesToHash([]byte{i, i, i, 1}), common.BytesToHash([]byte{i, i, i, i, 1}))
} }
if i%3 == 0 { if i%3 == 0 {
obj.SetCode([]byte{i, i, i, i, i, 1}) obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i, 1}), []byte{i, i, i, i, i, 1})
} }
finalState.UpdateStateObject(obj) finalState.UpdateStateObject(obj)
} }

@ -54,7 +54,7 @@ func makeTestState() (ethdb.Database, common.Hash, []*testAccount) {
acc.nonce = uint64(42 * i) acc.nonce = uint64(42 * i)
if i%3 == 0 { if i%3 == 0 {
obj.SetCode([]byte{i, i, i, i, i}) obj.SetCode(crypto.Keccak256Hash([]byte{i, i, i, i, i}), []byte{i, i, i, i, i})
acc.code = []byte{i, i, i, i, i} acc.code = []byte{i, i, i, i, i}
} }
state.UpdateStateObject(obj) state.UpdateStateObject(obj)

@ -27,7 +27,7 @@ type ContractRef interface {
ReturnGas(*big.Int, *big.Int) ReturnGas(*big.Int, *big.Int)
Address() common.Address Address() common.Address
Value() *big.Int Value() *big.Int
SetCode([]byte) SetCode(common.Hash, []byte)
ForEachStorage(callback func(key, value common.Hash) bool) ForEachStorage(callback func(key, value common.Hash) bool)
} }
@ -44,8 +44,9 @@ type Contract struct {
jumpdests destinations // result of JUMPDEST analysis. jumpdests destinations // result of JUMPDEST analysis.
Code []byte Code []byte
Input []byte CodeHash common.Hash
CodeAddr *common.Address CodeAddr *common.Address
Input []byte
value, Gas, UsedGas, Price *big.Int value, Gas, UsedGas, Price *big.Int
@ -143,14 +144,16 @@ func (c *Contract) Value() *big.Int {
} }
// SetCode sets the code to the contract // SetCode sets the code to the contract
func (self *Contract) SetCode(code []byte) { func (self *Contract) SetCode(hash common.Hash, code []byte) {
self.Code = code self.Code = code
self.CodeHash = hash
} }
// SetCallCode sets the code of the contract and address of the backing data // SetCallCode sets the code of the contract and address of the backing data
// object // object
func (self *Contract) SetCallCode(addr *common.Address, code []byte) { func (self *Contract) SetCallCode(addr *common.Address, hash common.Hash, code []byte) {
self.Code = code self.Code = code
self.CodeHash = hash
self.CodeAddr = addr self.CodeAddr = addr
} }

@ -94,6 +94,7 @@ type Database interface {
GetNonce(common.Address) uint64 GetNonce(common.Address) uint64
SetNonce(common.Address, uint64) SetNonce(common.Address, uint64)
GetCodeHash(common.Address) common.Hash
GetCodeSize(common.Address) int GetCodeSize(common.Address) int
GetCode(common.Address) []byte GetCode(common.Address) []byte
SetCode(common.Address, []byte) SetCode(common.Address, []byte)
@ -118,7 +119,7 @@ type Account interface {
Balance() *big.Int Balance() *big.Int
Address() common.Address Address() common.Address
ReturnGas(*big.Int, *big.Int) ReturnGas(*big.Int, *big.Int)
SetCode([]byte) SetCode(common.Hash, []byte)
ForEachStorage(cb func(key, value common.Hash) bool) ForEachStorage(cb func(key, value common.Hash) bool)
Value() *big.Int Value() *big.Int
} }

@ -135,7 +135,7 @@ func (account) SetNonce(uint64) {}
func (account) Balance() *big.Int { return nil } func (account) Balance() *big.Int { return nil }
func (account) Address() common.Address { return common.Address{} } func (account) Address() common.Address { return common.Address{} }
func (account) ReturnGas(*big.Int, *big.Int) {} func (account) ReturnGas(*big.Int, *big.Int) {}
func (account) SetCode([]byte) {} func (account) SetCode(common.Hash, []byte) {}
func (account) ForEachStorage(cb func(key, value common.Hash) bool) {} func (account) ForEachStorage(cb func(key, value common.Hash) bool) {}
func runVmBench(test vmBench, b *testing.B) { func runVmBench(test vmBench, b *testing.B) {

@ -30,7 +30,7 @@ type dummyContractRef struct {
func (dummyContractRef) ReturnGas(*big.Int, *big.Int) {} func (dummyContractRef) ReturnGas(*big.Int, *big.Int) {}
func (dummyContractRef) Address() common.Address { return common.Address{} } func (dummyContractRef) Address() common.Address { return common.Address{} }
func (dummyContractRef) Value() *big.Int { return new(big.Int) } func (dummyContractRef) Value() *big.Int { return new(big.Int) }
func (dummyContractRef) SetCode([]byte) {} func (dummyContractRef) SetCode(common.Hash, []byte) {}
func (d *dummyContractRef) ForEachStorage(callback func(key, value common.Hash) bool) { func (d *dummyContractRef) ForEachStorage(callback func(key, value common.Hash) bool) {
d.calledForEach = true d.calledForEach = true
} }

@ -104,7 +104,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
receiver = cfg.State.CreateAccount(common.StringToAddress("contract")) receiver = cfg.State.CreateAccount(common.StringToAddress("contract"))
) )
// set the receiver's (the executing contract) code for execution. // set the receiver's (the executing contract) code for execution.
receiver.SetCode(code) receiver.SetCode(crypto.Keccak256Hash(code), code)
// Call the code with the given configuration. // Call the code with the given configuration.
ret, err := vmenv.Call( ret, err := vmenv.Call(

@ -79,10 +79,11 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
return nil, nil return nil, nil
} }
var ( codehash := contract.CodeHash // codehash is used when doing jump dest caching
codehash = crypto.Keccak256Hash(contract.Code) // codehash is used when doing jump dest caching if codehash == (common.Hash{}) {
program *Program codehash = crypto.Keccak256Hash(contract.Code)
) }
var program *Program
if evm.cfg.EnableJit { if evm.cfg.EnableJit {
// If the JIT is enabled check the status of the JIT program, // If the JIT is enabled check the status of the JIT program,
// if it doesn't exist compile a new program in a separate // if it doesn't exist compile a new program in a separate

@ -0,0 +1,116 @@
// 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 build
import (
"flag"
"fmt"
"os"
)
var (
// These flags override values in build env.
GitCommitFlag = flag.String("git-commit", "", `Overrides git commit hash embedded into executables`)
GitBranchFlag = flag.String("git-branch", "", `Overrides git branch being built`)
GitTagFlag = flag.String("git-tag", "", `Overrides git tag being built`)
BuildnumFlag = flag.String("buildnum", "", `Overrides CI build number`)
PullRequestFlag = flag.Bool("pull-request", false, `Overrides pull request status of the build`)
)
// Environment contains metadata provided by the build environment.
type Environment struct {
Name string // name of the environment
Repo string // name of GitHub repo
Commit, Branch, Tag string // Git info
Buildnum string
IsPullRequest bool
}
func (env Environment) String() string {
return fmt.Sprintf("%s env (commit:%s branch:%s tag:%s buildnum:%s pr:%t)",
env.Name, env.Commit, env.Branch, env.Tag, env.Buildnum, env.IsPullRequest)
}
// Env returns metadata about the current CI environment, falling back to LocalEnv
// if not running on CI.
func Env() Environment {
switch {
case os.Getenv("CI") == "true" && os.Getenv("TRAVIS") == "true":
return Environment{
Name: "travis",
Repo: os.Getenv("TRAVIS_REPO_SLUG"),
Commit: os.Getenv("TRAVIS_COMMIT"),
Branch: os.Getenv("TRAVIS_BRANCH"),
Tag: os.Getenv("TRAVIS_TAG"),
Buildnum: os.Getenv("TRAVIS_BUILD_NUMBER"),
IsPullRequest: os.Getenv("TRAVIS_PULL_REQUEST") != "false",
}
case os.Getenv("CI") == "True" && os.Getenv("APPVEYOR") == "True":
return Environment{
Name: "appveyor",
Repo: os.Getenv("APPVEYOR_REPO_NAME"),
Commit: os.Getenv("APPVEYOR_REPO_COMMIT"),
Branch: os.Getenv("APPVEYOR_REPO_BRANCH"),
Tag: os.Getenv("APPVEYOR_REPO_TAG"),
Buildnum: os.Getenv("APPVEYOR_BUILD_NUMBER"),
IsPullRequest: os.Getenv("APPVEYOR_PULL_REQUEST_NUMBER") != "",
}
default:
return LocalEnv()
}
}
// LocalEnv returns build environment metadata gathered from git.
func LocalEnv() Environment {
env := applyEnvFlags(Environment{Name: "local", Repo: "ethereum/go-ethereum"})
if _, err := os.Stat(".git"); err != nil {
return env
}
if env.Commit == "" {
env.Commit = RunGit("rev-parse", "HEAD")
}
if env.Branch == "" {
if b := RunGit("rev-parse", "--abbrev-ref", "HEAD"); b != "HEAD" {
env.Branch = b
}
}
// Note that we don't get the current git tag. It would slow down
// builds and isn't used by anything.
return env
}
func applyEnvFlags(env Environment) Environment {
if !flag.Parsed() {
panic("you need to call flag.Parse before Env or LocalEnv")
}
if *GitCommitFlag != "" {
env.Commit = *GitCommitFlag
}
if *GitBranchFlag != "" {
env.Branch = *GitBranchFlag
}
if *GitTagFlag != "" {
env.Tag = *GitTagFlag
}
if *BuildnumFlag != "" {
env.Buildnum = *BuildnumFlag
}
if *PullRequestFlag {
env.IsPullRequest = true
}
return env
}

@ -29,9 +29,7 @@ import (
"text/template" "text/template"
) )
var ( var DryRunFlag = flag.Bool("n", false, "dry run, don't execute commands")
DryRunFlag = flag.Bool("n", false, "dry run, don't execute commands")
)
// MustRun executes the given command and exits the host process for // MustRun executes the given command and exits the host process for
// any error. // any error.
@ -69,6 +67,7 @@ func GOPATH() string {
return strings.Join(newpath, string(filepath.ListSeparator)) return strings.Join(newpath, string(filepath.ListSeparator))
} }
// VERSION returns the content of the VERSION file.
func VERSION() string { func VERSION() string {
version, err := ioutil.ReadFile("VERSION") version, err := ioutil.ReadFile("VERSION")
if err != nil { if err != nil {
@ -77,10 +76,8 @@ func VERSION() string {
return string(bytes.TrimSpace(version)) return string(bytes.TrimSpace(version))
} }
func GitCommit() string { // RunGit runs a git subcommand and returns its output.
return RunGit("rev-parse", "HEAD") // The command must complete successfully.
}
func RunGit(args ...string) string { func RunGit(args ...string) string {
cmd := exec.Command("git", args...) cmd := exec.Command("git", args...)
var stdout, stderr bytes.Buffer var stdout, stderr bytes.Buffer
@ -94,12 +91,13 @@ func RunGit(args ...string) string {
return strings.TrimSpace(stdout.String()) return strings.TrimSpace(stdout.String())
} }
// Render renders the given template file. // Render renders the given template file into outputFile.
func Render(templateFile, outputFile string, outputPerm os.FileMode, x interface{}) { func Render(templateFile, outputFile string, outputPerm os.FileMode, x interface{}) {
tpl := template.Must(template.ParseFiles(templateFile)) tpl := template.Must(template.ParseFiles(templateFile))
render(tpl, outputFile, outputPerm, x) render(tpl, outputFile, outputPerm, x)
} }
// RenderString renders the given template string into outputFile.
func RenderString(templateContent, outputFile string, outputPerm os.FileMode, x interface{}) { func RenderString(templateContent, outputFile string, outputPerm os.FileMode, x interface{}) {
tpl := template.Must(template.New("").Parse(templateContent)) tpl := template.Must(template.New("").Parse(templateContent))
render(tpl, outputFile, outputPerm, x) render(tpl, outputFile, outputPerm, x)

@ -23,6 +23,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie" "github.com/ethereum/go-ethereum/trie"
"golang.org/x/net/context" "golang.org/x/net/context"
@ -60,7 +61,7 @@ func makeTestState() (common.Hash, ethdb.Database) {
so.SetNonce(100) so.SetNonce(100)
} }
so.AddBalance(big.NewInt(int64(i))) so.AddBalance(big.NewInt(int64(i)))
so.SetCode([]byte{i, i, i}) so.SetCode(crypto.Keccak256Hash([]byte{i, i, i}), []byte{i, i, i})
so.UpdateRoot(sdb) so.UpdateRoot(sdb)
st.UpdateStateObject(so) st.UpdateStateObject(so)
} }

@ -31,6 +31,7 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
@ -219,7 +220,7 @@ func (t *BlockTest) InsertPreState(db ethdb.Database) (*state.StateDB, error) {
return nil, err return nil, err
} }
obj := statedb.CreateAccount(common.HexToAddress(addrString)) obj := statedb.CreateAccount(common.HexToAddress(addrString))
obj.SetCode(code) obj.SetCode(crypto.Keccak256Hash(code), code)
obj.SetBalance(balance) obj.SetBalance(balance)
obj.SetNonce(nonce) obj.SetNonce(nonce)
for k, v := range acct.Storage { for k, v := range acct.Storage {

@ -108,12 +108,13 @@ func StateObjectFromAccount(db ethdb.Database, addr string, account Account, onD
account.Code = account.Code[2:] account.Code = account.Code[2:]
} }
code := common.Hex2Bytes(account.Code) code := common.Hex2Bytes(account.Code)
codeHash := crypto.Keccak256Hash(code)
obj := state.NewObject(common.HexToAddress(addr), state.Account{ obj := state.NewObject(common.HexToAddress(addr), state.Account{
Balance: common.Big(account.Balance), Balance: common.Big(account.Balance),
CodeHash: crypto.Keccak256(code), CodeHash: codeHash[:],
Nonce: common.Big(account.Nonce).Uint64(), Nonce: common.Big(account.Nonce).Uint64(),
}, onDirty) }, onDirty)
obj.SetCode(code) obj.SetCode(codeHash, code)
return obj return obj
} }

@ -374,6 +374,9 @@ func (t *Trie) delete(n node, prefix, key []byte) (bool, node, error) {
// n still contains at least two values and cannot be reduced. // n still contains at least two values and cannot be reduced.
return true, n, nil return true, n, nil
case valueNode:
return true, nil, nil
case nil: case nil:
return false, nil, nil return false, nil, nil

@ -21,8 +21,11 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"math/rand"
"os" "os"
"reflect"
"testing" "testing"
"testing/quick"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -297,41 +300,6 @@ func TestReplication(t *testing.T) {
} }
} }
func paranoiaCheck(t1 *Trie) (bool, *Trie) {
t2 := new(Trie)
it := NewIterator(t1)
for it.Next() {
t2.Update(it.Key, it.Value)
}
return t2.Hash() == t1.Hash(), t2
}
func TestParanoia(t *testing.T) {
t.Skip()
trie := newEmpty()
vals := []struct{ k, v string }{
{"do", "verb"},
{"ether", "wookiedoo"},
{"horse", "stallion"},
{"shaman", "horse"},
{"doge", "coin"},
{"ether", ""},
{"dog", "puppy"},
{"shaman", ""},
{"somethingveryoddindeedthis is", "myothernodedata"},
}
for _, val := range vals {
updateString(trie, val.k, val.v)
}
trie.Commit()
ok, t2 := paranoiaCheck(trie)
if !ok {
t.Errorf("trie paranoia check failed %x %x", trie.Hash(), t2.Hash())
}
}
// Not an actual test // Not an actual test
func TestOutput(t *testing.T) { func TestOutput(t *testing.T) {
t.Skip() t.Skip()
@ -356,7 +324,128 @@ func TestLargeValue(t *testing.T) {
trie.Update([]byte("key1"), []byte{99, 99, 99, 99}) trie.Update([]byte("key1"), []byte{99, 99, 99, 99})
trie.Update([]byte("key2"), bytes.Repeat([]byte{1}, 32)) trie.Update([]byte("key2"), bytes.Repeat([]byte{1}, 32))
trie.Hash() trie.Hash()
}
type randTestStep struct {
op int
key []byte // for opUpdate, opDelete, opGet
value []byte // for opUpdate
}
type randTest []randTestStep
const (
opUpdate = iota
opDelete
opGet
opCommit
opHash
opReset
opItercheckhash
opMax // boundary value, not an actual op
)
func (randTest) Generate(r *rand.Rand, size int) reflect.Value {
var allKeys [][]byte
genKey := func() []byte {
if len(allKeys) < 2 || r.Intn(100) < 10 {
// new key
key := make([]byte, r.Intn(50))
randRead(r, key)
allKeys = append(allKeys, key)
return key
}
// use existing key
return allKeys[r.Intn(len(allKeys))]
}
var steps randTest
for i := 0; i < size; i++ {
step := randTestStep{op: r.Intn(opMax)}
switch step.op {
case opUpdate:
step.key = genKey()
step.value = make([]byte, 8)
binary.BigEndian.PutUint64(step.value, uint64(i))
case opGet, opDelete:
step.key = genKey()
}
steps = append(steps, step)
}
return reflect.ValueOf(steps)
}
// rand.Rand provides a Read method in Go 1.7 and later, but
// we can't use it yet.
func randRead(r *rand.Rand, b []byte) {
pos := 0
val := 0
for n := 0; n < len(b); n++ {
if pos == 0 {
val = r.Int()
pos = 7
}
b[n] = byte(val)
val >>= 8
pos--
}
}
func runRandTest(rt randTest) bool {
db, _ := ethdb.NewMemDatabase()
tr, _ := New(common.Hash{}, db)
values := make(map[string]string) // tracks content of the trie
for _, step := range rt {
switch step.op {
case opUpdate:
tr.Update(step.key, step.value)
values[string(step.key)] = string(step.value)
case opDelete:
tr.Delete(step.key)
delete(values, string(step.key))
case opGet:
v := tr.Get(step.key)
want := values[string(step.key)]
if string(v) != want {
fmt.Printf("mismatch for key 0x%x, got 0x%x want 0x%x", step.key, v, want)
return false
}
case opCommit:
if _, err := tr.Commit(); err != nil {
panic(err)
}
case opHash:
tr.Hash()
case opReset:
hash, err := tr.Commit()
if err != nil {
panic(err)
}
newtr, err := New(hash, db)
if err != nil {
panic(err)
}
tr = newtr
case opItercheckhash:
checktr, _ := New(common.Hash{}, nil)
it := tr.Iterator()
for it.Next() {
checktr.Update(it.Key, it.Value)
}
if tr.Hash() != checktr.Hash() {
fmt.Println("hashes not equal")
return false
}
}
}
return true
}
func TestRandom(t *testing.T) {
if err := quick.Check(runRandTest, nil); err != nil {
t.Fatal(err)
}
} }
func BenchmarkGet(b *testing.B) { benchGet(b, false) } func BenchmarkGet(b *testing.B) { benchGet(b, false) }

Loading…
Cancel
Save