Patch for concurrent iterator & others (onto v1.11.6) #386
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@ -5,7 +5,6 @@ accounts/usbwallet @karalabe
|
||||
accounts/scwallet @gballet
|
||||
accounts/abi @gballet @MariusVanDerWijden
|
||||
cmd/clef @holiman
|
||||
cmd/puppeth @karalabe
|
||||
consensus @karalabe
|
||||
core/ @karalabe @holiman @rjl493456442
|
||||
eth/ @karalabe @holiman @rjl493456442
|
||||
@ -14,7 +13,6 @@ eth/tracers/ @s1na
|
||||
graphql/ @gballet @s1na
|
||||
les/ @zsfelfoldi @rjl493456442
|
||||
light/ @zsfelfoldi @rjl493456442
|
||||
mobile/ @karalabe @ligi
|
||||
node/ @fjl
|
||||
p2p/ @fjl @zsfelfoldi
|
||||
rpc/ @fjl @holiman
|
||||
|
69
.travis.yml
69
.travis.yml
@ -120,75 +120,6 @@ jobs:
|
||||
- go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc
|
||||
- go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
||||
|
||||
# This builder does the Android Maven and Azure uploads
|
||||
- stage: build
|
||||
if: type = push
|
||||
os: linux
|
||||
dist: bionic
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- openjdk-8-jdk
|
||||
env:
|
||||
- azure-android
|
||||
- maven-android
|
||||
- GO111MODULE=on
|
||||
git:
|
||||
submodules: false # avoid cloning ethereum/tests
|
||||
before_install:
|
||||
# Install Android and it's dependencies manually, Travis is stale
|
||||
- export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
|
||||
- curl https://dl.google.com/android/repository/commandlinetools-linux-6858069_latest.zip -o android.zip
|
||||
- unzip -q android.zip -d $HOME/sdk && rm android.zip
|
||||
- mv $HOME/sdk/cmdline-tools $HOME/sdk/latest && mkdir $HOME/sdk/cmdline-tools && mv $HOME/sdk/latest $HOME/sdk/cmdline-tools
|
||||
- export PATH=$PATH:$HOME/sdk/cmdline-tools/latest/bin
|
||||
- export ANDROID_HOME=$HOME/sdk
|
||||
|
||||
- yes | sdkmanager --licenses >/dev/null
|
||||
- sdkmanager "platform-tools" "platforms;android-15" "platforms;android-19" "platforms;android-24" "ndk-bundle"
|
||||
|
||||
# Install Go to allow building with
|
||||
- curl https://dl.google.com/go/go1.19.5.linux-amd64.tar.gz | tar -xz
|
||||
- export PATH=`pwd`/go/bin:$PATH
|
||||
- export GOROOT=`pwd`/go
|
||||
- export GOPATH=$HOME/go
|
||||
script:
|
||||
# Build the Android archive and upload it to Maven Central and Azure
|
||||
- mkdir -p $GOPATH/src/github.com/ethereum
|
||||
- ln -s `pwd` $GOPATH/src/github.com/ethereum/go-ethereum
|
||||
- go run build/ci.go aar -signer ANDROID_SIGNING_KEY -signify SIGNIFY_KEY -deploy https://oss.sonatype.org -upload gethstore/builds
|
||||
|
||||
# This builder does the OSX Azure, iOS CocoaPods and iOS Azure uploads
|
||||
- stage: build
|
||||
if: type = push
|
||||
os: osx
|
||||
go: 1.19.x
|
||||
env:
|
||||
- azure-osx
|
||||
- azure-ios
|
||||
- cocoapods-ios
|
||||
- GO111MODULE=on
|
||||
git:
|
||||
submodules: false # avoid cloning ethereum/tests
|
||||
script:
|
||||
- go run build/ci.go install -dlgo
|
||||
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify SIGNIFY_KEY -upload gethstore/builds
|
||||
|
||||
# Build the iOS framework and upload it to CocoaPods and Azure
|
||||
- gem uninstall cocoapods -a -x
|
||||
- gem install cocoapods
|
||||
|
||||
- mv ~/.cocoapods/repos/master ~/.cocoapods/repos/master.bak
|
||||
- sed -i '.bak' 's/repo.join/!repo.join/g' $(dirname `gem which cocoapods`)/cocoapods/sources_manager.rb
|
||||
- if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then git clone --depth=1 https://github.com/CocoaPods/Specs.git ~/.cocoapods/repos/master && pod setup --verbose; fi
|
||||
|
||||
- xctool -version
|
||||
- xcrun simctl list
|
||||
|
||||
# Workaround for https://github.com/golang/go/issues/23749
|
||||
- export CGO_CFLAGS_ALLOW='-fmodules|-fblocks|-fobjc-arc'
|
||||
- go run build/ci.go xcode -signer IOS_SIGNING_KEY -signify SIGNIFY_KEY -deploy trunk -upload gethstore/builds
|
||||
|
||||
# These builders run the tests
|
||||
- stage: build
|
||||
os: linux
|
||||
|
12
Makefile
12
Makefile
@ -16,18 +16,6 @@ geth:
|
||||
all:
|
||||
$(GORUN) build/ci.go install
|
||||
|
||||
android:
|
||||
$(GORUN) build/ci.go aar --local
|
||||
@echo "Done building."
|
||||
@echo "Import \"$(GOBIN)/geth.aar\" to use the library."
|
||||
@echo "Import \"$(GOBIN)/geth-sources.jar\" to add javadocs"
|
||||
@echo "For more info see https://stackoverflow.com/questions/20994336/android-studio-how-to-attach-javadoc"
|
||||
|
||||
ios:
|
||||
$(GORUN) build/ci.go xcode --local
|
||||
@echo "Done building."
|
||||
@echo "Import \"$(GOBIN)/Geth.framework\" to use the library."
|
||||
|
||||
test: all
|
||||
$(GORUN) build/ci.go test
|
||||
|
||||
|
@ -22,7 +22,6 @@ package bind
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"regexp"
|
||||
@ -39,8 +38,6 @@ type Lang int
|
||||
|
||||
const (
|
||||
LangGo Lang = iota
|
||||
LangJava
|
||||
LangObjC
|
||||
)
|
||||
|
||||
func isKeyWord(arg string) bool {
|
||||
@ -221,11 +218,6 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||
if evmABI.HasReceive() {
|
||||
receive = &tmplMethod{Original: evmABI.Receive}
|
||||
}
|
||||
// There is no easy way to pass arbitrary java objects to the Go side.
|
||||
if len(structs) > 0 && lang == LangJava {
|
||||
return "", errors.New("java binding for tuple arguments is not supported yet")
|
||||
}
|
||||
|
||||
contracts[types[i]] = &tmplContract{
|
||||
Type: capitalise(types[i]),
|
||||
InputABI: strings.ReplaceAll(strippedABI, "\"", "\\\""),
|
||||
@ -299,7 +291,6 @@ func Bind(types []string, abis []string, bytecodes []string, fsigs []map[string]
|
||||
// programming language types.
|
||||
var bindType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{
|
||||
LangGo: bindTypeGo,
|
||||
LangJava: bindTypeJava,
|
||||
}
|
||||
|
||||
// bindBasicTypeGo converts basic solidity types(except array, slice and tuple) to Go ones.
|
||||
@ -342,86 +333,10 @@ func bindTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||
}
|
||||
}
|
||||
|
||||
// bindBasicTypeJava converts basic solidity types(except array, slice and tuple) to Java ones.
|
||||
func bindBasicTypeJava(kind abi.Type) string {
|
||||
switch kind.T {
|
||||
case abi.AddressTy:
|
||||
return "Address"
|
||||
case abi.IntTy, abi.UintTy:
|
||||
// Note that uint and int (without digits) are also matched,
|
||||
// these are size 256, and will translate to BigInt (the default).
|
||||
parts := regexp.MustCompile(`(u)?int([0-9]*)`).FindStringSubmatch(kind.String())
|
||||
if len(parts) != 3 {
|
||||
return kind.String()
|
||||
}
|
||||
// All unsigned integers should be translated to BigInt since gomobile doesn't
|
||||
// support them.
|
||||
if parts[1] == "u" {
|
||||
return "BigInt"
|
||||
}
|
||||
|
||||
namedSize := map[string]string{
|
||||
"8": "byte",
|
||||
"16": "short",
|
||||
"32": "int",
|
||||
"64": "long",
|
||||
}[parts[2]]
|
||||
|
||||
// default to BigInt
|
||||
if namedSize == "" {
|
||||
namedSize = "BigInt"
|
||||
}
|
||||
return namedSize
|
||||
case abi.FixedBytesTy, abi.BytesTy:
|
||||
return "byte[]"
|
||||
case abi.BoolTy:
|
||||
return "boolean"
|
||||
case abi.StringTy:
|
||||
return "String"
|
||||
case abi.FunctionTy:
|
||||
return "byte[24]"
|
||||
default:
|
||||
return kind.String()
|
||||
}
|
||||
}
|
||||
|
||||
// pluralizeJavaType explicitly converts multidimensional types to predefined
|
||||
// types in go side.
|
||||
func pluralizeJavaType(typ string) string {
|
||||
switch typ {
|
||||
case "boolean":
|
||||
return "Bools"
|
||||
case "String":
|
||||
return "Strings"
|
||||
case "Address":
|
||||
return "Addresses"
|
||||
case "byte[]":
|
||||
return "Binaries"
|
||||
case "BigInt":
|
||||
return "BigInts"
|
||||
}
|
||||
return typ + "[]"
|
||||
}
|
||||
|
||||
// bindTypeJava converts a Solidity type to a Java one. Since there is no clear mapping
|
||||
// from all Solidity types to Java ones (e.g. uint17), those that cannot be exactly
|
||||
// mapped will use an upscaled type (e.g. BigDecimal).
|
||||
func bindTypeJava(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||
switch kind.T {
|
||||
case abi.TupleTy:
|
||||
return structs[kind.TupleRawName+kind.String()].Name
|
||||
case abi.ArrayTy, abi.SliceTy:
|
||||
return pluralizeJavaType(bindTypeJava(*kind.Elem, structs))
|
||||
default:
|
||||
return bindBasicTypeJava(kind)
|
||||
}
|
||||
}
|
||||
|
||||
// bindTopicType is a set of type binders that convert Solidity types to some
|
||||
// supported programming language topic types.
|
||||
var bindTopicType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{
|
||||
LangGo: bindTopicTypeGo,
|
||||
LangJava: bindTopicTypeJava,
|
||||
}
|
||||
|
||||
// bindTopicTypeGo converts a Solidity topic type to a Go one. It is almost the same
|
||||
@ -441,28 +356,10 @@ func bindTopicTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||
return bound
|
||||
}
|
||||
|
||||
// bindTopicTypeJava converts a Solidity topic type to a Java one. It is almost the same
|
||||
// functionality as for simple types, but dynamic types get converted to hashes.
|
||||
func bindTopicTypeJava(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||
bound := bindTypeJava(kind, structs)
|
||||
|
||||
// todo(rjl493456442) according solidity documentation, indexed event
|
||||
// parameters that are not value types i.e. arrays and structs are not
|
||||
// stored directly but instead a keccak256-hash of an encoding is stored.
|
||||
//
|
||||
// We only convert strings and bytes to hash, still need to deal with
|
||||
// array(both fixed-size and dynamic-size) and struct.
|
||||
if bound == "String" || bound == "byte[]" {
|
||||
bound = "Hash"
|
||||
}
|
||||
return bound
|
||||
}
|
||||
|
||||
// bindStructType is a set of type binders that convert Solidity tuple types to some supported
|
||||
// programming language struct definition.
|
||||
var bindStructType = map[Lang]func(kind abi.Type, structs map[string]*tmplStruct) string{
|
||||
LangGo: bindStructTypeGo,
|
||||
LangJava: bindStructTypeJava,
|
||||
}
|
||||
|
||||
// bindStructTypeGo converts a Solidity tuple type to a Go one and records the mapping
|
||||
@ -511,74 +408,10 @@ func bindStructTypeGo(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||
}
|
||||
}
|
||||
|
||||
// bindStructTypeJava converts a Solidity tuple type to a Java one and records the mapping
|
||||
// in the given map.
|
||||
// Notably, this function will resolve and record nested struct recursively.
|
||||
func bindStructTypeJava(kind abi.Type, structs map[string]*tmplStruct) string {
|
||||
switch kind.T {
|
||||
case abi.TupleTy:
|
||||
// We compose a raw struct name and a canonical parameter expression
|
||||
// together here. The reason is before solidity v0.5.11, kind.TupleRawName
|
||||
// is empty, so we use canonical parameter expression to distinguish
|
||||
// different struct definition. From the consideration of backward
|
||||
// compatibility, we concat these two together so that if kind.TupleRawName
|
||||
// is not empty, it can have unique id.
|
||||
id := kind.TupleRawName + kind.String()
|
||||
if s, exist := structs[id]; exist {
|
||||
return s.Name
|
||||
}
|
||||
var fields []*tmplField
|
||||
for i, elem := range kind.TupleElems {
|
||||
field := bindStructTypeJava(*elem, structs)
|
||||
fields = append(fields, &tmplField{Type: field, Name: decapitalise(kind.TupleRawNames[i]), SolKind: *elem})
|
||||
}
|
||||
name := kind.TupleRawName
|
||||
if name == "" {
|
||||
name = fmt.Sprintf("Class%d", len(structs))
|
||||
}
|
||||
structs[id] = &tmplStruct{
|
||||
Name: name,
|
||||
Fields: fields,
|
||||
}
|
||||
return name
|
||||
case abi.ArrayTy, abi.SliceTy:
|
||||
return pluralizeJavaType(bindStructTypeJava(*kind.Elem, structs))
|
||||
default:
|
||||
return bindBasicTypeJava(kind)
|
||||
}
|
||||
}
|
||||
|
||||
// namedType is a set of functions that transform language specific types to
|
||||
// named versions that may be used inside method names.
|
||||
var namedType = map[Lang]func(string, abi.Type) string{
|
||||
LangGo: func(string, abi.Type) string { panic("this shouldn't be needed") },
|
||||
LangJava: namedTypeJava,
|
||||
}
|
||||
|
||||
// namedTypeJava converts some primitive data types to named variants that can
|
||||
// be used as parts of method names.
|
||||
func namedTypeJava(javaKind string, solKind abi.Type) string {
|
||||
switch javaKind {
|
||||
case "byte[]":
|
||||
return "Binary"
|
||||
case "boolean":
|
||||
return "Bool"
|
||||
default:
|
||||
parts := regexp.MustCompile(`(u)?int([0-9]*)(\[[0-9]*\])?`).FindStringSubmatch(solKind.String())
|
||||
if len(parts) != 4 {
|
||||
return javaKind
|
||||
}
|
||||
switch parts[2] {
|
||||
case "8", "16", "32", "64":
|
||||
if parts[3] == "" {
|
||||
return capitalise(fmt.Sprintf("%sint%s", parts[1], parts[2]))
|
||||
}
|
||||
return capitalise(fmt.Sprintf("%sint%ss", parts[1], parts[2]))
|
||||
|
||||
default:
|
||||
return javaKind
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// alias returns an alias of the given string based on the aliasing rules
|
||||
@ -594,7 +427,6 @@ func alias(aliases map[string]string, n string) string {
|
||||
// conform to target language naming conventions.
|
||||
var methodNormalizer = map[Lang]func(string) string{
|
||||
LangGo: abi.ToCamelCase,
|
||||
LangJava: decapitalise,
|
||||
}
|
||||
|
||||
// capitalise makes a camel-case string which starts with an upper case character.
|
||||
|
File diff suppressed because one or more lines are too long
@ -76,7 +76,6 @@ type tmplStruct struct {
|
||||
// programming languages the package can generate to.
|
||||
var tmplSource = map[Lang]string{
|
||||
LangGo: tmplSourceGo,
|
||||
LangJava: tmplSourceJava,
|
||||
}
|
||||
|
||||
// tmplSourceGo is the Go source template that the generated Go contract binding
|
||||
@ -570,140 +569,3 @@ var (
|
||||
{{end}}
|
||||
{{end}}
|
||||
`
|
||||
|
||||
// tmplSourceJava is the Java source template that the generated Java contract binding
|
||||
// is based on.
|
||||
const tmplSourceJava = `
|
||||
// This file is an automatically generated Java binding. Do not modify as any
|
||||
// change will likely be lost upon the next re-generation!
|
||||
|
||||
package {{.Package}};
|
||||
|
||||
import org.ethereum.geth.*;
|
||||
import java.util.*;
|
||||
|
||||
{{$structs := .Structs}}
|
||||
{{range $contract := .Contracts}}
|
||||
{{if not .Library}}public {{end}}class {{.Type}} {
|
||||
// ABI is the input ABI used to generate the binding from.
|
||||
public final static String ABI = "{{.InputABI}}";
|
||||
{{if $contract.FuncSigs}}
|
||||
// {{.Type}}FuncSigs maps the 4-byte function signature to its string representation.
|
||||
public final static Map<String, String> {{.Type}}FuncSigs;
|
||||
static {
|
||||
Hashtable<String, String> temp = new Hashtable<String, String>();
|
||||
{{range $strsig, $binsig := .FuncSigs}}temp.put("{{$binsig}}", "{{$strsig}}");
|
||||
{{end}}
|
||||
{{.Type}}FuncSigs = Collections.unmodifiableMap(temp);
|
||||
}
|
||||
{{end}}
|
||||
{{if .InputBin}}
|
||||
// BYTECODE is the compiled bytecode used for deploying new contracts.
|
||||
public final static String BYTECODE = "0x{{.InputBin}}";
|
||||
|
||||
// deploy deploys a new Ethereum contract, binding an instance of {{.Type}} to it.
|
||||
public static {{.Type}} deploy(TransactOpts auth, EthereumClient client{{range .Constructor.Inputs}}, {{bindtype .Type $structs}} {{.Name}}{{end}}) throws Exception {
|
||||
Interfaces args = Geth.newInterfaces({{(len .Constructor.Inputs)}});
|
||||
String bytecode = BYTECODE;
|
||||
{{if .Libraries}}
|
||||
|
||||
// "link" contract to dependent libraries by deploying them first.
|
||||
{{range $pattern, $name := .Libraries}}
|
||||
{{capitalise $name}} {{decapitalise $name}}Inst = {{capitalise $name}}.deploy(auth, client);
|
||||
bytecode = bytecode.replace("__${{$pattern}}$__", {{decapitalise $name}}Inst.Address.getHex().substring(2));
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{range $index, $element := .Constructor.Inputs}}Interface arg{{$index}} = Geth.newInterface();arg{{$index}}.set{{namedtype (bindtype .Type $structs) .Type}}({{.Name}});args.set({{$index}},arg{{$index}});
|
||||
{{end}}
|
||||
return new {{.Type}}(Geth.deployContract(auth, ABI, Geth.decodeFromHex(bytecode), client, args));
|
||||
}
|
||||
|
||||
// Internal constructor used by contract deployment.
|
||||
private {{.Type}}(BoundContract deployment) {
|
||||
this.Address = deployment.getAddress();
|
||||
this.Deployer = deployment.getDeployer();
|
||||
this.Contract = deployment;
|
||||
}
|
||||
{{end}}
|
||||
|
||||
// Ethereum address where this contract is located at.
|
||||
public final Address Address;
|
||||
|
||||
// Ethereum transaction in which this contract was deployed (if known!).
|
||||
public final Transaction Deployer;
|
||||
|
||||
// Contract instance bound to a blockchain address.
|
||||
private final BoundContract Contract;
|
||||
|
||||
// Creates a new instance of {{.Type}}, bound to a specific deployed contract.
|
||||
public {{.Type}}(Address address, EthereumClient client) throws Exception {
|
||||
this(Geth.bindContract(address, ABI, client));
|
||||
}
|
||||
|
||||
{{range .Calls}}
|
||||
{{if gt (len .Normalized.Outputs) 1}}
|
||||
// {{capitalise .Normalized.Name}}Results is the output of a call to {{.Normalized.Name}}.
|
||||
public class {{capitalise .Normalized.Name}}Results {
|
||||
{{range $index, $item := .Normalized.Outputs}}public {{bindtype .Type $structs}} {{if ne .Name ""}}{{.Name}}{{else}}Return{{$index}}{{end}};
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
// {{.Normalized.Name}} is a free data retrieval call binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||
//
|
||||
// Solidity: {{.Original.String}}
|
||||
public {{if gt (len .Normalized.Outputs) 1}}{{capitalise .Normalized.Name}}Results{{else if eq (len .Normalized.Outputs) 0}}void{{else}}{{range .Normalized.Outputs}}{{bindtype .Type $structs}}{{end}}{{end}} {{.Normalized.Name}}(CallOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type $structs}} {{.Name}}{{end}}) throws Exception {
|
||||
Interfaces args = Geth.newInterfaces({{(len .Normalized.Inputs)}});
|
||||
{{range $index, $item := .Normalized.Inputs}}Interface arg{{$index}} = Geth.newInterface();arg{{$index}}.set{{namedtype (bindtype .Type $structs) .Type}}({{.Name}});args.set({{$index}},arg{{$index}});
|
||||
{{end}}
|
||||
|
||||
Interfaces results = Geth.newInterfaces({{(len .Normalized.Outputs)}});
|
||||
{{range $index, $item := .Normalized.Outputs}}Interface result{{$index}} = Geth.newInterface(); result{{$index}}.setDefault{{namedtype (bindtype .Type $structs) .Type}}(); results.set({{$index}}, result{{$index}});
|
||||
{{end}}
|
||||
|
||||
if (opts == null) {
|
||||
opts = Geth.newCallOpts();
|
||||
}
|
||||
this.Contract.call(opts, results, "{{.Original.Name}}", args);
|
||||
{{if gt (len .Normalized.Outputs) 1}}
|
||||
{{capitalise .Normalized.Name}}Results result = new {{capitalise .Normalized.Name}}Results();
|
||||
{{range $index, $item := .Normalized.Outputs}}result.{{if ne .Name ""}}{{.Name}}{{else}}Return{{$index}}{{end}} = results.get({{$index}}).get{{namedtype (bindtype .Type $structs) .Type}}();
|
||||
{{end}}
|
||||
return result;
|
||||
{{else}}{{range .Normalized.Outputs}}return results.get(0).get{{namedtype (bindtype .Type $structs) .Type}}();{{end}}
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{range .Transacts}}
|
||||
// {{.Normalized.Name}} is a paid mutator transaction binding the contract method 0x{{printf "%x" .Original.ID}}.
|
||||
//
|
||||
// Solidity: {{.Original.String}}
|
||||
public Transaction {{.Normalized.Name}}(TransactOpts opts{{range .Normalized.Inputs}}, {{bindtype .Type $structs}} {{.Name}}{{end}}) throws Exception {
|
||||
Interfaces args = Geth.newInterfaces({{(len .Normalized.Inputs)}});
|
||||
{{range $index, $item := .Normalized.Inputs}}Interface arg{{$index}} = Geth.newInterface();arg{{$index}}.set{{namedtype (bindtype .Type $structs) .Type}}({{.Name}});args.set({{$index}},arg{{$index}});
|
||||
{{end}}
|
||||
return this.Contract.transact(opts, "{{.Original.Name}}" , args);
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .Fallback}}
|
||||
// Fallback is a paid mutator transaction binding the contract fallback function.
|
||||
//
|
||||
// Solidity: {{.Fallback.Original.String}}
|
||||
public Transaction Fallback(TransactOpts opts, byte[] calldata) throws Exception {
|
||||
return this.Contract.rawTransact(opts, calldata);
|
||||
}
|
||||
{{end}}
|
||||
|
||||
{{if .Receive}}
|
||||
// Receive is a paid mutator transaction binding the contract receive function.
|
||||
//
|
||||
// Solidity: {{.Receive.Original.String}}
|
||||
public Transaction Receive(TransactOpts opts) throws Exception {
|
||||
return this.Contract.rawTransact(opts, null);
|
||||
}
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
`
|
||||
|
238
build/ci.go
238
build/ci.go
@ -31,8 +31,6 @@ Available commands are:
|
||||
importkeys -- imports signing keys from env
|
||||
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
|
||||
nsis -- creates a Windows NSIS installer
|
||||
aar [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an Android archive
|
||||
xcode [ -local ] [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an iOS XCode framework
|
||||
purge [ -store blobstore ] [ -days threshold ] -- purges old archives from the blobstore
|
||||
|
||||
For all commands, -n prevents execution of external programs (dry run mode).
|
||||
@ -40,7 +38,6 @@ For all commands, -n prevents execution of external programs (dry run mode).
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
@ -50,7 +47,6 @@ import (
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -179,10 +175,6 @@ func main() {
|
||||
doDebianSource(os.Args[2:])
|
||||
case "nsis":
|
||||
doWindowsInstaller(os.Args[2:])
|
||||
case "aar":
|
||||
doAndroidArchive(os.Args[2:])
|
||||
case "xcode":
|
||||
doXCodeFramework(os.Args[2:])
|
||||
case "purge":
|
||||
doPurge(os.Args[2:])
|
||||
default:
|
||||
@ -994,236 +986,6 @@ func doWindowsInstaller(cmdline []string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Android archives
|
||||
|
||||
func doAndroidArchive(cmdline []string) {
|
||||
var (
|
||||
local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
|
||||
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. ANDROID_SIGNING_KEY)`)
|
||||
signify = flag.String("signify", "", `Environment variable holding the signify signing key (e.g. ANDROID_SIGNIFY_KEY)`)
|
||||
deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "https://oss.sonatype.org")`)
|
||||
upload = flag.String("upload", "", `Destination to upload the archive (usually "gethstore/builds")`)
|
||||
)
|
||||
flag.CommandLine.Parse(cmdline)
|
||||
env := build.Env()
|
||||
tc := new(build.GoToolchain)
|
||||
|
||||
// Sanity check that the SDK and NDK are installed and set
|
||||
if os.Getenv("ANDROID_HOME") == "" {
|
||||
log.Fatal("Please ensure ANDROID_HOME points to your Android SDK")
|
||||
}
|
||||
|
||||
// Build gomobile.
|
||||
install := tc.Install(GOBIN, "golang.org/x/mobile/cmd/gomobile@latest", "golang.org/x/mobile/cmd/gobind@latest")
|
||||
install.Env = append(install.Env)
|
||||
build.MustRun(install)
|
||||
|
||||
// Ensure all dependencies are available. This is required to make
|
||||
// gomobile bind work because it expects go.sum to contain all checksums.
|
||||
build.MustRun(tc.Go("mod", "download"))
|
||||
|
||||
// Build the Android archive and Maven resources
|
||||
build.MustRun(gomobileTool("bind", "-ldflags", "-s -w", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/ethereum/go-ethereum/mobile"))
|
||||
|
||||
if *local {
|
||||
// If we're building locally, copy bundle to build dir and skip Maven
|
||||
os.Rename("geth.aar", filepath.Join(GOBIN, "geth.aar"))
|
||||
os.Rename("geth-sources.jar", filepath.Join(GOBIN, "geth-sources.jar"))
|
||||
return
|
||||
}
|
||||
meta := newMavenMetadata(env)
|
||||
build.Render("build/mvn.pom", meta.Package+".pom", 0755, meta)
|
||||
|
||||
// Skip Maven deploy and Azure upload for PR builds
|
||||
maybeSkipArchive(env)
|
||||
|
||||
// Sign and upload the archive to Azure
|
||||
archive := "geth-" + archiveBasename("android", params.ArchiveVersion(env.Commit)) + ".aar"
|
||||
os.Rename("geth.aar", archive)
|
||||
|
||||
if err := archiveUpload(archive, *upload, *signer, *signify); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Sign and upload all the artifacts to Maven Central
|
||||
os.Rename(archive, meta.Package+".aar")
|
||||
if *signer != "" && *deploy != "" {
|
||||
// Import the signing key into the local GPG instance
|
||||
key := getenvBase64(*signer)
|
||||
gpg := exec.Command("gpg", "--import")
|
||||
gpg.Stdin = bytes.NewReader(key)
|
||||
build.MustRun(gpg)
|
||||
keyID, err := build.PGPKeyID(string(key))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Upload the artifacts to Sonatype and/or Maven Central
|
||||
repo := *deploy + "/service/local/staging/deploy/maven2"
|
||||
if meta.Develop {
|
||||
repo = *deploy + "/content/repositories/snapshots"
|
||||
}
|
||||
build.MustRunCommand("mvn", "gpg:sign-and-deploy-file", "-e", "-X",
|
||||
"-settings=build/mvn.settings", "-Durl="+repo, "-DrepositoryId=ossrh",
|
||||
"-Dgpg.keyname="+keyID,
|
||||
"-DpomFile="+meta.Package+".pom", "-Dfile="+meta.Package+".aar")
|
||||
}
|
||||
}
|
||||
|
||||
func gomobileTool(subcmd string, args ...string) *exec.Cmd {
|
||||
cmd := exec.Command(filepath.Join(GOBIN, "gomobile"), subcmd)
|
||||
cmd.Args = append(cmd.Args, args...)
|
||||
cmd.Env = []string{
|
||||
"PATH=" + GOBIN + string(os.PathListSeparator) + os.Getenv("PATH"),
|
||||
}
|
||||
for _, e := range os.Environ() {
|
||||
if strings.HasPrefix(e, "GOPATH=") || strings.HasPrefix(e, "PATH=") || strings.HasPrefix(e, "GOBIN=") {
|
||||
continue
|
||||
}
|
||||
cmd.Env = append(cmd.Env, e)
|
||||
}
|
||||
cmd.Env = append(cmd.Env, "GOBIN="+GOBIN)
|
||||
return cmd
|
||||
}
|
||||
|
||||
type mavenMetadata struct {
|
||||
Version string
|
||||
Package string
|
||||
Develop bool
|
||||
Contributors []mavenContributor
|
||||
}
|
||||
|
||||
type mavenContributor struct {
|
||||
Name string
|
||||
Email string
|
||||
}
|
||||
|
||||
func newMavenMetadata(env build.Environment) mavenMetadata {
|
||||
// Collect the list of authors from the repo root
|
||||
contribs := []mavenContributor{}
|
||||
if authors, err := os.Open("AUTHORS"); err == nil {
|
||||
defer authors.Close()
|
||||
|
||||
scanner := bufio.NewScanner(authors)
|
||||
for scanner.Scan() {
|
||||
// Skip any whitespace from the authors list
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line == "" || line[0] == '#' {
|
||||
continue
|
||||
}
|
||||
// Split the author and insert as a contributor
|
||||
re := regexp.MustCompile("([^<]+) <(.+)>")
|
||||
parts := re.FindStringSubmatch(line)
|
||||
if len(parts) == 3 {
|
||||
contribs = append(contribs, mavenContributor{Name: parts[1], Email: parts[2]})
|
||||
}
|
||||
}
|
||||
}
|
||||
// Render the version and package strings
|
||||
version := params.Version
|
||||
if isUnstableBuild(env) {
|
||||
version += "-SNAPSHOT"
|
||||
}
|
||||
return mavenMetadata{
|
||||
Version: version,
|
||||
Package: "geth-" + version,
|
||||
Develop: isUnstableBuild(env),
|
||||
Contributors: contribs,
|
||||
}
|
||||
}
|
||||
|
||||
// XCode frameworks
|
||||
|
||||
func doXCodeFramework(cmdline []string) {
|
||||
var (
|
||||
local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
|
||||
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. IOS_SIGNING_KEY)`)
|
||||
signify = flag.String("signify", "", `Environment variable holding the signify signing key (e.g. IOS_SIGNIFY_KEY)`)
|
||||
deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "trunk")`)
|
||||
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
|
||||
)
|
||||
flag.CommandLine.Parse(cmdline)
|
||||
env := build.Env()
|
||||
tc := new(build.GoToolchain)
|
||||
|
||||
// Build gomobile.
|
||||
build.MustRun(tc.Install(GOBIN, "golang.org/x/mobile/cmd/gomobile@latest", "golang.org/x/mobile/cmd/gobind@latest"))
|
||||
|
||||
// Build the iOS XCode framework
|
||||
bind := gomobileTool("bind", "-ldflags", "-s -w", "--target", "ios", "-v", "github.com/ethereum/go-ethereum/mobile")
|
||||
|
||||
if *local {
|
||||
// If we're building locally, use the build folder and stop afterwards
|
||||
bind.Dir = GOBIN
|
||||
build.MustRun(bind)
|
||||
return
|
||||
}
|
||||
|
||||
// Create the archive.
|
||||
maybeSkipArchive(env)
|
||||
archive := "geth-" + archiveBasename("ios", params.ArchiveVersion(env.Commit))
|
||||
if err := os.MkdirAll(archive, 0755); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
bind.Dir, _ = filepath.Abs(archive)
|
||||
build.MustRun(bind)
|
||||
build.MustRunCommand("tar", "-zcvf", archive+".tar.gz", archive)
|
||||
|
||||
// Sign and upload the framework to Azure
|
||||
if err := archiveUpload(archive+".tar.gz", *upload, *signer, *signify); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// Prepare and upload a PodSpec to CocoaPods
|
||||
if *deploy != "" {
|
||||
meta := newPodMetadata(env, archive)
|
||||
build.Render("build/pod.podspec", "Geth.podspec", 0755, meta)
|
||||
build.MustRunCommand("pod", *deploy, "push", "Geth.podspec", "--allow-warnings")
|
||||
}
|
||||
}
|
||||
|
||||
type podMetadata struct {
|
||||
Version string
|
||||
Commit string
|
||||
Archive string
|
||||
Contributors []podContributor
|
||||
}
|
||||
|
||||
type podContributor struct {
|
||||
Name string
|
||||
Email string
|
||||
}
|
||||
|
||||
func newPodMetadata(env build.Environment, archive string) podMetadata {
|
||||
// Collect the list of authors from the repo root
|
||||
contribs := []podContributor{}
|
||||
if authors, err := os.Open("AUTHORS"); err == nil {
|
||||
defer authors.Close()
|
||||
|
||||
scanner := bufio.NewScanner(authors)
|
||||
for scanner.Scan() {
|
||||
// Skip any whitespace from the authors list
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if line == "" || line[0] == '#' {
|
||||
continue
|
||||
}
|
||||
// Split the author and insert as a contributor
|
||||
re := regexp.MustCompile("([^<]+) <(.+)>")
|
||||
parts := re.FindStringSubmatch(line)
|
||||
if len(parts) == 3 {
|
||||
contribs = append(contribs, podContributor{Name: parts[1], Email: parts[2]})
|
||||
}
|
||||
}
|
||||
}
|
||||
version := params.Version
|
||||
if isUnstableBuild(env) {
|
||||
version += "-unstable." + env.Buildnum
|
||||
}
|
||||
return podMetadata{
|
||||
Archive: archive,
|
||||
Version: version,
|
||||
Commit: env.Commit,
|
||||
Contributors: contribs,
|
||||
}
|
||||
}
|
||||
|
||||
// Binary distribution cleanups
|
||||
|
||||
func doPurge(cmdline []string) {
|
||||
|
@ -1,57 +0,0 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.ethereum</groupId>
|
||||
<artifactId>geth</artifactId>
|
||||
<version>{{.Version}}</version>
|
||||
<packaging>aar</packaging>
|
||||
|
||||
<name>Android Ethereum Client</name>
|
||||
<description>Android port of the go-ethereum libraries and node</description>
|
||||
<url>https://github.com/ethereum/go-ethereum</url>
|
||||
<inceptionYear>2015</inceptionYear>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>GNU Lesser General Public License, Version 3.0</name>
|
||||
<url>https://www.gnu.org/licenses/lgpl-3.0.en.html</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<organization>
|
||||
<name>Ethereum</name>
|
||||
<url>https://ethereum.org</url>
|
||||
</organization>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>karalabe</id>
|
||||
<name>Péter Szilágyi</name>
|
||||
<email>peterke@gmail.com</email>
|
||||
<url>https://github.com/karalabe</url>
|
||||
<properties>
|
||||
<picUrl>https://www.gravatar.com/avatar/2ecbf0f5b4b79eebf8c193e5d324357f?s=256</picUrl>
|
||||
</properties>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<contributors>{{range .Contributors}}
|
||||
<contributor>
|
||||
<name>{{.Name}}</name>
|
||||
<email>{{.Email}}</email>
|
||||
</contributor>{{end}}
|
||||
</contributors>
|
||||
|
||||
<issueManagement>
|
||||
<system>GitHub Issues</system>
|
||||
<url>https://github.com/ethereum/go-ethereum/issues/</url>
|
||||
</issueManagement>
|
||||
|
||||
<scm>
|
||||
<url>https://github.com/ethereum/go-ethereum</url>
|
||||
</scm>
|
||||
</project>
|
@ -1,24 +0,0 @@
|
||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
|
||||
http://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||
<servers>
|
||||
<server>
|
||||
<id>ossrh</id>
|
||||
<username>${env.ANDROID_SONATYPE_USERNAME}</username>
|
||||
<password>${env.ANDROID_SONATYPE_PASSWORD}</password>
|
||||
</server>
|
||||
</servers>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>ossrh</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<gpg.executable>gpg</gpg.executable>
|
||||
<gpg.passphrase></gpg.passphrase>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</settings>
|
@ -1,22 +0,0 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = 'Geth'
|
||||
spec.version = '{{.Version}}'
|
||||
spec.license = { :type => 'GNU Lesser General Public License, Version 3.0' }
|
||||
spec.homepage = 'https://github.com/ethereum/go-ethereum'
|
||||
spec.authors = { {{range .Contributors}}
|
||||
'{{.Name}}' => '{{.Email}}',{{end}}
|
||||
}
|
||||
spec.summary = 'iOS Ethereum Client'
|
||||
spec.source = { :git => 'https://github.com/ethereum/go-ethereum.git', :commit => '{{.Commit}}' }
|
||||
|
||||
spec.platform = :ios
|
||||
spec.ios.deployment_target = '9.0'
|
||||
spec.ios.vendored_frameworks = 'Frameworks/Geth.framework'
|
||||
|
||||
spec.prepare_command = <<-CMD
|
||||
curl https://gethstore.blob.core.windows.net/builds/{{.Archive}}.tar.gz | tar -xvz
|
||||
mkdir Frameworks
|
||||
mv {{.Archive}}/Geth.framework Frameworks
|
||||
rm -rf {{.Archive}}
|
||||
CMD
|
||||
end
|
@ -24,8 +24,4 @@ import (
|
||||
_ "github.com/fjl/gencodec"
|
||||
_ "github.com/golang/protobuf/protoc-gen-go"
|
||||
_ "golang.org/x/tools/cmd/stringer"
|
||||
|
||||
// Tool imports for mobile build.
|
||||
_ "golang.org/x/mobile/cmd/gobind"
|
||||
_ "golang.org/x/mobile/cmd/gomobile"
|
||||
)
|
||||
|
@ -65,7 +65,7 @@ var (
|
||||
}
|
||||
langFlag = &cli.StringFlag{
|
||||
Name: "lang",
|
||||
Usage: "Destination language for the bindings (go, java, objc)",
|
||||
Usage: "Destination language for the bindings (go)",
|
||||
Value: "go",
|
||||
}
|
||||
aliasFlag = &cli.StringFlag{
|
||||
@ -102,11 +102,6 @@ func abigen(c *cli.Context) error {
|
||||
switch c.String(langFlag.Name) {
|
||||
case "go":
|
||||
lang = bind.LangGo
|
||||
case "java":
|
||||
lang = bind.LangJava
|
||||
case "objc":
|
||||
lang = bind.LangObjC
|
||||
utils.Fatalf("Objc binding generation is uncompleted")
|
||||
default:
|
||||
utils.Fatalf("Unsupported destination language \"%s\" (--lang)", c.String(langFlag.Name))
|
||||
}
|
||||
|
1
go.mod
1
go.mod
@ -58,7 +58,6 @@ require (
|
||||
github.com/tyler-smith/go-bip39 v1.1.0
|
||||
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa
|
||||
golang.org/x/crypto v0.1.0
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
|
||||
golang.org/x/sys v0.2.0
|
||||
golang.org/x/text v0.4.0
|
||||
|
1
go.sum
1
go.sum
@ -464,7 +464,6 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG1In4gJY5YRhtpDNeDeHWs=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
|
@ -1,221 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains all the wrappers from the accounts package to support client side key
|
||||
// management on mobile platforms.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
const (
|
||||
// StandardScryptN is the N parameter of Scrypt encryption algorithm, using 256MB
|
||||
// memory and taking approximately 1s CPU time on a modern processor.
|
||||
StandardScryptN = int(keystore.StandardScryptN)
|
||||
|
||||
// StandardScryptP is the P parameter of Scrypt encryption algorithm, using 256MB
|
||||
// memory and taking approximately 1s CPU time on a modern processor.
|
||||
StandardScryptP = int(keystore.StandardScryptP)
|
||||
|
||||
// LightScryptN is the N parameter of Scrypt encryption algorithm, using 4MB
|
||||
// memory and taking approximately 100ms CPU time on a modern processor.
|
||||
LightScryptN = int(keystore.LightScryptN)
|
||||
|
||||
// LightScryptP is the P parameter of Scrypt encryption algorithm, using 4MB
|
||||
// memory and taking approximately 100ms CPU time on a modern processor.
|
||||
LightScryptP = int(keystore.LightScryptP)
|
||||
)
|
||||
|
||||
// Account represents a stored key.
|
||||
type Account struct{ account accounts.Account }
|
||||
|
||||
// Accounts represents a slice of accounts.
|
||||
type Accounts struct{ accounts []accounts.Account }
|
||||
|
||||
// Size returns the number of accounts in the slice.
|
||||
func (a *Accounts) Size() int {
|
||||
return len(a.accounts)
|
||||
}
|
||||
|
||||
// Get returns the account at the given index from the slice.
|
||||
func (a *Accounts) Get(index int) (account *Account, _ error) {
|
||||
if index < 0 || index >= len(a.accounts) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return &Account{a.accounts[index]}, nil
|
||||
}
|
||||
|
||||
// Set sets the account at the given index in the slice.
|
||||
func (a *Accounts) Set(index int, account *Account) error {
|
||||
if index < 0 || index >= len(a.accounts) {
|
||||
return errors.New("index out of bounds")
|
||||
}
|
||||
a.accounts[index] = account.account
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAddress retrieves the address associated with the account.
|
||||
func (a *Account) GetAddress() *Address {
|
||||
return &Address{a.account.Address}
|
||||
}
|
||||
|
||||
// GetURL retrieves the canonical URL of the account.
|
||||
func (a *Account) GetURL() string {
|
||||
return a.account.URL.String()
|
||||
}
|
||||
|
||||
// KeyStore manages a key storage directory on disk.
|
||||
type KeyStore struct{ keystore *keystore.KeyStore }
|
||||
|
||||
// NewKeyStore creates a keystore for the given directory.
|
||||
func NewKeyStore(keydir string, scryptN, scryptP int) *KeyStore {
|
||||
return &KeyStore{keystore: keystore.NewKeyStore(keydir, scryptN, scryptP)}
|
||||
}
|
||||
|
||||
// HasAddress reports whether a key with the given address is present.
|
||||
func (ks *KeyStore) HasAddress(address *Address) bool {
|
||||
return ks.keystore.HasAddress(address.address)
|
||||
}
|
||||
|
||||
// GetAccounts returns all key files present in the directory.
|
||||
func (ks *KeyStore) GetAccounts() *Accounts {
|
||||
return &Accounts{ks.keystore.Accounts()}
|
||||
}
|
||||
|
||||
// DeleteAccount deletes the key matched by account if the passphrase is correct.
|
||||
// If a contains no filename, the address must match a unique key.
|
||||
func (ks *KeyStore) DeleteAccount(account *Account, passphrase string) error {
|
||||
return ks.keystore.Delete(account.account, passphrase)
|
||||
}
|
||||
|
||||
// SignHash 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 (ks *KeyStore) SignHash(address *Address, hash []byte) (signature []byte, _ error) {
|
||||
return ks.keystore.SignHash(accounts.Account{Address: address.address}, common.CopyBytes(hash))
|
||||
}
|
||||
|
||||
// SignTx signs the given transaction with the requested account.
|
||||
func (ks *KeyStore) SignTx(account *Account, tx *Transaction, chainID *BigInt) (*Transaction, error) {
|
||||
if chainID == nil { // Null passed from mobile app
|
||||
chainID = new(BigInt)
|
||||
}
|
||||
signed, err := ks.keystore.SignTx(account.account, tx.tx, chainID.bigint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Transaction{signed}, nil
|
||||
}
|
||||
|
||||
// SignHashPassphrase 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 (ks *KeyStore) SignHashPassphrase(account *Account, passphrase string, hash []byte) (signature []byte, _ error) {
|
||||
return ks.keystore.SignHashWithPassphrase(account.account, passphrase, common.CopyBytes(hash))
|
||||
}
|
||||
|
||||
// SignTxPassphrase signs the transaction if the private key matching the
|
||||
// given address can be decrypted with the given passphrase.
|
||||
func (ks *KeyStore) SignTxPassphrase(account *Account, passphrase string, tx *Transaction, chainID *BigInt) (*Transaction, error) {
|
||||
if chainID == nil { // Null passed from mobile app
|
||||
chainID = new(BigInt)
|
||||
}
|
||||
signed, err := ks.keystore.SignTxWithPassphrase(account.account, passphrase, tx.tx, chainID.bigint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Transaction{signed}, nil
|
||||
}
|
||||
|
||||
// Unlock unlocks the given account indefinitely.
|
||||
func (ks *KeyStore) Unlock(account *Account, passphrase string) error {
|
||||
return ks.keystore.TimedUnlock(account.account, passphrase, 0)
|
||||
}
|
||||
|
||||
// Lock removes the private key with the given address from memory.
|
||||
func (ks *KeyStore) Lock(address *Address) error {
|
||||
return ks.keystore.Lock(address.address)
|
||||
}
|
||||
|
||||
// TimedUnlock unlocks the given account with the passphrase. The account stays
|
||||
// unlocked for the duration of timeout (nanoseconds). A timeout of 0 unlocks the
|
||||
// account until the program exits. The account must match a unique key file.
|
||||
//
|
||||
// If the account address is already unlocked for a duration, TimedUnlock extends or
|
||||
// shortens the active unlock timeout. If the address was previously unlocked
|
||||
// indefinitely the timeout is not altered.
|
||||
func (ks *KeyStore) TimedUnlock(account *Account, passphrase string, timeout int64) error {
|
||||
return ks.keystore.TimedUnlock(account.account, passphrase, time.Duration(timeout))
|
||||
}
|
||||
|
||||
// NewAccount generates a new key and stores it into the key directory,
|
||||
// encrypting it with the passphrase.
|
||||
func (ks *KeyStore) NewAccount(passphrase string) (*Account, error) {
|
||||
account, err := ks.keystore.NewAccount(passphrase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Account{account}, nil
|
||||
}
|
||||
|
||||
// UpdateAccount changes the passphrase of an existing account.
|
||||
func (ks *KeyStore) UpdateAccount(account *Account, passphrase, newPassphrase string) error {
|
||||
return ks.keystore.Update(account.account, passphrase, newPassphrase)
|
||||
}
|
||||
|
||||
// ExportKey exports as a JSON key, encrypted with newPassphrase.
|
||||
func (ks *KeyStore) ExportKey(account *Account, passphrase, newPassphrase string) (key []byte, _ error) {
|
||||
return ks.keystore.Export(account.account, passphrase, newPassphrase)
|
||||
}
|
||||
|
||||
// ImportKey stores the given encrypted JSON key into the key directory.
|
||||
func (ks *KeyStore) ImportKey(keyJSON []byte, passphrase, newPassphrase string) (account *Account, _ error) {
|
||||
acc, err := ks.keystore.Import(common.CopyBytes(keyJSON), passphrase, newPassphrase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Account{acc}, nil
|
||||
}
|
||||
|
||||
// ImportECDSAKey stores the given encrypted JSON key into the key directory.
|
||||
func (ks *KeyStore) ImportECDSAKey(key []byte, passphrase string) (account *Account, _ error) {
|
||||
privkey, err := crypto.ToECDSA(common.CopyBytes(key))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
acc, err := ks.keystore.ImportECDSA(privkey, passphrase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Account{acc}, nil
|
||||
}
|
||||
|
||||
// ImportPreSaleKey decrypts the given Ethereum presale wallet and stores
|
||||
// a key file in the key directory. The key file is encrypted with the same passphrase.
|
||||
func (ks *KeyStore) ImportPreSaleKey(keyJSON []byte, passphrase string) (account *Account, _ error) {
|
||||
acc, err := ks.keystore.ImportPreSaleKey(common.CopyBytes(keyJSON), passphrase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Account{acc}, nil
|
||||
}
|
@ -1,261 +0,0 @@
|
||||
// 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 geth
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cespare/cp"
|
||||
)
|
||||
|
||||
// androidTestClass is a Java class to do some lightweight tests against the Android
|
||||
// bindings. The goal is not to test each individual functionality, rather just to
|
||||
// catch breaking API and/or implementation changes.
|
||||
const androidTestClass = `
|
||||
package go;
|
||||
|
||||
import android.test.InstrumentationTestCase;
|
||||
import android.test.MoreAsserts;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.ethereum.geth.*;
|
||||
|
||||
public class AndroidTest extends InstrumentationTestCase {
|
||||
public AndroidTest() {}
|
||||
|
||||
public void testAccountManagement() {
|
||||
// Create an encrypted keystore with light crypto parameters.
|
||||
KeyStore ks = new KeyStore(getInstrumentation().getContext().getFilesDir() + "/keystore", Geth.LightScryptN, Geth.LightScryptP);
|
||||
|
||||
try {
|
||||
// Create a new account with the specified encryption passphrase.
|
||||
Account newAcc = ks.newAccount("Creation password");
|
||||
|
||||
// Export the newly created account with a different passphrase. The returned
|
||||
// data from this method invocation is a JSON encoded, encrypted key-file.
|
||||
byte[] jsonAcc = ks.exportKey(newAcc, "Creation password", "Export password");
|
||||
|
||||
// Update the passphrase on the account created above inside the local keystore.
|
||||
ks.updateAccount(newAcc, "Creation password", "Update password");
|
||||
|
||||
// Delete the account updated above from the local keystore.
|
||||
ks.deleteAccount(newAcc, "Update password");
|
||||
|
||||
// Import back the account we've exported (and then deleted) above with yet
|
||||
// again a fresh passphrase.
|
||||
Account impAcc = ks.importKey(jsonAcc, "Export password", "Import password");
|
||||
|
||||
// Create a new account to sign transactions with
|
||||
Account signer = ks.newAccount("Signer password");
|
||||
|
||||
Transaction tx = new Transaction(
|
||||
1, new Address("0x0000000000000000000000000000000000000000"),
|
||||
new BigInt(0), 0, new BigInt(1), null); // Random empty transaction
|
||||
BigInt chain = new BigInt(1); // Chain identifier of the main net
|
||||
|
||||
// Sign a transaction with a single authorization
|
||||
Transaction signed = ks.signTxPassphrase(signer, "Signer password", tx, chain);
|
||||
|
||||
// Sign a transaction with multiple manually cancelled authorizations
|
||||
ks.unlock(signer, "Signer password");
|
||||
signed = ks.signTx(signer, tx, chain);
|
||||
ks.lock(signer.getAddress());
|
||||
|
||||
// Sign a transaction with multiple automatically cancelled authorizations
|
||||
ks.timedUnlock(signer, "Signer password", 1000000000);
|
||||
signed = ks.signTx(signer, tx, chain);
|
||||
} catch (Exception e) {
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public void testInprocNode() {
|
||||
Context ctx = new Context();
|
||||
|
||||
try {
|
||||
// Start up a new inprocess node
|
||||
Node node = new Node(getInstrumentation().getContext().getFilesDir() + "/.ethereum", new NodeConfig());
|
||||
node.start();
|
||||
|
||||
// Retrieve some data via function calls (we don't really care about the results)
|
||||
NodeInfo info = node.getNodeInfo();
|
||||
info.getName();
|
||||
info.getListenerAddress();
|
||||
info.getProtocols();
|
||||
|
||||
// Retrieve some data via the APIs (we don't really care about the results)
|
||||
EthereumClient ec = node.getEthereumClient();
|
||||
ec.getBlockByNumber(ctx, -1).getNumber();
|
||||
|
||||
NewHeadHandler handler = new NewHeadHandler() {
|
||||
@Override public void onError(String error) {}
|
||||
@Override public void onNewHead(final Header header) {}
|
||||
};
|
||||
ec.subscribeNewHead(ctx, handler, 16);
|
||||
} catch (Exception e) {
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that recovering transaction signers works for both Homestead and EIP155
|
||||
// signatures too. Regression test for go-ethereum issue #14599.
|
||||
public void testIssue14599() {
|
||||
try {
|
||||
byte[] preEIP155RLP = new BigInteger("f901fc8032830138808080b901ae60056013565b6101918061001d6000396000f35b3360008190555056006001600060e060020a6000350480630a874df61461003a57806341c0e1b514610058578063a02b161e14610066578063dbbdf0831461007757005b610045600435610149565b80600160a060020a031660005260206000f35b610060610161565b60006000f35b6100716004356100d4565b60006000f35b61008560043560243561008b565b60006000f35b600054600160a060020a031632600160a060020a031614156100ac576100b1565b6100d0565b8060018360005260205260406000208190555081600060005260206000a15b5050565b600054600160a060020a031633600160a060020a031614158015610118575033600160a060020a0316600182600052602052604060002054600160a060020a031614155b61012157610126565b610146565b600060018260005260205260406000208190555080600060005260206000a15b50565b60006001826000526020526040600020549050919050565b600054600160a060020a031633600160a060020a0316146101815761018f565b600054600160a060020a0316ff5b561ca0c5689ed1ad124753d54576dfb4b571465a41900a1dff4058d8adf16f752013d0a01221cbd70ec28c94a3b55ec771bcbc70778d6ee0b51ca7ea9514594c861b1884", 16).toByteArray();
|
||||
preEIP155RLP = Arrays.copyOfRange(preEIP155RLP, 1, preEIP155RLP.length);
|
||||
|
||||
byte[] postEIP155RLP = new BigInteger("f86b80847735940082520894ef5bbb9bba2e1ca69ef81b23a8727d889f3ef0a1880de0b6b3a7640000802ba06fef16c44726a102e6d55a651740636ef8aec6df3ebf009e7b0c1f29e4ac114aa057e7fbc69760b522a78bb568cfc37a58bfdcf6ea86cb8f9b550263f58074b9cc", 16).toByteArray();
|
||||
postEIP155RLP = Arrays.copyOfRange(postEIP155RLP, 1, postEIP155RLP.length);
|
||||
|
||||
Transaction preEIP155 = new Transaction(preEIP155RLP);
|
||||
Transaction postEIP155 = new Transaction(postEIP155RLP);
|
||||
|
||||
preEIP155.getFrom(null); // Homestead should accept homestead
|
||||
preEIP155.getFrom(new BigInt(4)); // EIP155 should accept homestead (missing chain ID)
|
||||
postEIP155.getFrom(new BigInt(4)); // EIP155 should accept EIP 155
|
||||
|
||||
try {
|
||||
postEIP155.getFrom(null);
|
||||
fail("EIP155 transaction accepted by Homestead");
|
||||
} catch (Exception e) {}
|
||||
} catch (Exception e) {
|
||||
fail(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
// TestAndroid runs the Android java test class specified above.
|
||||
//
|
||||
// This requires the gradle command in PATH and the Android SDK whose path is available
|
||||
// through ANDROID_HOME environment variable. To successfully run the tests, an Android
|
||||
// device must also be available with debugging enabled.
|
||||
//
|
||||
// This method has been adapted from golang.org/x/mobile/bind/java/seq_test.go/runTest
|
||||
func TestAndroid(t *testing.T) {
|
||||
// Skip tests on Windows altogether
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("cannot test Android bindings on Windows, skipping")
|
||||
}
|
||||
// Make sure all the Android tools are installed
|
||||
if _, err := exec.Command("which", "gradle").CombinedOutput(); err != nil {
|
||||
t.Skip("command gradle not found, skipping")
|
||||
}
|
||||
if sdk := os.Getenv("ANDROID_HOME"); sdk == "" {
|
||||
// Android SDK not explicitly given, try to auto-resolve
|
||||
autopath := filepath.Join(os.Getenv("HOME"), "Android", "Sdk")
|
||||
if _, err := os.Stat(autopath); err != nil {
|
||||
t.Skip("ANDROID_HOME environment var not set, skipping")
|
||||
}
|
||||
os.Setenv("ANDROID_HOME", autopath)
|
||||
}
|
||||
if _, err := exec.Command("which", "gomobile").CombinedOutput(); err != nil {
|
||||
t.Log("gomobile missing, installing it...")
|
||||
if out, err := exec.Command("go", "get", "golang.org/x/mobile/cmd/gomobile").CombinedOutput(); err != nil {
|
||||
t.Fatalf("install failed: %v\n%s", err, string(out))
|
||||
}
|
||||
t.Log("initializing gomobile...")
|
||||
start := time.Now()
|
||||
if _, err := exec.Command("gomobile", "init").CombinedOutput(); err != nil {
|
||||
t.Fatalf("initialization failed: %v", err)
|
||||
}
|
||||
t.Logf("initialization took %v", time.Since(start))
|
||||
}
|
||||
// Create and switch to a temporary workspace
|
||||
workspace := t.TempDir()
|
||||
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to get current working directory: %v", err)
|
||||
}
|
||||
if err := os.Chdir(workspace); err != nil {
|
||||
t.Fatalf("failed to switch to temporary workspace: %v", err)
|
||||
}
|
||||
defer os.Chdir(pwd)
|
||||
|
||||
// Create the skeleton of the Android project
|
||||
for _, dir := range []string{"src/main", "src/androidTest/java/org/ethereum/gethtest", "libs"} {
|
||||
err = os.MkdirAll(dir, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
// Generate the mobile bindings for Geth and add the tester class
|
||||
gobind := exec.Command("gomobile", "bind", "-javapkg", "org.ethereum", "github.com/ethereum/go-ethereum/mobile")
|
||||
if output, err := gobind.CombinedOutput(); err != nil {
|
||||
t.Logf("%s", output)
|
||||
t.Fatalf("failed to run gomobile bind: %v", err)
|
||||
}
|
||||
cp.CopyFile(filepath.Join("libs", "geth.aar"), "geth.aar")
|
||||
|
||||
if err = os.WriteFile(filepath.Join("src", "androidTest", "java", "org", "ethereum", "gethtest", "AndroidTest.java"), []byte(androidTestClass), os.ModePerm); err != nil {
|
||||
t.Fatalf("failed to write Android test class: %v", err)
|
||||
}
|
||||
// Finish creating the project and run the tests via gradle
|
||||
if err = os.WriteFile(filepath.Join("src", "main", "AndroidManifest.xml"), []byte(androidManifest), os.ModePerm); err != nil {
|
||||
t.Fatalf("failed to write Android manifest: %v", err)
|
||||
}
|
||||
if err = os.WriteFile("build.gradle", []byte(gradleConfig), os.ModePerm); err != nil {
|
||||
t.Fatalf("failed to write gradle build file: %v", err)
|
||||
}
|
||||
if output, err := exec.Command("gradle", "connectedAndroidTest").CombinedOutput(); err != nil {
|
||||
t.Logf("%s", output)
|
||||
t.Errorf("failed to run gradle test: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
const androidManifest = `<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.ethereum.gethtest"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>`
|
||||
|
||||
const gradleConfig = `buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.3'
|
||||
}
|
||||
}
|
||||
allprojects {
|
||||
repositories { jcenter() }
|
||||
}
|
||||
apply plugin: 'com.android.library'
|
||||
android {
|
||||
compileSdkVersion 'android-19'
|
||||
buildToolsVersion '21.1.2'
|
||||
defaultConfig { minSdkVersion 15 }
|
||||
}
|
||||
repositories {
|
||||
flatDir { dirs 'libs' }
|
||||
}
|
||||
dependencies {
|
||||
compile 'com.android.support:appcompat-v7:19.0.0'
|
||||
compile(name: "geth", ext: "aar")
|
||||
}
|
||||
`
|
128
mobile/big.go
128
mobile/big.go
@ -1,128 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains all the wrappers from the math/big package.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// A BigInt represents a signed multi-precision integer.
|
||||
type BigInt struct {
|
||||
bigint *big.Int
|
||||
}
|
||||
|
||||
// NewBigInt allocates and returns a new BigInt set to x.
|
||||
func NewBigInt(x int64) *BigInt {
|
||||
return &BigInt{big.NewInt(x)}
|
||||
}
|
||||
|
||||
// NewBigIntFromString allocates and returns a new BigInt set to x
|
||||
// interpreted in the provided base.
|
||||
func NewBigIntFromString(x string, base int) *BigInt {
|
||||
b, success := new(big.Int).SetString(x, base)
|
||||
if !success {
|
||||
return nil
|
||||
}
|
||||
return &BigInt{b}
|
||||
}
|
||||
|
||||
// GetBytes returns the absolute value of x as a big-endian byte slice.
|
||||
func (bi *BigInt) GetBytes() []byte {
|
||||
return bi.bigint.Bytes()
|
||||
}
|
||||
|
||||
// String returns the value of x as a formatted decimal string.
|
||||
func (bi *BigInt) String() string {
|
||||
return bi.bigint.String()
|
||||
}
|
||||
|
||||
// GetInt64 returns the int64 representation of x. If x cannot be represented in
|
||||
// an int64, the result is undefined.
|
||||
func (bi *BigInt) GetInt64() int64 {
|
||||
return bi.bigint.Int64()
|
||||
}
|
||||
|
||||
// SetBytes interprets buf as the bytes of a big-endian unsigned integer and sets
|
||||
// the big int to that value.
|
||||
func (bi *BigInt) SetBytes(buf []byte) {
|
||||
bi.bigint.SetBytes(common.CopyBytes(buf))
|
||||
}
|
||||
|
||||
// SetInt64 sets the big int to x.
|
||||
func (bi *BigInt) SetInt64(x int64) {
|
||||
bi.bigint.SetInt64(x)
|
||||
}
|
||||
|
||||
// Sign returns:
|
||||
//
|
||||
// -1 if x < 0
|
||||
// 0 if x == 0
|
||||
// +1 if x > 0
|
||||
func (bi *BigInt) Sign() int {
|
||||
return bi.bigint.Sign()
|
||||
}
|
||||
|
||||
// SetString sets the big int to x.
|
||||
//
|
||||
// The string prefix determines the actual conversion base. A prefix of "0x" or
|
||||
// "0X" selects base 16; the "0" prefix selects base 8, and a "0b" or "0B" prefix
|
||||
// selects base 2. Otherwise the selected base is 10.
|
||||
func (bi *BigInt) SetString(x string, base int) {
|
||||
bi.bigint.SetString(x, base)
|
||||
}
|
||||
|
||||
// BigInts represents a slice of big ints.
|
||||
type BigInts struct{ bigints []*big.Int }
|
||||
|
||||
// NewBigInts creates a slice of uninitialized big numbers.
|
||||
func NewBigInts(size int) *BigInts {
|
||||
return &BigInts{
|
||||
bigints: make([]*big.Int, size),
|
||||
}
|
||||
}
|
||||
|
||||
// Size returns the number of big ints in the slice.
|
||||
func (bi *BigInts) Size() int {
|
||||
return len(bi.bigints)
|
||||
}
|
||||
|
||||
// Get returns the bigint at the given index from the slice.
|
||||
func (bi *BigInts) Get(index int) (bigint *BigInt, _ error) {
|
||||
if index < 0 || index >= len(bi.bigints) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return &BigInt{bi.bigints[index]}, nil
|
||||
}
|
||||
|
||||
// Set sets the big int at the given index in the slice.
|
||||
func (bi *BigInts) Set(index int, bigint *BigInt) error {
|
||||
if index < 0 || index >= len(bi.bigints) {
|
||||
return errors.New("index out of bounds")
|
||||
}
|
||||
bi.bigints[index] = bigint.bigint
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetString returns the value of x as a formatted string in some number base.
|
||||
func (bi *BigInt) GetString(base int) string {
|
||||
return bi.bigint.Text(base)
|
||||
}
|
213
mobile/bind.go
213
mobile/bind.go
@ -1,213 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains all the wrappers from the bind package.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// Signer is an interface defining the callback when a contract requires a
|
||||
// method to sign the transaction before submission.
|
||||
type Signer interface {
|
||||
Sign(addr *Address, unsignedTx *Transaction) (tx *Transaction, _ error)
|
||||
}
|
||||
|
||||
type MobileSigner struct {
|
||||
sign bind.SignerFn
|
||||
}
|
||||
|
||||
func (s *MobileSigner) Sign(addr *Address, unsignedTx *Transaction) (signedTx *Transaction, _ error) {
|
||||
sig, err := s.sign(addr.address, unsignedTx.tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Transaction{sig}, nil
|
||||
}
|
||||
|
||||
// CallOpts is the collection of options to fine tune a contract call request.
|
||||
type CallOpts struct {
|
||||
opts bind.CallOpts
|
||||
}
|
||||
|
||||
// NewCallOpts creates a new option set for contract calls.
|
||||
func NewCallOpts() *CallOpts {
|
||||
return new(CallOpts)
|
||||
}
|
||||
|
||||
func (opts *CallOpts) IsPending() bool { return opts.opts.Pending }
|
||||
func (opts *CallOpts) GetGasLimit() int64 { return 0 /* TODO(karalabe) */ }
|
||||
|
||||
// GetContext cannot be reliably implemented without identity preservation (https://github.com/golang/go/issues/16876)
|
||||
// Even then it's awkward to unpack the subtleties of a Go context out to Java.
|
||||
// func (opts *CallOpts) GetContext() *Context { return &Context{opts.opts.Context} }
|
||||
|
||||
func (opts *CallOpts) SetPending(pending bool) { opts.opts.Pending = pending }
|
||||
func (opts *CallOpts) SetGasLimit(limit int64) { /* TODO(karalabe) */ }
|
||||
func (opts *CallOpts) SetContext(context *Context) { opts.opts.Context = context.context }
|
||||
func (opts *CallOpts) SetFrom(addr *Address) { opts.opts.From = addr.address }
|
||||
|
||||
// TransactOpts is the collection of authorization data required to create a
|
||||
// valid Ethereum transaction.
|
||||
type TransactOpts struct {
|
||||
opts bind.TransactOpts
|
||||
}
|
||||
|
||||
// NewTransactOpts creates a new option set for contract transaction.
|
||||
func NewTransactOpts() *TransactOpts {
|
||||
return new(TransactOpts)
|
||||
}
|
||||
|
||||
// NewKeyedTransactOpts is a utility method to easily create a transaction signer
|
||||
// from a single private key.
|
||||
func NewKeyedTransactOpts(keyJson []byte, passphrase string, chainID *big.Int) (*TransactOpts, error) {
|
||||
key, err := keystore.DecryptKey(keyJson, passphrase)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
auth, err := bind.NewKeyedTransactorWithChainID(key.PrivateKey, chainID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &TransactOpts{*auth}, nil
|
||||
}
|
||||
|
||||
func (opts *TransactOpts) GetFrom() *Address { return &Address{opts.opts.From} }
|
||||
func (opts *TransactOpts) GetNonce() int64 { return opts.opts.Nonce.Int64() }
|
||||
func (opts *TransactOpts) GetValue() *BigInt { return &BigInt{opts.opts.Value} }
|
||||
func (opts *TransactOpts) GetGasPrice() *BigInt { return &BigInt{opts.opts.GasPrice} }
|
||||
func (opts *TransactOpts) GetGasLimit() int64 { return int64(opts.opts.GasLimit) }
|
||||
|
||||
// GetSigner cannot be reliably implemented without identity preservation (https://github.com/golang/go/issues/16876)
|
||||
// func (opts *TransactOpts) GetSigner() Signer { return &signer{opts.opts.Signer} }
|
||||
|
||||
// GetContext cannot be reliably implemented without identity preservation (https://github.com/golang/go/issues/16876)
|
||||
// Even then it's awkward to unpack the subtleties of a Go context out to Java.
|
||||
//func (opts *TransactOpts) GetContext() *Context { return &Context{opts.opts.Context} }
|
||||
|
||||
func (opts *TransactOpts) SetFrom(from *Address) { opts.opts.From = from.address }
|
||||
func (opts *TransactOpts) SetNonce(nonce int64) { opts.opts.Nonce = big.NewInt(nonce) }
|
||||
func (opts *TransactOpts) SetSigner(s Signer) {
|
||||
opts.opts.Signer = func(addr common.Address, tx *types.Transaction) (*types.Transaction, error) {
|
||||
sig, err := s.Sign(&Address{addr}, &Transaction{tx})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sig.tx, nil
|
||||
}
|
||||
}
|
||||
func (opts *TransactOpts) SetValue(value *BigInt) { opts.opts.Value = value.bigint }
|
||||
func (opts *TransactOpts) SetGasPrice(price *BigInt) { opts.opts.GasPrice = price.bigint }
|
||||
func (opts *TransactOpts) SetGasLimit(limit int64) { opts.opts.GasLimit = uint64(limit) }
|
||||
func (opts *TransactOpts) SetContext(context *Context) { opts.opts.Context = context.context }
|
||||
|
||||
// BoundContract is the base wrapper object that reflects a contract on the
|
||||
// Ethereum network. It contains a collection of methods that are used by the
|
||||
// higher level contract bindings to operate.
|
||||
type BoundContract struct {
|
||||
contract *bind.BoundContract
|
||||
address common.Address
|
||||
deployer *types.Transaction
|
||||
}
|
||||
|
||||
// DeployContract deploys a contract onto the Ethereum blockchain and binds the
|
||||
// deployment address with a wrapper.
|
||||
func DeployContract(opts *TransactOpts, abiJSON string, bytecode []byte, client *EthereumClient, args *Interfaces) (contract *BoundContract, _ error) {
|
||||
// Deploy the contract to the network
|
||||
parsed, err := abi.JSON(strings.NewReader(abiJSON))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addr, tx, bound, err := bind.DeployContract(&opts.opts, parsed, common.CopyBytes(bytecode), client.client, args.objects...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &BoundContract{
|
||||
contract: bound,
|
||||
address: addr,
|
||||
deployer: tx,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BindContract creates a low level contract interface through which calls and
|
||||
// transactions may be made through.
|
||||
func BindContract(address *Address, abiJSON string, client *EthereumClient) (contract *BoundContract, _ error) {
|
||||
parsed, err := abi.JSON(strings.NewReader(abiJSON))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &BoundContract{
|
||||
contract: bind.NewBoundContract(address.address, parsed, client.client, client.client, client.client),
|
||||
address: address.address,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *BoundContract) GetAddress() *Address { return &Address{c.address} }
|
||||
func (c *BoundContract) GetDeployer() *Transaction {
|
||||
if c.deployer == nil {
|
||||
return nil
|
||||
}
|
||||
return &Transaction{c.deployer}
|
||||
}
|
||||
|
||||
// Call invokes the (constant) contract method with params as input values and
|
||||
// sets the output to result.
|
||||
func (c *BoundContract) Call(opts *CallOpts, out *Interfaces, method string, args *Interfaces) error {
|
||||
results := make([]interface{}, len(out.objects))
|
||||
copy(results, out.objects)
|
||||
if err := c.contract.Call(&opts.opts, &results, method, args.objects...); err != nil {
|
||||
return err
|
||||
}
|
||||
copy(out.objects, results)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Transact invokes the (paid) contract method with params as input values.
|
||||
func (c *BoundContract) Transact(opts *TransactOpts, method string, args *Interfaces) (tx *Transaction, _ error) {
|
||||
rawTx, err := c.contract.Transact(&opts.opts, method, args.objects...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Transaction{rawTx}, nil
|
||||
}
|
||||
|
||||
// RawTransact invokes the (paid) contract method with raw calldata as input values.
|
||||
func (c *BoundContract) RawTransact(opts *TransactOpts, calldata []byte) (tx *Transaction, _ error) {
|
||||
rawTx, err := c.contract.RawTransact(&opts.opts, calldata)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Transaction{rawTx}, nil
|
||||
}
|
||||
|
||||
// Transfer initiates a plain transaction to move funds to the contract, calling
|
||||
// its default method if one is available.
|
||||
func (c *BoundContract) Transfer(opts *TransactOpts) (tx *Transaction, _ error) {
|
||||
rawTx, err := c.contract.Transfer(&opts.opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Transaction{rawTx}, nil
|
||||
}
|
251
mobile/common.go
251
mobile/common.go
@ -1,251 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains all the wrappers from the common package.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
)
|
||||
|
||||
// Hash represents the 32 byte Keccak256 hash of arbitrary data.
|
||||
type Hash struct {
|
||||
hash common.Hash
|
||||
}
|
||||
|
||||
// NewHashFromBytes converts a slice of bytes to a hash value.
|
||||
func NewHashFromBytes(binary []byte) (hash *Hash, _ error) {
|
||||
h := new(Hash)
|
||||
if err := h.SetBytes(common.CopyBytes(binary)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// NewHashFromHex converts a hex string to a hash value.
|
||||
func NewHashFromHex(hex string) (hash *Hash, _ error) {
|
||||
h := new(Hash)
|
||||
if err := h.SetHex(hex); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// SetBytes sets the specified slice of bytes as the hash value.
|
||||
func (h *Hash) SetBytes(hash []byte) error {
|
||||
if length := len(hash); length != common.HashLength {
|
||||
return fmt.Errorf("invalid hash length: %v != %v", length, common.HashLength)
|
||||
}
|
||||
copy(h.hash[:], hash)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBytes retrieves the byte representation of the hash.
|
||||
func (h *Hash) GetBytes() []byte {
|
||||
return h.hash[:]
|
||||
}
|
||||
|
||||
// SetHex sets the specified hex string as the hash value.
|
||||
func (h *Hash) SetHex(hash string) error {
|
||||
hash = strings.ToLower(hash)
|
||||
if len(hash) >= 2 && hash[:2] == "0x" {
|
||||
hash = hash[2:]
|
||||
}
|
||||
if length := len(hash); length != 2*common.HashLength {
|
||||
return fmt.Errorf("invalid hash hex length: %v != %v", length, 2*common.HashLength)
|
||||
}
|
||||
bin, err := hex.DecodeString(hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copy(h.hash[:], bin)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetHex retrieves the hex string representation of the hash.
|
||||
func (h *Hash) GetHex() string {
|
||||
return h.hash.Hex()
|
||||
}
|
||||
|
||||
// String implements Stringer interface for printable representation of the hash.
|
||||
func (h *Hash) String() string {
|
||||
return h.GetHex()
|
||||
}
|
||||
|
||||
// Hashes represents a slice of hashes.
|
||||
type Hashes struct{ hashes []common.Hash }
|
||||
|
||||
// NewHashes creates a slice of uninitialized Hashes.
|
||||
func NewHashes(size int) *Hashes {
|
||||
return &Hashes{
|
||||
hashes: make([]common.Hash, size),
|
||||
}
|
||||
}
|
||||
|
||||
// NewHashesEmpty creates an empty slice of Hashes values.
|
||||
func NewHashesEmpty() *Hashes {
|
||||
return NewHashes(0)
|
||||
}
|
||||
|
||||
// Size returns the number of hashes in the slice.
|
||||
func (h *Hashes) Size() int {
|
||||
return len(h.hashes)
|
||||
}
|
||||
|
||||
// Get returns the hash at the given index from the slice.
|
||||
func (h *Hashes) Get(index int) (hash *Hash, _ error) {
|
||||
if index < 0 || index >= len(h.hashes) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return &Hash{h.hashes[index]}, nil
|
||||
}
|
||||
|
||||
// Set sets the Hash at the given index in the slice.
|
||||
func (h *Hashes) Set(index int, hash *Hash) error {
|
||||
if index < 0 || index >= len(h.hashes) {
|
||||
return errors.New("index out of bounds")
|
||||
}
|
||||
h.hashes[index] = hash.hash
|
||||
return nil
|
||||
}
|
||||
|
||||
// Append adds a new Hash element to the end of the slice.
|
||||
func (h *Hashes) Append(hash *Hash) {
|
||||
h.hashes = append(h.hashes, hash.hash)
|
||||
}
|
||||
|
||||
// Address represents the 20 byte address of an Ethereum account.
|
||||
type Address struct {
|
||||
address common.Address
|
||||
}
|
||||
|
||||
// NewAddressFromBytes converts a slice of bytes to a hash value.
|
||||
func NewAddressFromBytes(binary []byte) (address *Address, _ error) {
|
||||
a := new(Address)
|
||||
if err := a.SetBytes(common.CopyBytes(binary)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// NewAddressFromHex converts a hex string to a address value.
|
||||
func NewAddressFromHex(hex string) (address *Address, _ error) {
|
||||
a := new(Address)
|
||||
if err := a.SetHex(hex); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// SetBytes sets the specified slice of bytes as the address value.
|
||||
func (a *Address) SetBytes(address []byte) error {
|
||||
if length := len(address); length != common.AddressLength {
|
||||
return fmt.Errorf("invalid address length: %v != %v", length, common.AddressLength)
|
||||
}
|
||||
copy(a.address[:], address)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBytes retrieves the byte representation of the address.
|
||||
func (a *Address) GetBytes() []byte {
|
||||
return a.address[:]
|
||||
}
|
||||
|
||||
// SetHex sets the specified hex string as the address value.
|
||||
func (a *Address) SetHex(address string) error {
|
||||
address = strings.ToLower(address)
|
||||
if len(address) >= 2 && address[:2] == "0x" {
|
||||
address = address[2:]
|
||||
}
|
||||
if length := len(address); length != 2*common.AddressLength {
|
||||
return fmt.Errorf("invalid address hex length: %v != %v", length, 2*common.AddressLength)
|
||||
}
|
||||
bin, err := hex.DecodeString(address)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
copy(a.address[:], bin)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetHex retrieves the hex string representation of the address.
|
||||
func (a *Address) GetHex() string {
|
||||
return a.address.Hex()
|
||||
}
|
||||
|
||||
// String returns a printable representation of the address.
|
||||
func (a *Address) String() string {
|
||||
return a.GetHex()
|
||||
}
|
||||
|
||||
// Addresses represents a slice of addresses.
|
||||
type Addresses struct{ addresses []common.Address }
|
||||
|
||||
// NewAddresses creates a slice of uninitialized addresses.
|
||||
func NewAddresses(size int) *Addresses {
|
||||
return &Addresses{
|
||||
addresses: make([]common.Address, size),
|
||||
}
|
||||
}
|
||||
|
||||
// NewAddressesEmpty creates an empty slice of Addresses values.
|
||||
func NewAddressesEmpty() *Addresses {
|
||||
return NewAddresses(0)
|
||||
}
|
||||
|
||||
// Size returns the number of addresses in the slice.
|
||||
func (a *Addresses) Size() int {
|
||||
return len(a.addresses)
|
||||
}
|
||||
|
||||
// Get returns the address at the given index from the slice.
|
||||
func (a *Addresses) Get(index int) (address *Address, _ error) {
|
||||
if index < 0 || index >= len(a.addresses) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return &Address{a.addresses[index]}, nil
|
||||
}
|
||||
|
||||
// Set sets the address at the given index in the slice.
|
||||
func (a *Addresses) Set(index int, address *Address) error {
|
||||
if index < 0 || index >= len(a.addresses) {
|
||||
return errors.New("index out of bounds")
|
||||
}
|
||||
a.addresses[index] = address.address
|
||||
return nil
|
||||
}
|
||||
|
||||
// Append adds a new address element to the end of the slice.
|
||||
func (a *Addresses) Append(address *Address) {
|
||||
a.addresses = append(a.addresses, address.address)
|
||||
}
|
||||
|
||||
// EncodeToHex encodes b as a hex string with 0x prefix.
|
||||
func EncodeToHex(b []byte) string {
|
||||
return hexutil.Encode(b)
|
||||
}
|
||||
|
||||
// DecodeFromHex decodes a hex string with 0x prefix.
|
||||
func DecodeFromHex(s string) ([]byte, error) {
|
||||
return hexutil.Decode(s)
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains all the wrappers from the golang.org/x/net/context package to support
|
||||
// client side context management on mobile platforms.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Context carries a deadline, a cancellation signal, and other values across API
|
||||
// boundaries.
|
||||
type Context struct {
|
||||
context context.Context
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
// NewContext returns a non-nil, empty Context. It is never canceled, has no
|
||||
// values, and has no deadline. It is typically used by the main function,
|
||||
// initialization, and tests, and as the top-level Context for incoming requests.
|
||||
func NewContext() *Context {
|
||||
return &Context{
|
||||
context: context.Background(),
|
||||
}
|
||||
}
|
||||
|
||||
// WithCancel returns a copy of the original context with cancellation mechanism
|
||||
// included.
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete.
|
||||
func (c *Context) WithCancel() *Context {
|
||||
child, cancel := context.WithCancel(c.context)
|
||||
return &Context{
|
||||
context: child,
|
||||
cancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
// WithDeadline returns a copy of the original context with the deadline adjusted
|
||||
// to be no later than the specified time.
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete.
|
||||
func (c *Context) WithDeadline(sec int64, nsec int64) *Context {
|
||||
child, cancel := context.WithDeadline(c.context, time.Unix(sec, nsec))
|
||||
return &Context{
|
||||
context: child,
|
||||
cancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
// WithTimeout returns a copy of the original context with the deadline adjusted
|
||||
// to be no later than now + the duration specified.
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete.
|
||||
func (c *Context) WithTimeout(nsec int64) *Context {
|
||||
child, cancel := context.WithTimeout(c.context, time.Duration(nsec))
|
||||
return &Context{
|
||||
context: child,
|
||||
cancel: cancel,
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains all the wrappers from the accounts package to support client side enode
|
||||
// management on mobile platforms.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
)
|
||||
|
||||
// Enode represents a host on the network.
|
||||
type Enode struct {
|
||||
node *enode.Node
|
||||
}
|
||||
|
||||
// NewEnode parses a node designator.
|
||||
//
|
||||
// There are two basic forms of node designators
|
||||
// - incomplete nodes, which only have the public key (node ID)
|
||||
// - complete nodes, which contain the public key and IP/Port information
|
||||
//
|
||||
// For incomplete nodes, the designator must look like one of these
|
||||
//
|
||||
// enode://<hex node id>
|
||||
// <hex node id>
|
||||
//
|
||||
// For complete nodes, the node ID is encoded in the username portion
|
||||
// of the URL, separated from the host by an @ sign. The hostname can
|
||||
// only be given as an IP address, DNS domain names are not allowed.
|
||||
// The port in the host name section is the TCP listening port. If the
|
||||
// TCP and UDP (discovery) ports differ, the UDP port is specified as
|
||||
// query parameter "discport".
|
||||
//
|
||||
// In the following example, the node URL describes
|
||||
// a node with IP address 10.3.58.6, TCP listening port 30303
|
||||
// and UDP discovery port 30301.
|
||||
//
|
||||
// enode://<hex node id>@10.3.58.6:30303?discport=30301
|
||||
func NewEnode(rawurl string) (*Enode, error) {
|
||||
node, err := enode.Parse(enode.ValidSchemes, rawurl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Enode{node}, nil
|
||||
}
|
||||
|
||||
// Enodes represents a slice of accounts.
|
||||
type Enodes struct{ nodes []*enode.Node }
|
||||
|
||||
// NewEnodes creates a slice of uninitialized enodes.
|
||||
func NewEnodes(size int) *Enodes {
|
||||
return &Enodes{
|
||||
nodes: make([]*enode.Node, size),
|
||||
}
|
||||
}
|
||||
|
||||
// NewEnodesEmpty creates an empty slice of Enode values.
|
||||
func NewEnodesEmpty() *Enodes {
|
||||
return NewEnodes(0)
|
||||
}
|
||||
|
||||
// Size returns the number of enodes in the slice.
|
||||
func (e *Enodes) Size() int {
|
||||
return len(e.nodes)
|
||||
}
|
||||
|
||||
// Get returns the enode at the given index from the slice.
|
||||
func (e *Enodes) Get(index int) (enode *Enode, _ error) {
|
||||
if index < 0 || index >= len(e.nodes) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return &Enode{e.nodes[index]}, nil
|
||||
}
|
||||
|
||||
// Set sets the enode at the given index in the slice.
|
||||
func (e *Enodes) Set(index int, enode *Enode) error {
|
||||
if index < 0 || index >= len(e.nodes) {
|
||||
return errors.New("index out of bounds")
|
||||
}
|
||||
e.nodes[index] = enode.node
|
||||
return nil
|
||||
}
|
||||
|
||||
// Append adds a new enode element to the end of the slice.
|
||||
func (e *Enodes) Append(enode *Enode) {
|
||||
e.nodes = append(e.nodes, enode.node)
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
// 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 geth contains the simplified mobile APIs to go-ethereum.
|
||||
//
|
||||
// The scope of this package is *not* to allow writing a custom Ethereum client
|
||||
// with pieces plucked from go-ethereum, rather to allow writing native dapps on
|
||||
// mobile platforms. Keep this in mind when using or extending this package!
|
||||
//
|
||||
// # API limitations
|
||||
//
|
||||
// Since gomobile cannot bridge arbitrary types between Go and Android/iOS, the
|
||||
// exposed APIs need to be manually wrapped into simplified types, with custom
|
||||
// constructors and getters/setters to ensure that they can be meaningfully used
|
||||
// from Java/ObjC too.
|
||||
//
|
||||
// With this in mind, please try to limit the scope of this package and only add
|
||||
// essentials without which mobile support cannot work, especially since manually
|
||||
// syncing the code will be unwieldy otherwise. In the long term we might consider
|
||||
// writing custom library generators, but those are out of scope now.
|
||||
//
|
||||
// Content wise each file in this package corresponds to an entire Go package
|
||||
// from the go-ethereum repository. Please adhere to this scoping to prevent this
|
||||
// package getting unmaintainable.
|
||||
//
|
||||
// Wrapping guidelines:
|
||||
//
|
||||
// Every type that is to be exposed should be wrapped into its own plain struct,
|
||||
// which internally contains a single field: the original go-ethereum version.
|
||||
// This is needed because gomobile cannot expose named types for now.
|
||||
//
|
||||
// Whenever a method argument or a return type is a custom struct, the pointer
|
||||
// variant should always be used as value types crossing over between language
|
||||
// boundaries might have strange behaviors.
|
||||
//
|
||||
// Slices of types should be converted into a single multiplicative type wrapping
|
||||
// a go slice with the methods `Size`, `Get` and `Set`. Further slice operations
|
||||
// should not be provided to limit the remote code complexity. Arrays should be
|
||||
// avoided as much as possible since they complicate bounds checking.
|
||||
//
|
||||
// If a method has multiple return values (e.g. some return + an error), those
|
||||
// are generated as output arguments in ObjC. To avoid weird generated names like
|
||||
// ret_0 for them, please always assign names to output variables if tuples.
|
||||
//
|
||||
// Note, a panic *cannot* cross over language boundaries, instead will result in
|
||||
// an undebuggable SEGFAULT in the process. For error handling only ever use error
|
||||
// returns, which may be the only or the second return.
|
||||
package geth
|
@ -1,315 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains a wrapper for the Ethereum client.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
)
|
||||
|
||||
// EthereumClient provides access to the Ethereum APIs.
|
||||
type EthereumClient struct {
|
||||
client *ethclient.Client
|
||||
}
|
||||
|
||||
// NewEthereumClient connects a client to the given URL.
|
||||
func NewEthereumClient(rawurl string) (client *EthereumClient, _ error) {
|
||||
rawClient, err := ethclient.Dial(rawurl)
|
||||
return &EthereumClient{rawClient}, err
|
||||
}
|
||||
|
||||
// GetBlockByHash returns the given full block.
|
||||
func (ec *EthereumClient) GetBlockByHash(ctx *Context, hash *Hash) (block *Block, _ error) {
|
||||
rawBlock, err := ec.client.BlockByHash(ctx.context, hash.hash)
|
||||
return &Block{rawBlock}, err
|
||||
}
|
||||
|
||||
// GetBlockByNumber returns a block from the current canonical chain. If number is <0, the
|
||||
// latest known block is returned.
|
||||
func (ec *EthereumClient) GetBlockByNumber(ctx *Context, number int64) (block *Block, _ error) {
|
||||
if number < 0 {
|
||||
rawBlock, err := ec.client.BlockByNumber(ctx.context, nil)
|
||||
return &Block{rawBlock}, err
|
||||
}
|
||||
rawBlock, err := ec.client.BlockByNumber(ctx.context, big.NewInt(number))
|
||||
return &Block{rawBlock}, err
|
||||
}
|
||||
|
||||
// GetHeaderByHash returns the block header with the given hash.
|
||||
func (ec *EthereumClient) GetHeaderByHash(ctx *Context, hash *Hash) (header *Header, _ error) {
|
||||
rawHeader, err := ec.client.HeaderByHash(ctx.context, hash.hash)
|
||||
return &Header{rawHeader}, err
|
||||
}
|
||||
|
||||
// GetHeaderByNumber returns a block header from the current canonical chain. If number is <0,
|
||||
// the latest known header is returned.
|
||||
func (ec *EthereumClient) GetHeaderByNumber(ctx *Context, number int64) (header *Header, _ error) {
|
||||
if number < 0 {
|
||||
rawHeader, err := ec.client.HeaderByNumber(ctx.context, nil)
|
||||
return &Header{rawHeader}, err
|
||||
}
|
||||
rawHeader, err := ec.client.HeaderByNumber(ctx.context, big.NewInt(number))
|
||||
return &Header{rawHeader}, err
|
||||
}
|
||||
|
||||
// GetTransactionByHash returns the transaction with the given hash.
|
||||
func (ec *EthereumClient) GetTransactionByHash(ctx *Context, hash *Hash) (tx *Transaction, _ error) {
|
||||
// TODO(karalabe): handle isPending
|
||||
rawTx, _, err := ec.client.TransactionByHash(ctx.context, hash.hash)
|
||||
return &Transaction{rawTx}, err
|
||||
}
|
||||
|
||||
// GetTransactionSender returns the sender address of a transaction. The transaction must
|
||||
// be included in blockchain at the given block and index.
|
||||
func (ec *EthereumClient) GetTransactionSender(ctx *Context, tx *Transaction, blockhash *Hash, index int) (sender *Address, _ error) {
|
||||
addr, err := ec.client.TransactionSender(ctx.context, tx.tx, blockhash.hash, uint(index))
|
||||
return &Address{addr}, err
|
||||
}
|
||||
|
||||
// GetTransactionCount returns the total number of transactions in the given block.
|
||||
func (ec *EthereumClient) GetTransactionCount(ctx *Context, hash *Hash) (count int, _ error) {
|
||||
rawCount, err := ec.client.TransactionCount(ctx.context, hash.hash)
|
||||
return int(rawCount), err
|
||||
}
|
||||
|
||||
// GetTransactionInBlock returns a single transaction at index in the given block.
|
||||
func (ec *EthereumClient) GetTransactionInBlock(ctx *Context, hash *Hash, index int) (tx *Transaction, _ error) {
|
||||
rawTx, err := ec.client.TransactionInBlock(ctx.context, hash.hash, uint(index))
|
||||
return &Transaction{rawTx}, err
|
||||
}
|
||||
|
||||
// GetTransactionReceipt returns the receipt of a transaction by transaction hash.
|
||||
// Note that the receipt is not available for pending transactions.
|
||||
func (ec *EthereumClient) GetTransactionReceipt(ctx *Context, hash *Hash) (receipt *Receipt, _ error) {
|
||||
rawReceipt, err := ec.client.TransactionReceipt(ctx.context, hash.hash)
|
||||
return &Receipt{rawReceipt}, err
|
||||
}
|
||||
|
||||
// SyncProgress retrieves the current progress of the sync algorithm. If there's
|
||||
// no sync currently running, it returns nil.
|
||||
func (ec *EthereumClient) SyncProgress(ctx *Context) (progress *SyncProgress, _ error) {
|
||||
rawProgress, err := ec.client.SyncProgress(ctx.context)
|
||||
if rawProgress == nil {
|
||||
return nil, err
|
||||
}
|
||||
return &SyncProgress{*rawProgress}, err
|
||||
}
|
||||
|
||||
// NewHeadHandler is a client-side subscription callback to invoke on events and
|
||||
// subscription failure.
|
||||
type NewHeadHandler interface {
|
||||
OnNewHead(header *Header)
|
||||
OnError(failure string)
|
||||
}
|
||||
|
||||
// SubscribeNewHead subscribes to notifications about the current blockchain head
|
||||
// on the given channel.
|
||||
func (ec *EthereumClient) SubscribeNewHead(ctx *Context, handler NewHeadHandler, buffer int) (sub *Subscription, _ error) {
|
||||
// Subscribe to the event internally
|
||||
ch := make(chan *types.Header, buffer)
|
||||
rawSub, err := ec.client.SubscribeNewHead(ctx.context, ch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Start up a dispatcher to feed into the callback
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case header := <-ch:
|
||||
handler.OnNewHead(&Header{header})
|
||||
|
||||
case err := <-rawSub.Err():
|
||||
if err != nil {
|
||||
handler.OnError(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return &Subscription{rawSub}, nil
|
||||
}
|
||||
|
||||
// State Access
|
||||
|
||||
// GetBalanceAt returns the wei balance of the given account.
|
||||
// The block number can be <0, in which case the balance is taken from the latest known block.
|
||||
func (ec *EthereumClient) GetBalanceAt(ctx *Context, account *Address, number int64) (balance *BigInt, _ error) {
|
||||
if number < 0 {
|
||||
rawBalance, err := ec.client.BalanceAt(ctx.context, account.address, nil)
|
||||
return &BigInt{rawBalance}, err
|
||||
}
|
||||
rawBalance, err := ec.client.BalanceAt(ctx.context, account.address, big.NewInt(number))
|
||||
return &BigInt{rawBalance}, err
|
||||
}
|
||||
|
||||
// GetStorageAt returns the value of key in the contract storage of the given account.
|
||||
// The block number can be <0, in which case the value is taken from the latest known block.
|
||||
func (ec *EthereumClient) GetStorageAt(ctx *Context, account *Address, key *Hash, number int64) (storage []byte, _ error) {
|
||||
if number < 0 {
|
||||
return ec.client.StorageAt(ctx.context, account.address, key.hash, nil)
|
||||
}
|
||||
return ec.client.StorageAt(ctx.context, account.address, key.hash, big.NewInt(number))
|
||||
}
|
||||
|
||||
// GetCodeAt returns the contract code of the given account.
|
||||
// The block number can be <0, in which case the code is taken from the latest known block.
|
||||
func (ec *EthereumClient) GetCodeAt(ctx *Context, account *Address, number int64) (code []byte, _ error) {
|
||||
if number < 0 {
|
||||
return ec.client.CodeAt(ctx.context, account.address, nil)
|
||||
}
|
||||
return ec.client.CodeAt(ctx.context, account.address, big.NewInt(number))
|
||||
}
|
||||
|
||||
// GetNonceAt returns the account nonce of the given account.
|
||||
// The block number can be <0, in which case the nonce is taken from the latest known block.
|
||||
func (ec *EthereumClient) GetNonceAt(ctx *Context, account *Address, number int64) (nonce int64, _ error) {
|
||||
if number < 0 {
|
||||
rawNonce, err := ec.client.NonceAt(ctx.context, account.address, nil)
|
||||
return int64(rawNonce), err
|
||||
}
|
||||
rawNonce, err := ec.client.NonceAt(ctx.context, account.address, big.NewInt(number))
|
||||
return int64(rawNonce), err
|
||||
}
|
||||
|
||||
// Filters
|
||||
|
||||
// FilterLogs executes a filter query.
|
||||
func (ec *EthereumClient) FilterLogs(ctx *Context, query *FilterQuery) (logs *Logs, _ error) {
|
||||
rawLogs, err := ec.client.FilterLogs(ctx.context, query.query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Temp hack due to vm.Logs being []*vm.Log
|
||||
res := make([]*types.Log, len(rawLogs))
|
||||
for i := range rawLogs {
|
||||
res[i] = &rawLogs[i]
|
||||
}
|
||||
return &Logs{res}, nil
|
||||
}
|
||||
|
||||
// FilterLogsHandler is a client-side subscription callback to invoke on events and
|
||||
// subscription failure.
|
||||
type FilterLogsHandler interface {
|
||||
OnFilterLogs(log *Log)
|
||||
OnError(failure string)
|
||||
}
|
||||
|
||||
// SubscribeFilterLogs subscribes to the results of a streaming filter query.
|
||||
func (ec *EthereumClient) SubscribeFilterLogs(ctx *Context, query *FilterQuery, handler FilterLogsHandler, buffer int) (sub *Subscription, _ error) {
|
||||
// Subscribe to the event internally
|
||||
ch := make(chan types.Log, buffer)
|
||||
rawSub, err := ec.client.SubscribeFilterLogs(ctx.context, query.query, ch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Start up a dispatcher to feed into the callback
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case log := <-ch:
|
||||
handler.OnFilterLogs(&Log{&log})
|
||||
|
||||
case err := <-rawSub.Err():
|
||||
if err != nil {
|
||||
handler.OnError(err.Error())
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
return &Subscription{rawSub}, nil
|
||||
}
|
||||
|
||||
// Pending State
|
||||
|
||||
// GetPendingBalanceAt returns the wei balance of the given account in the pending state.
|
||||
func (ec *EthereumClient) GetPendingBalanceAt(ctx *Context, account *Address) (balance *BigInt, _ error) {
|
||||
rawBalance, err := ec.client.PendingBalanceAt(ctx.context, account.address)
|
||||
return &BigInt{rawBalance}, err
|
||||
}
|
||||
|
||||
// GetPendingStorageAt returns the value of key in the contract storage of the given account in the pending state.
|
||||
func (ec *EthereumClient) GetPendingStorageAt(ctx *Context, account *Address, key *Hash) (storage []byte, _ error) {
|
||||
return ec.client.PendingStorageAt(ctx.context, account.address, key.hash)
|
||||
}
|
||||
|
||||
// GetPendingCodeAt returns the contract code of the given account in the pending state.
|
||||
func (ec *EthereumClient) GetPendingCodeAt(ctx *Context, account *Address) (code []byte, _ error) {
|
||||
return ec.client.PendingCodeAt(ctx.context, account.address)
|
||||
}
|
||||
|
||||
// GetPendingNonceAt returns the account nonce of the given account in the pending state.
|
||||
// This is the nonce that should be used for the next transaction.
|
||||
func (ec *EthereumClient) GetPendingNonceAt(ctx *Context, account *Address) (nonce int64, _ error) {
|
||||
rawNonce, err := ec.client.PendingNonceAt(ctx.context, account.address)
|
||||
return int64(rawNonce), err
|
||||
}
|
||||
|
||||
// GetPendingTransactionCount returns the total number of transactions in the pending state.
|
||||
func (ec *EthereumClient) GetPendingTransactionCount(ctx *Context) (count int, _ error) {
|
||||
rawCount, err := ec.client.PendingTransactionCount(ctx.context)
|
||||
return int(rawCount), err
|
||||
}
|
||||
|
||||
// Contract Calling
|
||||
|
||||
// CallContract executes a message call transaction, which is directly executed in the VM
|
||||
// of the node, but never mined into the blockchain.
|
||||
//
|
||||
// blockNumber selects the block height at which the call runs. It can be <0, in which
|
||||
// case the code is taken from the latest known block. Note that state from very old
|
||||
// blocks might not be available.
|
||||
func (ec *EthereumClient) CallContract(ctx *Context, msg *CallMsg, number int64) (output []byte, _ error) {
|
||||
if number < 0 {
|
||||
return ec.client.CallContract(ctx.context, msg.msg, nil)
|
||||
}
|
||||
return ec.client.CallContract(ctx.context, msg.msg, big.NewInt(number))
|
||||
}
|
||||
|
||||
// PendingCallContract executes a message call transaction using the EVM.
|
||||
// The state seen by the contract call is the pending state.
|
||||
func (ec *EthereumClient) PendingCallContract(ctx *Context, msg *CallMsg) (output []byte, _ error) {
|
||||
return ec.client.PendingCallContract(ctx.context, msg.msg)
|
||||
}
|
||||
|
||||
// SuggestGasPrice retrieves the currently suggested gas price to allow a timely
|
||||
// execution of a transaction.
|
||||
func (ec *EthereumClient) SuggestGasPrice(ctx *Context) (price *BigInt, _ error) {
|
||||
rawPrice, err := ec.client.SuggestGasPrice(ctx.context)
|
||||
return &BigInt{rawPrice}, err
|
||||
}
|
||||
|
||||
// EstimateGas tries to estimate the gas needed to execute a specific transaction based on
|
||||
// the current pending state of the backend blockchain. There is no guarantee that this is
|
||||
// the true gas limit requirement as other transactions may be added or removed by miners,
|
||||
// but it should provide a basis for setting a reasonable default.
|
||||
func (ec *EthereumClient) EstimateGas(ctx *Context, msg *CallMsg) (gas int64, _ error) {
|
||||
rawGas, err := ec.client.EstimateGas(ctx.context, msg.msg)
|
||||
return int64(rawGas), err
|
||||
}
|
||||
|
||||
// SendTransaction injects a signed transaction into the pending pool for execution.
|
||||
//
|
||||
// If the transaction was a contract creation use the TransactionReceipt method to get the
|
||||
// contract address after the transaction has been mined.
|
||||
func (ec *EthereumClient) SendTransaction(ctx *Context, tx *Transaction) error {
|
||||
return ec.client.SendTransaction(ctx.context, tx.tx)
|
||||
}
|
@ -1,157 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains all the wrappers from the go-ethereum root package.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// Subscription represents an event subscription where events are
|
||||
// delivered on a data channel.
|
||||
type Subscription struct {
|
||||
sub ethereum.Subscription
|
||||
}
|
||||
|
||||
// Unsubscribe cancels the sending of events to the data channel
|
||||
// and closes the error channel.
|
||||
func (s *Subscription) Unsubscribe() {
|
||||
s.sub.Unsubscribe()
|
||||
}
|
||||
|
||||
// CallMsg contains parameters for contract calls.
|
||||
type CallMsg struct {
|
||||
msg ethereum.CallMsg
|
||||
}
|
||||
|
||||
// NewCallMsg creates an empty contract call parameter list.
|
||||
func NewCallMsg() *CallMsg {
|
||||
return new(CallMsg)
|
||||
}
|
||||
|
||||
func (msg *CallMsg) GetFrom() *Address { return &Address{msg.msg.From} }
|
||||
func (msg *CallMsg) GetGas() int64 { return int64(msg.msg.Gas) }
|
||||
func (msg *CallMsg) GetGasPrice() *BigInt { return &BigInt{msg.msg.GasPrice} }
|
||||
func (msg *CallMsg) GetValue() *BigInt { return &BigInt{msg.msg.Value} }
|
||||
func (msg *CallMsg) GetData() []byte { return msg.msg.Data }
|
||||
func (msg *CallMsg) GetTo() *Address {
|
||||
if to := msg.msg.To; to != nil {
|
||||
return &Address{*msg.msg.To}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *CallMsg) SetFrom(address *Address) { msg.msg.From = address.address }
|
||||
func (msg *CallMsg) SetGas(gas int64) { msg.msg.Gas = uint64(gas) }
|
||||
func (msg *CallMsg) SetGasPrice(price *BigInt) { msg.msg.GasPrice = price.bigint }
|
||||
func (msg *CallMsg) SetValue(value *BigInt) { msg.msg.Value = value.bigint }
|
||||
func (msg *CallMsg) SetData(data []byte) { msg.msg.Data = common.CopyBytes(data) }
|
||||
func (msg *CallMsg) SetTo(address *Address) {
|
||||
if address == nil {
|
||||
msg.msg.To = nil
|
||||
return
|
||||
}
|
||||
msg.msg.To = &address.address
|
||||
}
|
||||
|
||||
// SyncProgress gives progress indications when the node is synchronising with
|
||||
// the Ethereum network.
|
||||
type SyncProgress struct {
|
||||
progress ethereum.SyncProgress
|
||||
}
|
||||
|
||||
func (p *SyncProgress) GetStartingBlock() int64 { return int64(p.progress.StartingBlock) }
|
||||
func (p *SyncProgress) GetCurrentBlock() int64 { return int64(p.progress.CurrentBlock) }
|
||||
func (p *SyncProgress) GetHighestBlock() int64 { return int64(p.progress.HighestBlock) }
|
||||
func (p *SyncProgress) GetSyncedAccounts() int64 { return int64(p.progress.SyncedAccounts) }
|
||||
func (p *SyncProgress) GetSyncedAccountBytes() int64 { return int64(p.progress.SyncedAccountBytes) }
|
||||
func (p *SyncProgress) GetSyncedBytecodes() int64 { return int64(p.progress.SyncedBytecodes) }
|
||||
func (p *SyncProgress) GetSyncedBytecodeBytes() int64 { return int64(p.progress.SyncedBytecodeBytes) }
|
||||
func (p *SyncProgress) GetSyncedStorage() int64 { return int64(p.progress.SyncedStorage) }
|
||||
func (p *SyncProgress) GetSyncedStorageBytes() int64 { return int64(p.progress.SyncedStorageBytes) }
|
||||
func (p *SyncProgress) GetHealedTrienodes() int64 { return int64(p.progress.HealedTrienodes) }
|
||||
func (p *SyncProgress) GetHealedTrienodeBytes() int64 { return int64(p.progress.HealedTrienodeBytes) }
|
||||
func (p *SyncProgress) GetHealedBytecodes() int64 { return int64(p.progress.HealedBytecodes) }
|
||||
func (p *SyncProgress) GetHealedBytecodeBytes() int64 { return int64(p.progress.HealedBytecodeBytes) }
|
||||
func (p *SyncProgress) GetHealingTrienodes() int64 { return int64(p.progress.HealingTrienodes) }
|
||||
func (p *SyncProgress) GetHealingBytecode() int64 { return int64(p.progress.HealingBytecode) }
|
||||
|
||||
// Topics is a set of topic lists to filter events with.
|
||||
type Topics struct{ topics [][]common.Hash }
|
||||
|
||||
// NewTopics creates a slice of uninitialized Topics.
|
||||
func NewTopics(size int) *Topics {
|
||||
return &Topics{
|
||||
topics: make([][]common.Hash, size),
|
||||
}
|
||||
}
|
||||
|
||||
// NewTopicsEmpty creates an empty slice of Topics values.
|
||||
func NewTopicsEmpty() *Topics {
|
||||
return NewTopics(0)
|
||||
}
|
||||
|
||||
// Size returns the number of topic lists inside the set
|
||||
func (t *Topics) Size() int {
|
||||
return len(t.topics)
|
||||
}
|
||||
|
||||
// Get returns the topic list at the given index from the slice.
|
||||
func (t *Topics) Get(index int) (hashes *Hashes, _ error) {
|
||||
if index < 0 || index >= len(t.topics) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return &Hashes{t.topics[index]}, nil
|
||||
}
|
||||
|
||||
// Set sets the topic list at the given index in the slice.
|
||||
func (t *Topics) Set(index int, topics *Hashes) error {
|
||||
if index < 0 || index >= len(t.topics) {
|
||||
return errors.New("index out of bounds")
|
||||
}
|
||||
t.topics[index] = topics.hashes
|
||||
return nil
|
||||
}
|
||||
|
||||
// Append adds a new topic list to the end of the slice.
|
||||
func (t *Topics) Append(topics *Hashes) {
|
||||
t.topics = append(t.topics, topics.hashes)
|
||||
}
|
||||
|
||||
// FilterQuery contains options for contract log filtering.
|
||||
type FilterQuery struct {
|
||||
query ethereum.FilterQuery
|
||||
}
|
||||
|
||||
// NewFilterQuery creates an empty filter query for contract log filtering.
|
||||
func NewFilterQuery() *FilterQuery {
|
||||
return new(FilterQuery)
|
||||
}
|
||||
|
||||
func (fq *FilterQuery) GetFromBlock() *BigInt { return &BigInt{fq.query.FromBlock} }
|
||||
func (fq *FilterQuery) GetToBlock() *BigInt { return &BigInt{fq.query.ToBlock} }
|
||||
func (fq *FilterQuery) GetAddresses() *Addresses { return &Addresses{fq.query.Addresses} }
|
||||
func (fq *FilterQuery) GetTopics() *Topics { return &Topics{fq.query.Topics} }
|
||||
|
||||
func (fq *FilterQuery) SetFromBlock(fromBlock *BigInt) { fq.query.FromBlock = fromBlock.bigint }
|
||||
func (fq *FilterQuery) SetToBlock(toBlock *BigInt) { fq.query.ToBlock = toBlock.bigint }
|
||||
func (fq *FilterQuery) SetAddresses(addresses *Addresses) { fq.query.Addresses = addresses.addresses }
|
||||
func (fq *FilterQuery) SetTopics(topics *Topics) { fq.query.Topics = topics.topics }
|
253
mobile/geth.go
253
mobile/geth.go
@ -1,253 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains all the wrappers from the node package to support client side node
|
||||
// management on mobile platforms.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/eth/downloader"
|
||||
"github.com/ethereum/go-ethereum/eth/ethconfig"
|
||||
"github.com/ethereum/go-ethereum/eth/filters"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/ethstats"
|
||||
"github.com/ethereum/go-ethereum/internal/debug"
|
||||
"github.com/ethereum/go-ethereum/les"
|
||||
"github.com/ethereum/go-ethereum/node"
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rpc"
|
||||
)
|
||||
|
||||
// NodeConfig represents the collection of configuration values to fine tune the Geth
|
||||
// node embedded into a mobile process. The available values are a subset of the
|
||||
// entire API provided by go-ethereum to reduce the maintenance surface and dev
|
||||
// complexity.
|
||||
type NodeConfig struct {
|
||||
// Bootstrap nodes used to establish connectivity with the rest of the network.
|
||||
BootstrapNodes *Enodes
|
||||
|
||||
// MaxPeers is the maximum number of peers that can be connected. If this is
|
||||
// set to zero, then only the configured static and trusted peers can connect.
|
||||
MaxPeers int
|
||||
|
||||
// EthereumEnabled specifies whether the node should run the Ethereum protocol.
|
||||
EthereumEnabled bool
|
||||
|
||||
// EthereumNetworkID is the network identifier used by the Ethereum protocol to
|
||||
// decide if remote peers should be accepted or not.
|
||||
EthereumNetworkID int64 // uint64 in truth, but Java can't handle that...
|
||||
|
||||
// EthereumGenesis is the genesis JSON to use to seed the blockchain with. An
|
||||
// empty genesis state is equivalent to using the mainnet's state.
|
||||
EthereumGenesis string
|
||||
|
||||
// EthereumDatabaseCache is the system memory in MB to allocate for database caching.
|
||||
// A minimum of 16MB is always reserved.
|
||||
EthereumDatabaseCache int
|
||||
|
||||
// EthereumNetStats is a netstats connection string to use to report various
|
||||
// chain, transaction and node stats to a monitoring server.
|
||||
//
|
||||
// It has the form "nodename:secret@host:port"
|
||||
EthereumNetStats string
|
||||
|
||||
// Listening address of pprof server.
|
||||
PprofAddress string
|
||||
}
|
||||
|
||||
// defaultNodeConfig contains the default node configuration values to use if all
|
||||
// or some fields are missing from the user's specified list.
|
||||
var defaultNodeConfig = &NodeConfig{
|
||||
BootstrapNodes: FoundationBootnodes(),
|
||||
MaxPeers: 25,
|
||||
EthereumEnabled: true,
|
||||
EthereumNetworkID: 1,
|
||||
EthereumDatabaseCache: 16,
|
||||
}
|
||||
|
||||
// NewNodeConfig creates a new node option set, initialized to the default values.
|
||||
func NewNodeConfig() *NodeConfig {
|
||||
config := *defaultNodeConfig
|
||||
return &config
|
||||
}
|
||||
|
||||
// AddBootstrapNode adds an additional bootstrap node to the node config.
|
||||
func (conf *NodeConfig) AddBootstrapNode(node *Enode) {
|
||||
conf.BootstrapNodes.Append(node)
|
||||
}
|
||||
|
||||
// EncodeJSON encodes a NodeConfig into a JSON data dump.
|
||||
func (conf *NodeConfig) EncodeJSON() (string, error) {
|
||||
data, err := json.Marshal(conf)
|
||||
return string(data), err
|
||||
}
|
||||
|
||||
// String returns a printable representation of the node config.
|
||||
func (conf *NodeConfig) String() string {
|
||||
return encodeOrError(conf)
|
||||
}
|
||||
|
||||
// Node represents a Geth Ethereum node instance.
|
||||
type Node struct {
|
||||
node *node.Node
|
||||
}
|
||||
|
||||
// NewNode creates and configures a new Geth node.
|
||||
func NewNode(datadir string, config *NodeConfig) (stack *Node, _ error) {
|
||||
// If no or partial configurations were specified, use defaults
|
||||
if config == nil {
|
||||
config = NewNodeConfig()
|
||||
}
|
||||
if config.MaxPeers == 0 {
|
||||
config.MaxPeers = defaultNodeConfig.MaxPeers
|
||||
}
|
||||
if config.BootstrapNodes == nil || config.BootstrapNodes.Size() == 0 {
|
||||
config.BootstrapNodes = defaultNodeConfig.BootstrapNodes
|
||||
}
|
||||
|
||||
if config.PprofAddress != "" {
|
||||
debug.StartPProf(config.PprofAddress, true)
|
||||
}
|
||||
|
||||
// Create the empty networking stack
|
||||
nodeConf := &node.Config{
|
||||
Name: clientIdentifier,
|
||||
Version: params.VersionWithMeta,
|
||||
DataDir: datadir,
|
||||
KeyStoreDir: filepath.Join(datadir, "keystore"), // Mobile should never use internal keystores!
|
||||
P2P: p2p.Config{
|
||||
NoDiscovery: true,
|
||||
DiscoveryV5: true,
|
||||
BootstrapNodesV5: config.BootstrapNodes.nodes,
|
||||
ListenAddr: ":0",
|
||||
NAT: nat.Any(),
|
||||
MaxPeers: config.MaxPeers,
|
||||
},
|
||||
}
|
||||
|
||||
rawStack, err := node.New(nodeConf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
debug.Memsize.Add("node", rawStack)
|
||||
|
||||
var genesis *core.Genesis
|
||||
if config.EthereumGenesis != "" {
|
||||
// Parse the user supplied genesis spec if not mainnet
|
||||
genesis = new(core.Genesis)
|
||||
if err := json.Unmarshal([]byte(config.EthereumGenesis), genesis); err != nil {
|
||||
rawStack.Close()
|
||||
return nil, fmt.Errorf("invalid genesis spec: %v", err)
|
||||
}
|
||||
// If we have the Ropsten testnet, hard code the chain configs too
|
||||
if config.EthereumGenesis == RopstenGenesis() {
|
||||
genesis.Config = params.RopstenChainConfig
|
||||
if config.EthereumNetworkID == 1 {
|
||||
config.EthereumNetworkID = 3
|
||||
}
|
||||
}
|
||||
// If we have the Sepolia testnet, hard code the chain configs too
|
||||
if config.EthereumGenesis == SepoliaGenesis() {
|
||||
genesis.Config = params.SepoliaChainConfig
|
||||
if config.EthereumNetworkID == 1 {
|
||||
config.EthereumNetworkID = 11155111
|
||||
}
|
||||
}
|
||||
// If we have the Rinkeby testnet, hard code the chain configs too
|
||||
if config.EthereumGenesis == RinkebyGenesis() {
|
||||
genesis.Config = params.RinkebyChainConfig
|
||||
if config.EthereumNetworkID == 1 {
|
||||
config.EthereumNetworkID = 4
|
||||
}
|
||||
}
|
||||
// If we have the Goerli testnet, hard code the chain configs too
|
||||
if config.EthereumGenesis == GoerliGenesis() {
|
||||
genesis.Config = params.GoerliChainConfig
|
||||
if config.EthereumNetworkID == 1 {
|
||||
config.EthereumNetworkID = 5
|
||||
}
|
||||
}
|
||||
}
|
||||
// Register the Ethereum protocol if requested
|
||||
if config.EthereumEnabled {
|
||||
ethConf := ethconfig.Defaults
|
||||
ethConf.Genesis = genesis
|
||||
ethConf.SyncMode = downloader.LightSync
|
||||
ethConf.NetworkId = uint64(config.EthereumNetworkID)
|
||||
ethConf.DatabaseCache = config.EthereumDatabaseCache
|
||||
lesBackend, err := les.New(rawStack, ðConf)
|
||||
if err != nil {
|
||||
rawStack.Close()
|
||||
return nil, fmt.Errorf("ethereum init: %v", err)
|
||||
}
|
||||
// Register log filter RPC API.
|
||||
filterSystem := filters.NewFilterSystem(lesBackend.ApiBackend, filters.Config{
|
||||
LogCacheSize: ethConf.FilterLogCacheSize,
|
||||
})
|
||||
rawStack.RegisterAPIs([]rpc.API{{
|
||||
Namespace: "eth",
|
||||
Service: filters.NewFilterAPI(filterSystem, true),
|
||||
}})
|
||||
// If netstats reporting is requested, do it
|
||||
if config.EthereumNetStats != "" {
|
||||
if err := ethstats.New(rawStack, lesBackend.ApiBackend, lesBackend.Engine(), config.EthereumNetStats); err != nil {
|
||||
rawStack.Close()
|
||||
return nil, fmt.Errorf("netstats init: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return &Node{rawStack}, nil
|
||||
}
|
||||
|
||||
// Close terminates a running node along with all it's services, tearing internal state
|
||||
// down. It is not possible to restart a closed node.
|
||||
func (n *Node) Close() error {
|
||||
return n.node.Close()
|
||||
}
|
||||
|
||||
// Start creates a live P2P node and starts running it.
|
||||
func (n *Node) Start() error {
|
||||
// TODO: recreate the node so it can be started multiple times
|
||||
return n.node.Start()
|
||||
}
|
||||
|
||||
// GetEthereumClient retrieves a client to access the Ethereum subsystem.
|
||||
func (n *Node) GetEthereumClient() (client *EthereumClient, _ error) {
|
||||
rpc, err := n.node.Attach()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &EthereumClient{ethclient.NewClient(rpc)}, nil
|
||||
}
|
||||
|
||||
// GetNodeInfo gathers and returns a collection of metadata known about the host.
|
||||
func (n *Node) GetNodeInfo() *NodeInfo {
|
||||
return &NodeInfo{n.node.Server().NodeInfo()}
|
||||
}
|
||||
|
||||
// GetPeersInfo returns an array of metadata objects describing connected peers.
|
||||
func (n *Node) GetPeersInfo() *PeerInfos {
|
||||
return &PeerInfos{n.node.Server().PeersInfo()}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
//go:build android
|
||||
// +build android
|
||||
|
||||
package geth
|
||||
|
||||
// clientIdentifier is a hard coded identifier to report into the network.
|
||||
var clientIdentifier = "GethDroid"
|
@ -1,23 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
//go:build ios
|
||||
// +build ios
|
||||
|
||||
package geth
|
||||
|
||||
// clientIdentifier is a hard coded identifier to report into the network.
|
||||
var clientIdentifier = "iGeth"
|
@ -1,23 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
//go:build !android && !ios
|
||||
// +build !android,!ios
|
||||
|
||||
package geth
|
||||
|
||||
// clientIdentifier is a hard coded identifier to report into the network.
|
||||
var clientIdentifier = "GethMobile"
|
@ -1,34 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains initialization code for the mobile library.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Initialize the logger
|
||||
log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(false))))
|
||||
|
||||
// Initialize the goroutine count
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
}
|
@ -1,276 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains perverted wrappers to allow crossing over empty interfaces.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// Interface represents a wrapped version of Go's interface{}, with the capacity
|
||||
// to store arbitrary data types.
|
||||
//
|
||||
// Since it's impossible to get the arbitrary-ness converted between Go and mobile
|
||||
// platforms, we're using explicit getters and setters for the conversions. There
|
||||
// is of course no point in enumerating everything, just enough to support the
|
||||
// contract bindings requiring client side generated code.
|
||||
type Interface struct {
|
||||
object interface{}
|
||||
}
|
||||
|
||||
// NewInterface creates a new empty interface that can be used to pass around
|
||||
// generic types.
|
||||
func NewInterface() *Interface {
|
||||
return new(Interface)
|
||||
}
|
||||
|
||||
func (i *Interface) SetBool(b bool) { i.object = &b }
|
||||
func (i *Interface) SetBools(bs *Bools) { i.object = &bs.bools }
|
||||
func (i *Interface) SetString(str string) { i.object = &str }
|
||||
func (i *Interface) SetStrings(strs *Strings) { i.object = &strs.strs }
|
||||
func (i *Interface) SetBinary(binary []byte) { b := common.CopyBytes(binary); i.object = &b }
|
||||
func (i *Interface) SetBinaries(binaries *Binaries) { i.object = &binaries.binaries }
|
||||
func (i *Interface) SetAddress(address *Address) { i.object = &address.address }
|
||||
func (i *Interface) SetAddresses(addrs *Addresses) { i.object = &addrs.addresses }
|
||||
func (i *Interface) SetHash(hash *Hash) { i.object = &hash.hash }
|
||||
func (i *Interface) SetHashes(hashes *Hashes) { i.object = &hashes.hashes }
|
||||
func (i *Interface) SetInt8(n int8) { i.object = &n }
|
||||
func (i *Interface) SetInt16(n int16) { i.object = &n }
|
||||
func (i *Interface) SetInt32(n int32) { i.object = &n }
|
||||
func (i *Interface) SetInt64(n int64) { i.object = &n }
|
||||
func (i *Interface) SetInt8s(bigints *BigInts) {
|
||||
ints := make([]int8, 0, bigints.Size())
|
||||
for _, bi := range bigints.bigints {
|
||||
ints = append(ints, int8(bi.Int64()))
|
||||
}
|
||||
i.object = &ints
|
||||
}
|
||||
func (i *Interface) SetInt16s(bigints *BigInts) {
|
||||
ints := make([]int16, 0, bigints.Size())
|
||||
for _, bi := range bigints.bigints {
|
||||
ints = append(ints, int16(bi.Int64()))
|
||||
}
|
||||
i.object = &ints
|
||||
}
|
||||
func (i *Interface) SetInt32s(bigints *BigInts) {
|
||||
ints := make([]int32, 0, bigints.Size())
|
||||
for _, bi := range bigints.bigints {
|
||||
ints = append(ints, int32(bi.Int64()))
|
||||
}
|
||||
i.object = &ints
|
||||
}
|
||||
func (i *Interface) SetInt64s(bigints *BigInts) {
|
||||
ints := make([]int64, 0, bigints.Size())
|
||||
for _, bi := range bigints.bigints {
|
||||
ints = append(ints, bi.Int64())
|
||||
}
|
||||
i.object = &ints
|
||||
}
|
||||
func (i *Interface) SetUint8(bigint *BigInt) { n := uint8(bigint.bigint.Uint64()); i.object = &n }
|
||||
func (i *Interface) SetUint16(bigint *BigInt) { n := uint16(bigint.bigint.Uint64()); i.object = &n }
|
||||
func (i *Interface) SetUint32(bigint *BigInt) { n := uint32(bigint.bigint.Uint64()); i.object = &n }
|
||||
func (i *Interface) SetUint64(bigint *BigInt) { n := bigint.bigint.Uint64(); i.object = &n }
|
||||
func (i *Interface) SetUint8s(bigints *BigInts) {
|
||||
ints := make([]uint8, 0, bigints.Size())
|
||||
for _, bi := range bigints.bigints {
|
||||
ints = append(ints, uint8(bi.Uint64()))
|
||||
}
|
||||
i.object = &ints
|
||||
}
|
||||
func (i *Interface) SetUint16s(bigints *BigInts) {
|
||||
ints := make([]uint16, 0, bigints.Size())
|
||||
for _, bi := range bigints.bigints {
|
||||
ints = append(ints, uint16(bi.Uint64()))
|
||||
}
|
||||
i.object = &ints
|
||||
}
|
||||
func (i *Interface) SetUint32s(bigints *BigInts) {
|
||||
ints := make([]uint32, 0, bigints.Size())
|
||||
for _, bi := range bigints.bigints {
|
||||
ints = append(ints, uint32(bi.Uint64()))
|
||||
}
|
||||
i.object = &ints
|
||||
}
|
||||
func (i *Interface) SetUint64s(bigints *BigInts) {
|
||||
ints := make([]uint64, 0, bigints.Size())
|
||||
for _, bi := range bigints.bigints {
|
||||
ints = append(ints, bi.Uint64())
|
||||
}
|
||||
i.object = &ints
|
||||
}
|
||||
func (i *Interface) SetBigInt(bigint *BigInt) { i.object = &bigint.bigint }
|
||||
func (i *Interface) SetBigInts(bigints *BigInts) { i.object = &bigints.bigints }
|
||||
|
||||
func (i *Interface) SetDefaultBool() { i.object = new(bool) }
|
||||
func (i *Interface) SetDefaultBools() { i.object = new([]bool) }
|
||||
func (i *Interface) SetDefaultString() { i.object = new(string) }
|
||||
func (i *Interface) SetDefaultStrings() { i.object = new([]string) }
|
||||
func (i *Interface) SetDefaultBinary() { i.object = new([]byte) }
|
||||
func (i *Interface) SetDefaultBinaries() { i.object = new([][]byte) }
|
||||
func (i *Interface) SetDefaultAddress() { i.object = new(common.Address) }
|
||||
func (i *Interface) SetDefaultAddresses() { i.object = new([]common.Address) }
|
||||
func (i *Interface) SetDefaultHash() { i.object = new(common.Hash) }
|
||||
func (i *Interface) SetDefaultHashes() { i.object = new([]common.Hash) }
|
||||
func (i *Interface) SetDefaultInt8() { i.object = new(int8) }
|
||||
func (i *Interface) SetDefaultInt8s() { i.object = new([]int8) }
|
||||
func (i *Interface) SetDefaultInt16() { i.object = new(int16) }
|
||||
func (i *Interface) SetDefaultInt16s() { i.object = new([]int16) }
|
||||
func (i *Interface) SetDefaultInt32() { i.object = new(int32) }
|
||||
func (i *Interface) SetDefaultInt32s() { i.object = new([]int32) }
|
||||
func (i *Interface) SetDefaultInt64() { i.object = new(int64) }
|
||||
func (i *Interface) SetDefaultInt64s() { i.object = new([]int64) }
|
||||
func (i *Interface) SetDefaultUint8() { i.object = new(uint8) }
|
||||
func (i *Interface) SetDefaultUint8s() { i.object = new([]uint8) }
|
||||
func (i *Interface) SetDefaultUint16() { i.object = new(uint16) }
|
||||
func (i *Interface) SetDefaultUint16s() { i.object = new([]uint16) }
|
||||
func (i *Interface) SetDefaultUint32() { i.object = new(uint32) }
|
||||
func (i *Interface) SetDefaultUint32s() { i.object = new([]uint32) }
|
||||
func (i *Interface) SetDefaultUint64() { i.object = new(uint64) }
|
||||
func (i *Interface) SetDefaultUint64s() { i.object = new([]uint64) }
|
||||
func (i *Interface) SetDefaultBigInt() { i.object = new(*big.Int) }
|
||||
func (i *Interface) SetDefaultBigInts() { i.object = new([]*big.Int) }
|
||||
|
||||
func (i *Interface) GetBool() bool { return *i.object.(*bool) }
|
||||
func (i *Interface) GetBools() *Bools { return &Bools{*i.object.(*[]bool)} }
|
||||
func (i *Interface) GetString() string { return *i.object.(*string) }
|
||||
func (i *Interface) GetStrings() *Strings { return &Strings{*i.object.(*[]string)} }
|
||||
func (i *Interface) GetBinary() []byte { return *i.object.(*[]byte) }
|
||||
func (i *Interface) GetBinaries() *Binaries { return &Binaries{*i.object.(*[][]byte)} }
|
||||
func (i *Interface) GetAddress() *Address { return &Address{*i.object.(*common.Address)} }
|
||||
func (i *Interface) GetAddresses() *Addresses { return &Addresses{*i.object.(*[]common.Address)} }
|
||||
func (i *Interface) GetHash() *Hash { return &Hash{*i.object.(*common.Hash)} }
|
||||
func (i *Interface) GetHashes() *Hashes { return &Hashes{*i.object.(*[]common.Hash)} }
|
||||
func (i *Interface) GetInt8() int8 { return *i.object.(*int8) }
|
||||
func (i *Interface) GetInt16() int16 { return *i.object.(*int16) }
|
||||
func (i *Interface) GetInt32() int32 { return *i.object.(*int32) }
|
||||
func (i *Interface) GetInt64() int64 { return *i.object.(*int64) }
|
||||
func (i *Interface) GetInt8s() *BigInts {
|
||||
val := i.object.(*[]int8)
|
||||
bigints := NewBigInts(len(*val))
|
||||
for i, v := range *val {
|
||||
bigints.Set(i, &BigInt{new(big.Int).SetInt64(int64(v))})
|
||||
}
|
||||
return bigints
|
||||
}
|
||||
func (i *Interface) GetInt16s() *BigInts {
|
||||
val := i.object.(*[]int16)
|
||||
bigints := NewBigInts(len(*val))
|
||||
for i, v := range *val {
|
||||
bigints.Set(i, &BigInt{new(big.Int).SetInt64(int64(v))})
|
||||
}
|
||||
return bigints
|
||||
}
|
||||
func (i *Interface) GetInt32s() *BigInts {
|
||||
val := i.object.(*[]int32)
|
||||
bigints := NewBigInts(len(*val))
|
||||
for i, v := range *val {
|
||||
bigints.Set(i, &BigInt{new(big.Int).SetInt64(int64(v))})
|
||||
}
|
||||
return bigints
|
||||
}
|
||||
func (i *Interface) GetInt64s() *BigInts {
|
||||
val := i.object.(*[]int64)
|
||||
bigints := NewBigInts(len(*val))
|
||||
for i, v := range *val {
|
||||
bigints.Set(i, &BigInt{new(big.Int).SetInt64(v)})
|
||||
}
|
||||
return bigints
|
||||
}
|
||||
func (i *Interface) GetUint8() *BigInt {
|
||||
return &BigInt{new(big.Int).SetUint64(uint64(*i.object.(*uint8)))}
|
||||
}
|
||||
func (i *Interface) GetUint16() *BigInt {
|
||||
return &BigInt{new(big.Int).SetUint64(uint64(*i.object.(*uint16)))}
|
||||
}
|
||||
func (i *Interface) GetUint32() *BigInt {
|
||||
return &BigInt{new(big.Int).SetUint64(uint64(*i.object.(*uint32)))}
|
||||
}
|
||||
func (i *Interface) GetUint64() *BigInt {
|
||||
return &BigInt{new(big.Int).SetUint64(*i.object.(*uint64))}
|
||||
}
|
||||
func (i *Interface) GetUint8s() *BigInts {
|
||||
val := i.object.(*[]uint8)
|
||||
bigints := NewBigInts(len(*val))
|
||||
for i, v := range *val {
|
||||
bigints.Set(i, &BigInt{new(big.Int).SetUint64(uint64(v))})
|
||||
}
|
||||
return bigints
|
||||
}
|
||||
func (i *Interface) GetUint16s() *BigInts {
|
||||
val := i.object.(*[]uint16)
|
||||
bigints := NewBigInts(len(*val))
|
||||
for i, v := range *val {
|
||||
bigints.Set(i, &BigInt{new(big.Int).SetUint64(uint64(v))})
|
||||
}
|
||||
return bigints
|
||||
}
|
||||
func (i *Interface) GetUint32s() *BigInts {
|
||||
val := i.object.(*[]uint32)
|
||||
bigints := NewBigInts(len(*val))
|
||||
for i, v := range *val {
|
||||
bigints.Set(i, &BigInt{new(big.Int).SetUint64(uint64(v))})
|
||||
}
|
||||
return bigints
|
||||
}
|
||||
func (i *Interface) GetUint64s() *BigInts {
|
||||
val := i.object.(*[]uint64)
|
||||
bigints := NewBigInts(len(*val))
|
||||
for i, v := range *val {
|
||||
bigints.Set(i, &BigInt{new(big.Int).SetUint64(v)})
|
||||
}
|
||||
return bigints
|
||||
}
|
||||
func (i *Interface) GetBigInt() *BigInt { return &BigInt{*i.object.(**big.Int)} }
|
||||
func (i *Interface) GetBigInts() *BigInts { return &BigInts{*i.object.(*[]*big.Int)} }
|
||||
|
||||
// Interfaces is a slices of wrapped generic objects.
|
||||
type Interfaces struct {
|
||||
objects []interface{}
|
||||
}
|
||||
|
||||
// NewInterfaces creates a slice of uninitialized interfaces.
|
||||
func NewInterfaces(size int) *Interfaces {
|
||||
return &Interfaces{objects: make([]interface{}, size)}
|
||||
}
|
||||
|
||||
// Size returns the number of interfaces in the slice.
|
||||
func (i *Interfaces) Size() int {
|
||||
return len(i.objects)
|
||||
}
|
||||
|
||||
// Get returns the bigint at the given index from the slice.
|
||||
// Notably the returned value can be changed without affecting the
|
||||
// interfaces itself.
|
||||
func (i *Interfaces) Get(index int) (iface *Interface, _ error) {
|
||||
if index < 0 || index >= len(i.objects) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return &Interface{object: i.objects[index]}, nil
|
||||
}
|
||||
|
||||
// Set sets the big int at the given index in the slice.
|
||||
func (i *Interfaces) Set(index int, object *Interface) error {
|
||||
if index < 0 || index >= len(i.objects) {
|
||||
return errors.New("index out of bounds")
|
||||
}
|
||||
i.objects[index] = object.object
|
||||
return nil
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
// Copyright 2019 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 geth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
func TestInterfaceGetSet(t *testing.T) {
|
||||
var tests = []struct {
|
||||
method string
|
||||
input interface{}
|
||||
expect interface{}
|
||||
}{
|
||||
{"Bool", true, true},
|
||||
{"Bool", false, false},
|
||||
{"Bools", &Bools{[]bool{false, true}}, &Bools{[]bool{false, true}}},
|
||||
{"String", "go-ethereum", "go-ethereum"},
|
||||
{"Strings", &Strings{strs: []string{"hello", "world"}}, &Strings{strs: []string{"hello", "world"}}},
|
||||
{"Binary", []byte{0x01, 0x02}, []byte{0x01, 0x02}},
|
||||
{"Binaries", &Binaries{[][]byte{{0x01, 0x02}, {0x03, 0x04}}}, &Binaries{[][]byte{{0x01, 0x02}, {0x03, 0x04}}}},
|
||||
{"Address", &Address{common.HexToAddress("deadbeef")}, &Address{common.HexToAddress("deadbeef")}},
|
||||
{"Addresses", &Addresses{[]common.Address{common.HexToAddress("deadbeef"), common.HexToAddress("cafebabe")}}, &Addresses{[]common.Address{common.HexToAddress("deadbeef"), common.HexToAddress("cafebabe")}}},
|
||||
{"Hash", &Hash{common.HexToHash("deadbeef")}, &Hash{common.HexToHash("deadbeef")}},
|
||||
{"Hashes", &Hashes{[]common.Hash{common.HexToHash("deadbeef"), common.HexToHash("cafebabe")}}, &Hashes{[]common.Hash{common.HexToHash("deadbeef"), common.HexToHash("cafebabe")}}},
|
||||
{"Int8", int8(1), int8(1)},
|
||||
{"Int16", int16(1), int16(1)},
|
||||
{"Int32", int32(1), int32(1)},
|
||||
{"Int64", int64(1), int64(1)},
|
||||
{"Int8s", &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}, &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}},
|
||||
{"Int16s", &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}, &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}},
|
||||
{"Int32s", &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}, &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}},
|
||||
{"Int64s", &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}, &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}},
|
||||
{"Uint8", NewBigInt(1), NewBigInt(1)},
|
||||
{"Uint16", NewBigInt(1), NewBigInt(1)},
|
||||
{"Uint32", NewBigInt(1), NewBigInt(1)},
|
||||
{"Uint64", NewBigInt(1), NewBigInt(1)},
|
||||
{"Uint8s", &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}, &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}},
|
||||
{"Uint16s", &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}, &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}},
|
||||
{"Uint32s", &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}, &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}},
|
||||
{"Uint64s", &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}, &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}},
|
||||
{"BigInt", NewBigInt(1), NewBigInt(1)},
|
||||
{"BigInts", &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}, &BigInts{[]*big.Int{big.NewInt(1), big.NewInt(2)}}},
|
||||
}
|
||||
|
||||
args := NewInterfaces(len(tests))
|
||||
|
||||
callFn := func(receiver interface{}, method string, arg interface{}) interface{} {
|
||||
rval := reflect.ValueOf(receiver)
|
||||
rval.MethodByName(fmt.Sprintf("Set%s", method)).Call([]reflect.Value{reflect.ValueOf(arg)})
|
||||
res := rval.MethodByName(fmt.Sprintf("Get%s", method)).Call(nil)
|
||||
if len(res) > 0 {
|
||||
return res[0].Interface()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
for index, c := range tests {
|
||||
// In theory the change of iface shouldn't effect the args value
|
||||
iface, _ := args.Get(index)
|
||||
result := callFn(iface, c.method, c.input)
|
||||
if !reflect.DeepEqual(result, c.expect) {
|
||||
t.Errorf("Interface get/set mismatch, want %v, got %v", c.expect, result)
|
||||
}
|
||||
// Check whether the underlying value in args is still zero
|
||||
iface, _ = args.Get(index)
|
||||
if iface.object != nil {
|
||||
t.Error("Get operation is not write safe")
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
// 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 geth
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
)
|
||||
|
||||
// SetVerbosity sets the global verbosity level (between 0 and 6 - see logger/verbosity.go).
|
||||
func SetVerbosity(level int) {
|
||||
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(level), log.StreamHandler(os.Stderr, log.TerminalFormat(false))))
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains wrappers for the p2p package.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/p2p"
|
||||
)
|
||||
|
||||
// NodeInfo represents pi short summary of the information known about the host.
|
||||
type NodeInfo struct {
|
||||
info *p2p.NodeInfo
|
||||
}
|
||||
|
||||
func (ni *NodeInfo) GetID() string { return ni.info.ID }
|
||||
func (ni *NodeInfo) GetName() string { return ni.info.Name }
|
||||
func (ni *NodeInfo) GetEnode() string { return ni.info.Enode }
|
||||
func (ni *NodeInfo) GetIP() string { return ni.info.IP }
|
||||
func (ni *NodeInfo) GetDiscoveryPort() int { return ni.info.Ports.Discovery }
|
||||
func (ni *NodeInfo) GetListenerPort() int { return ni.info.Ports.Listener }
|
||||
func (ni *NodeInfo) GetListenerAddress() string { return ni.info.ListenAddr }
|
||||
func (ni *NodeInfo) GetProtocols() *Strings {
|
||||
protos := []string{}
|
||||
for proto := range ni.info.Protocols {
|
||||
protos = append(protos, proto)
|
||||
}
|
||||
return &Strings{protos}
|
||||
}
|
||||
|
||||
// PeerInfo represents pi short summary of the information known about pi connected peer.
|
||||
type PeerInfo struct {
|
||||
info *p2p.PeerInfo
|
||||
}
|
||||
|
||||
func (pi *PeerInfo) GetID() string { return pi.info.ID }
|
||||
func (pi *PeerInfo) GetName() string { return pi.info.Name }
|
||||
func (pi *PeerInfo) GetCaps() *Strings { return &Strings{pi.info.Caps} }
|
||||
func (pi *PeerInfo) GetLocalAddress() string { return pi.info.Network.LocalAddress }
|
||||
func (pi *PeerInfo) GetRemoteAddress() string { return pi.info.Network.RemoteAddress }
|
||||
|
||||
// PeerInfos represents a slice of infos about remote peers.
|
||||
type PeerInfos struct {
|
||||
infos []*p2p.PeerInfo
|
||||
}
|
||||
|
||||
// Size returns the number of peer info entries in the slice.
|
||||
func (pi *PeerInfos) Size() int {
|
||||
return len(pi.infos)
|
||||
}
|
||||
|
||||
// Get returns the peer info at the given index from the slice.
|
||||
func (pi *PeerInfos) Get(index int) (info *PeerInfo, _ error) {
|
||||
if index < 0 || index >= len(pi.infos) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return &PeerInfo{pi.infos[index]}, nil
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains all the wrappers from the params package.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
// MainnetGenesis returns the JSON spec to use for the main Ethereum network. It
|
||||
// is actually empty since that defaults to the hard coded binary genesis block.
|
||||
func MainnetGenesis() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// RopstenGenesis returns the JSON spec to use for the Ropsten test network.
|
||||
func RopstenGenesis() string {
|
||||
enc, err := json.Marshal(core.DefaultRopstenGenesisBlock())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(enc)
|
||||
}
|
||||
|
||||
// SepoliaGenesis returns the JSON spec to use for the Sepolia test network.
|
||||
func SepoliaGenesis() string {
|
||||
enc, err := json.Marshal(core.DefaultSepoliaGenesisBlock())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(enc)
|
||||
}
|
||||
|
||||
// RinkebyGenesis returns the JSON spec to use for the Rinkeby test network
|
||||
func RinkebyGenesis() string {
|
||||
enc, err := json.Marshal(core.DefaultRinkebyGenesisBlock())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(enc)
|
||||
}
|
||||
|
||||
// GoerliGenesis returns the JSON spec to use for the Goerli test network
|
||||
func GoerliGenesis() string {
|
||||
enc, err := json.Marshal(core.DefaultGoerliGenesisBlock())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(enc)
|
||||
}
|
||||
|
||||
// FoundationBootnodes returns the enode URLs of the P2P bootstrap nodes operated
|
||||
// by the foundation running the V5 discovery protocol.
|
||||
func FoundationBootnodes() *Enodes {
|
||||
nodes := &Enodes{nodes: make([]*enode.Node, len(params.MainnetBootnodes))}
|
||||
for i, url := range params.MainnetBootnodes {
|
||||
var err error
|
||||
nodes.nodes[i], err = enode.Parse(enode.ValidSchemes, url)
|
||||
if err != nil {
|
||||
panic("invalid node URL: " + err.Error())
|
||||
}
|
||||
}
|
||||
return nodes
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains various wrappers for primitive types.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
// Strings represents s slice of strs.
|
||||
type Strings struct{ strs []string }
|
||||
|
||||
// Size returns the number of strs in the slice.
|
||||
func (s *Strings) Size() int {
|
||||
return len(s.strs)
|
||||
}
|
||||
|
||||
// Get returns the string at the given index from the slice.
|
||||
func (s *Strings) Get(index int) (str string, _ error) {
|
||||
if index < 0 || index >= len(s.strs) {
|
||||
return "", errors.New("index out of bounds")
|
||||
}
|
||||
return s.strs[index], nil
|
||||
}
|
||||
|
||||
// Set sets the string at the given index in the slice.
|
||||
func (s *Strings) Set(index int, str string) error {
|
||||
if index < 0 || index >= len(s.strs) {
|
||||
return errors.New("index out of bounds")
|
||||
}
|
||||
s.strs[index] = str
|
||||
return nil
|
||||
}
|
||||
|
||||
// String implements the Stringer interface.
|
||||
func (s *Strings) String() string {
|
||||
return fmt.Sprintf("%v", s.strs)
|
||||
}
|
||||
|
||||
// Bools represents a slice of bool.
|
||||
type Bools struct{ bools []bool }
|
||||
|
||||
// Size returns the number of bool in the slice.
|
||||
func (bs *Bools) Size() int {
|
||||
return len(bs.bools)
|
||||
}
|
||||
|
||||
// Get returns the bool at the given index from the slice.
|
||||
func (bs *Bools) Get(index int) (b bool, _ error) {
|
||||
if index < 0 || index >= len(bs.bools) {
|
||||
return false, errors.New("index out of bounds")
|
||||
}
|
||||
return bs.bools[index], nil
|
||||
}
|
||||
|
||||
// Set sets the bool at the given index in the slice.
|
||||
func (bs *Bools) Set(index int, b bool) error {
|
||||
if index < 0 || index >= len(bs.bools) {
|
||||
return errors.New("index out of bounds")
|
||||
}
|
||||
bs.bools[index] = b
|
||||
return nil
|
||||
}
|
||||
|
||||
// String implements the Stringer interface.
|
||||
func (bs *Bools) String() string {
|
||||
return fmt.Sprintf("%v", bs.bools)
|
||||
}
|
||||
|
||||
// Binaries represents a slice of byte slice
|
||||
type Binaries struct{ binaries [][]byte }
|
||||
|
||||
// Size returns the number of byte slice in the slice.
|
||||
func (bs *Binaries) Size() int {
|
||||
return len(bs.binaries)
|
||||
}
|
||||
|
||||
// Get returns the byte slice at the given index from the slice.
|
||||
func (bs *Binaries) Get(index int) (binary []byte, _ error) {
|
||||
if index < 0 || index >= len(bs.binaries) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return common.CopyBytes(bs.binaries[index]), nil
|
||||
}
|
||||
|
||||
// Set sets the byte slice at the given index in the slice.
|
||||
func (bs *Binaries) Set(index int, binary []byte) error {
|
||||
if index < 0 || index >= len(bs.binaries) {
|
||||
return errors.New("index out of bounds")
|
||||
}
|
||||
bs.binaries[index] = common.CopyBytes(binary)
|
||||
return nil
|
||||
}
|
||||
|
||||
// String implements the Stringer interface.
|
||||
func (bs *Binaries) String() string {
|
||||
return fmt.Sprintf("%v", bs.binaries)
|
||||
}
|
377
mobile/types.go
377
mobile/types.go
@ -1,377 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains all the wrappers from the core/types package.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
type jsonEncoder interface {
|
||||
EncodeJSON() (string, error)
|
||||
}
|
||||
|
||||
// encodeOrError tries to encode the object into json.
|
||||
// If the encoding fails the resulting error is returned.
|
||||
func encodeOrError(encoder jsonEncoder) string {
|
||||
enc, err := encoder.EncodeJSON()
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
return enc
|
||||
}
|
||||
|
||||
// A Nonce is a 64-bit hash which proves (combined with the mix-hash) that
|
||||
// a sufficient amount of computation has been carried out on a block.
|
||||
type Nonce struct {
|
||||
nonce types.BlockNonce
|
||||
}
|
||||
|
||||
// GetBytes retrieves the byte representation of the block nonce.
|
||||
func (n *Nonce) GetBytes() []byte {
|
||||
return n.nonce[:]
|
||||
}
|
||||
|
||||
// GetHex retrieves the hex string representation of the block nonce.
|
||||
func (n *Nonce) GetHex() string {
|
||||
return fmt.Sprintf("%#x", n.nonce[:])
|
||||
}
|
||||
|
||||
// String returns a printable representation of the nonce.
|
||||
func (n *Nonce) String() string {
|
||||
return n.GetHex()
|
||||
}
|
||||
|
||||
// Bloom represents a 256 bit bloom filter.
|
||||
type Bloom struct {
|
||||
bloom types.Bloom
|
||||
}
|
||||
|
||||
// GetBytes retrieves the byte representation of the bloom filter.
|
||||
func (b *Bloom) GetBytes() []byte {
|
||||
return b.bloom[:]
|
||||
}
|
||||
|
||||
// GetHex retrieves the hex string representation of the bloom filter.
|
||||
func (b *Bloom) GetHex() string {
|
||||
return fmt.Sprintf("%#x", b.bloom[:])
|
||||
}
|
||||
|
||||
// String returns a printable representation of the bloom filter.
|
||||
func (b *Bloom) String() string {
|
||||
return b.GetHex()
|
||||
}
|
||||
|
||||
// Header represents a block header in the Ethereum blockchain.
|
||||
type Header struct {
|
||||
header *types.Header
|
||||
}
|
||||
|
||||
// NewHeaderFromRLP parses a header from an RLP data dump.
|
||||
func NewHeaderFromRLP(data []byte) (*Header, error) {
|
||||
h := &Header{
|
||||
header: new(types.Header),
|
||||
}
|
||||
if err := rlp.DecodeBytes(common.CopyBytes(data), h.header); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// EncodeRLP encodes a header into an RLP data dump.
|
||||
func (h *Header) EncodeRLP() ([]byte, error) {
|
||||
return rlp.EncodeToBytes(h.header)
|
||||
}
|
||||
|
||||
// NewHeaderFromJSON parses a header from a JSON data dump.
|
||||
func NewHeaderFromJSON(data string) (*Header, error) {
|
||||
h := &Header{
|
||||
header: new(types.Header),
|
||||
}
|
||||
if err := json.Unmarshal([]byte(data), h.header); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// EncodeJSON encodes a header into a JSON data dump.
|
||||
func (h *Header) EncodeJSON() (string, error) {
|
||||
data, err := json.Marshal(h.header)
|
||||
return string(data), err
|
||||
}
|
||||
|
||||
// String returns a printable representation of the header.
|
||||
func (h *Header) String() string {
|
||||
return encodeOrError(h)
|
||||
}
|
||||
|
||||
func (h *Header) GetParentHash() *Hash { return &Hash{h.header.ParentHash} }
|
||||
func (h *Header) GetUncleHash() *Hash { return &Hash{h.header.UncleHash} }
|
||||
func (h *Header) GetCoinbase() *Address { return &Address{h.header.Coinbase} }
|
||||
func (h *Header) GetRoot() *Hash { return &Hash{h.header.Root} }
|
||||
func (h *Header) GetTxHash() *Hash { return &Hash{h.header.TxHash} }
|
||||
func (h *Header) GetReceiptHash() *Hash { return &Hash{h.header.ReceiptHash} }
|
||||
func (h *Header) GetBloom() *Bloom { return &Bloom{h.header.Bloom} }
|
||||
func (h *Header) GetDifficulty() *BigInt { return &BigInt{h.header.Difficulty} }
|
||||
func (h *Header) GetNumber() int64 { return h.header.Number.Int64() }
|
||||
func (h *Header) GetGasLimit() int64 { return int64(h.header.GasLimit) }
|
||||
func (h *Header) GetGasUsed() int64 { return int64(h.header.GasUsed) }
|
||||
func (h *Header) GetTime() int64 { return int64(h.header.Time) }
|
||||
func (h *Header) GetExtra() []byte { return h.header.Extra }
|
||||
func (h *Header) GetMixDigest() *Hash { return &Hash{h.header.MixDigest} }
|
||||
func (h *Header) GetNonce() *Nonce { return &Nonce{h.header.Nonce} }
|
||||
func (h *Header) GetHash() *Hash { return &Hash{h.header.Hash()} }
|
||||
|
||||
// Headers represents a slice of headers.
|
||||
type Headers struct{ headers []*types.Header }
|
||||
|
||||
// Size returns the number of headers in the slice.
|
||||
func (h *Headers) Size() int {
|
||||
return len(h.headers)
|
||||
}
|
||||
|
||||
// Get returns the header at the given index from the slice.
|
||||
func (h *Headers) Get(index int) (header *Header, _ error) {
|
||||
if index < 0 || index >= len(h.headers) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return &Header{h.headers[index]}, nil
|
||||
}
|
||||
|
||||
// Block represents an entire block in the Ethereum blockchain.
|
||||
type Block struct {
|
||||
block *types.Block
|
||||
}
|
||||
|
||||
// NewBlockFromRLP parses a block from an RLP data dump.
|
||||
func NewBlockFromRLP(data []byte) (*Block, error) {
|
||||
b := &Block{
|
||||
block: new(types.Block),
|
||||
}
|
||||
if err := rlp.DecodeBytes(common.CopyBytes(data), b.block); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// EncodeRLP encodes a block into an RLP data dump.
|
||||
func (b *Block) EncodeRLP() ([]byte, error) {
|
||||
return rlp.EncodeToBytes(b.block)
|
||||
}
|
||||
|
||||
// NewBlockFromJSON parses a block from a JSON data dump.
|
||||
func NewBlockFromJSON(data string) (*Block, error) {
|
||||
b := &Block{
|
||||
block: new(types.Block),
|
||||
}
|
||||
if err := json.Unmarshal([]byte(data), b.block); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// EncodeJSON encodes a block into a JSON data dump.
|
||||
func (b *Block) EncodeJSON() (string, error) {
|
||||
data, err := json.Marshal(b.block)
|
||||
return string(data), err
|
||||
}
|
||||
|
||||
// String returns a printable representation of the block.
|
||||
func (b *Block) String() string {
|
||||
return encodeOrError(b)
|
||||
}
|
||||
|
||||
func (b *Block) GetParentHash() *Hash { return &Hash{b.block.ParentHash()} }
|
||||
func (b *Block) GetUncleHash() *Hash { return &Hash{b.block.UncleHash()} }
|
||||
func (b *Block) GetCoinbase() *Address { return &Address{b.block.Coinbase()} }
|
||||
func (b *Block) GetRoot() *Hash { return &Hash{b.block.Root()} }
|
||||
func (b *Block) GetTxHash() *Hash { return &Hash{b.block.TxHash()} }
|
||||
func (b *Block) GetReceiptHash() *Hash { return &Hash{b.block.ReceiptHash()} }
|
||||
func (b *Block) GetBloom() *Bloom { return &Bloom{b.block.Bloom()} }
|
||||
func (b *Block) GetDifficulty() *BigInt { return &BigInt{b.block.Difficulty()} }
|
||||
func (b *Block) GetNumber() int64 { return b.block.Number().Int64() }
|
||||
func (b *Block) GetGasLimit() int64 { return int64(b.block.GasLimit()) }
|
||||
func (b *Block) GetGasUsed() int64 { return int64(b.block.GasUsed()) }
|
||||
func (b *Block) GetTime() int64 { return int64(b.block.Time()) }
|
||||
func (b *Block) GetExtra() []byte { return b.block.Extra() }
|
||||
func (b *Block) GetMixDigest() *Hash { return &Hash{b.block.MixDigest()} }
|
||||
func (b *Block) GetNonce() int64 { return int64(b.block.Nonce()) }
|
||||
func (b *Block) GetHash() *Hash { return &Hash{b.block.Hash()} }
|
||||
func (b *Block) GetHeader() *Header { return &Header{b.block.Header()} }
|
||||
func (b *Block) GetUncles() *Headers { return &Headers{b.block.Uncles()} }
|
||||
func (b *Block) GetTransactions() *Transactions { return &Transactions{b.block.Transactions()} }
|
||||
func (b *Block) GetTransaction(hash *Hash) *Transaction {
|
||||
return &Transaction{b.block.Transaction(hash.hash)}
|
||||
}
|
||||
|
||||
// Transaction represents a single Ethereum transaction.
|
||||
type Transaction struct {
|
||||
tx *types.Transaction
|
||||
}
|
||||
|
||||
// NewContractCreation creates a new transaction for deploying a new contract with
|
||||
// the given properties.
|
||||
func NewContractCreation(nonce int64, amount *BigInt, gasLimit int64, gasPrice *BigInt, data []byte) *Transaction {
|
||||
return &Transaction{types.NewContractCreation(uint64(nonce), amount.bigint, uint64(gasLimit), gasPrice.bigint, common.CopyBytes(data))}
|
||||
}
|
||||
|
||||
// NewTransaction creates a new transaction with the given properties. Contracts
|
||||
// can be created by transacting with a nil recipient.
|
||||
func NewTransaction(nonce int64, to *Address, amount *BigInt, gasLimit int64, gasPrice *BigInt, data []byte) *Transaction {
|
||||
if to == nil {
|
||||
return &Transaction{types.NewContractCreation(uint64(nonce), amount.bigint, uint64(gasLimit), gasPrice.bigint, common.CopyBytes(data))}
|
||||
}
|
||||
return &Transaction{types.NewTransaction(uint64(nonce), to.address, amount.bigint, uint64(gasLimit), gasPrice.bigint, common.CopyBytes(data))}
|
||||
}
|
||||
|
||||
// NewTransactionFromRLP parses a transaction from an RLP data dump.
|
||||
func NewTransactionFromRLP(data []byte) (*Transaction, error) {
|
||||
tx := &Transaction{
|
||||
tx: new(types.Transaction),
|
||||
}
|
||||
if err := rlp.DecodeBytes(common.CopyBytes(data), tx.tx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// EncodeRLP encodes a transaction into an RLP data dump.
|
||||
func (tx *Transaction) EncodeRLP() ([]byte, error) {
|
||||
return rlp.EncodeToBytes(tx.tx)
|
||||
}
|
||||
|
||||
// NewTransactionFromJSON parses a transaction from a JSON data dump.
|
||||
func NewTransactionFromJSON(data string) (*Transaction, error) {
|
||||
tx := &Transaction{
|
||||
tx: new(types.Transaction),
|
||||
}
|
||||
if err := json.Unmarshal([]byte(data), tx.tx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tx, nil
|
||||
}
|
||||
|
||||
// EncodeJSON encodes a transaction into a JSON data dump.
|
||||
func (tx *Transaction) EncodeJSON() (string, error) {
|
||||
data, err := json.Marshal(tx.tx)
|
||||
return string(data), err
|
||||
}
|
||||
|
||||
// String returns a printable representation of the transaction.
|
||||
func (tx *Transaction) String() string {
|
||||
return encodeOrError(tx)
|
||||
}
|
||||
|
||||
func (tx *Transaction) GetData() []byte { return tx.tx.Data() }
|
||||
func (tx *Transaction) GetGas() int64 { return int64(tx.tx.Gas()) }
|
||||
func (tx *Transaction) GetGasPrice() *BigInt { return &BigInt{tx.tx.GasPrice()} }
|
||||
func (tx *Transaction) GetValue() *BigInt { return &BigInt{tx.tx.Value()} }
|
||||
func (tx *Transaction) GetNonce() int64 { return int64(tx.tx.Nonce()) }
|
||||
|
||||
func (tx *Transaction) GetHash() *Hash { return &Hash{tx.tx.Hash()} }
|
||||
func (tx *Transaction) GetCost() *BigInt { return &BigInt{tx.tx.Cost()} }
|
||||
|
||||
func (tx *Transaction) GetTo() *Address {
|
||||
if to := tx.tx.To(); to != nil {
|
||||
return &Address{*to}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tx *Transaction) WithSignature(sig []byte, chainID *BigInt) (signedTx *Transaction, _ error) {
|
||||
var signer types.Signer = types.HomesteadSigner{}
|
||||
if chainID != nil {
|
||||
signer = types.NewEIP155Signer(chainID.bigint)
|
||||
}
|
||||
rawTx, err := tx.tx.WithSignature(signer, common.CopyBytes(sig))
|
||||
return &Transaction{rawTx}, err
|
||||
}
|
||||
|
||||
// Transactions represents a slice of transactions.
|
||||
type Transactions struct{ txs types.Transactions }
|
||||
|
||||
// Size returns the number of transactions in the slice.
|
||||
func (txs *Transactions) Size() int {
|
||||
return len(txs.txs)
|
||||
}
|
||||
|
||||
// Get returns the transaction at the given index from the slice.
|
||||
func (txs *Transactions) Get(index int) (tx *Transaction, _ error) {
|
||||
if index < 0 || index >= len(txs.txs) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return &Transaction{txs.txs[index]}, nil
|
||||
}
|
||||
|
||||
// Receipt represents the results of a transaction.
|
||||
type Receipt struct {
|
||||
receipt *types.Receipt
|
||||
}
|
||||
|
||||
// NewReceiptFromRLP parses a transaction receipt from an RLP data dump.
|
||||
func NewReceiptFromRLP(data []byte) (*Receipt, error) {
|
||||
r := &Receipt{
|
||||
receipt: new(types.Receipt),
|
||||
}
|
||||
if err := rlp.DecodeBytes(common.CopyBytes(data), r.receipt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// EncodeRLP encodes a transaction receipt into an RLP data dump.
|
||||
func (r *Receipt) EncodeRLP() ([]byte, error) {
|
||||
return rlp.EncodeToBytes(r.receipt)
|
||||
}
|
||||
|
||||
// NewReceiptFromJSON parses a transaction receipt from a JSON data dump.
|
||||
func NewReceiptFromJSON(data string) (*Receipt, error) {
|
||||
r := &Receipt{
|
||||
receipt: new(types.Receipt),
|
||||
}
|
||||
if err := json.Unmarshal([]byte(data), r.receipt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// EncodeJSON encodes a transaction receipt into a JSON data dump.
|
||||
func (r *Receipt) EncodeJSON() (string, error) {
|
||||
data, err := json.Marshal(r.receipt)
|
||||
return string(data), err
|
||||
}
|
||||
|
||||
// String returns a printable representation of the receipt.
|
||||
func (r *Receipt) String() string {
|
||||
return encodeOrError(r)
|
||||
}
|
||||
|
||||
func (r *Receipt) GetStatus() int { return int(r.receipt.Status) }
|
||||
func (r *Receipt) GetPostState() []byte { return r.receipt.PostState }
|
||||
func (r *Receipt) GetCumulativeGasUsed() int64 { return int64(r.receipt.CumulativeGasUsed) }
|
||||
func (r *Receipt) GetBloom() *Bloom { return &Bloom{r.receipt.Bloom} }
|
||||
func (r *Receipt) GetLogs() *Logs { return &Logs{r.receipt.Logs} }
|
||||
func (r *Receipt) GetTxHash() *Hash { return &Hash{r.receipt.TxHash} }
|
||||
func (r *Receipt) GetContractAddress() *Address { return &Address{r.receipt.ContractAddress} }
|
||||
func (r *Receipt) GetGasUsed() int64 { return int64(r.receipt.GasUsed) }
|
56
mobile/vm.go
56
mobile/vm.go
@ -1,56 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
// Contains all the wrappers from the core/types package.
|
||||
|
||||
package geth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// Log represents a contract log event. These events are generated by the LOG
|
||||
// opcode and stored/indexed by the node.
|
||||
type Log struct {
|
||||
log *types.Log
|
||||
}
|
||||
|
||||
func (l *Log) GetAddress() *Address { return &Address{l.log.Address} }
|
||||
func (l *Log) GetTopics() *Hashes { return &Hashes{l.log.Topics} }
|
||||
func (l *Log) GetData() []byte { return l.log.Data }
|
||||
func (l *Log) GetBlockNumber() int64 { return int64(l.log.BlockNumber) }
|
||||
func (l *Log) GetTxHash() *Hash { return &Hash{l.log.TxHash} }
|
||||
func (l *Log) GetTxIndex() int { return int(l.log.TxIndex) }
|
||||
func (l *Log) GetBlockHash() *Hash { return &Hash{l.log.BlockHash} }
|
||||
func (l *Log) GetIndex() int { return int(l.log.Index) }
|
||||
|
||||
// Logs represents a slice of VM logs.
|
||||
type Logs struct{ logs []*types.Log }
|
||||
|
||||
// Size returns the number of logs in the slice.
|
||||
func (l *Logs) Size() int {
|
||||
return len(l.logs)
|
||||
}
|
||||
|
||||
// Get returns the log at the given index from the slice.
|
||||
func (l *Logs) Get(index int) (log *Log, _ error) {
|
||||
if index < 0 || index >= len(l.logs) {
|
||||
return nil, errors.New("index out of bounds")
|
||||
}
|
||||
return &Log{l.logs[index]}, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user