Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
586eddfd
Commit
586eddfd
authored
Apr 28, 2016
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
release, all: integrate the release service into geth
parent
d46da273
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
822 additions
and
109 deletions
+822
-109
backend.go
accounts/abi/bind/backend.go
+3
-2
main.go
cmd/geth/main.go
+37
-22
flags.go
cmd/utils/flags.go
+6
-8
api.go
eth/api.go
+16
-14
backend.go
eth/backend.go
+11
-11
bind.go
eth/bind.go
+110
-0
node.go
node/node.go
+1
-2
service.go
node/service.go
+1
-1
contract.go
release/contract.go
+432
-0
contract.sol
release/contract.sol
+52
-43
contract_test.go
release/contract_test.go
+6
-6
generator.go
release/generator.go
+0
-0
release.go
release/release.go
+147
-0
No files found.
accounts/abi/bind/backend.go
View file @
586eddfd
...
...
@@ -47,7 +47,8 @@ type ContractCaller interface {
// used when the user does not provide some needed values, but rather leaves it up
// to the transactor to decide.
type
ContractTransactor
interface
{
// Nonce retrieves the current pending nonce associated with an account.
// PendingAccountNonce retrieves the current pending nonce associated with an
// account.
PendingAccountNonce
(
account
common
.
Address
)
(
uint64
,
error
)
// SuggestGasPrice retrieves the currently suggested gas price to allow a timely
...
...
@@ -62,7 +63,7 @@ type ContractTransactor interface {
EstimateGasLimit
(
sender
common
.
Address
,
contract
*
common
.
Address
,
value
*
big
.
Int
,
data
[]
byte
)
(
*
big
.
Int
,
error
)
// SendTransaction injects the transaction into the pending pool for execution.
SendTransaction
(
*
types
.
Transaction
)
error
SendTransaction
(
tx
*
types
.
Transaction
)
error
}
// ContractBackend defines the methods needed to allow operating with contract
...
...
cmd/geth/main.go
View file @
586eddfd
...
...
@@ -18,6 +18,7 @@
package
main
import
(
"encoding/hex"
"fmt"
"io/ioutil"
"os"
...
...
@@ -41,31 +42,48 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/release"
"github.com/ethereum/go-ethereum/rlp"
)
const
(
ClientIdentifier
=
"Geth"
Version
=
"1.5.0-unstable"
VersionMajor
=
1
VersionMinor
=
5
VersionPatch
=
0
clientIdentifier
=
"Geth"
// Client identifier to advertise over the network
versionMajor
=
1
// Major version component of the current release
versionMinor
=
5
// Minor version component of the current release
versionPatch
=
0
// Patch version component of the current release
versionMeta
=
"unstable"
// Version metadata to append to the version string
versionOracle
=
"0x48a117313039b73ab02fb9f73e04a66defe123ec"
// Ethereum address of the Geth release oracle
)
var
(
gitCommit
string
// set via linker flagg
nodeNameVersion
string
app
*
cli
.
App
gitCommit
string
// Git SHA1 commit hash of the release (set via linker flags)
verString
string
// Combined textual representation of all the version components
relConfig
release
.
Config
// Structured version information and release oracle config
app
*
cli
.
App
)
func
init
()
{
if
gitCommit
==
""
{
nodeNameVersion
=
Version
}
else
{
nodeNameVersion
=
Version
+
"-"
+
gitCommit
[
:
8
]
// Construct the textual version string from the individual components
verString
=
fmt
.
Sprintf
(
"%d.%d.%d"
,
versionMajor
,
versionMinor
,
versionPatch
)
if
versionMeta
!=
""
{
verString
+=
"-"
+
versionMeta
}
if
gitCommit
!=
""
{
verString
+=
"-"
+
gitCommit
[
:
8
]
}
// Construct the version release oracle configuration
relConfig
.
Oracle
=
common
.
HexToAddress
(
versionOracle
)
app
=
utils
.
NewApp
(
Version
,
"the go-ethereum command line interface"
)
relConfig
.
Major
=
uint32
(
versionMajor
)
relConfig
.
Minor
=
uint32
(
versionMinor
)
relConfig
.
Patch
=
uint32
(
versionPatch
)
commit
,
_
:=
hex
.
DecodeString
(
gitCommit
)
copy
(
relConfig
.
Commit
[
:
],
commit
)
// Initialize the CLI app and start Geth
app
=
utils
.
NewApp
(
verString
,
"the go-ethereum command line interface"
)
app
.
Action
=
geth
app
.
HideVersion
=
true
// we have a command to print the version
app
.
Commands
=
[]
cli
.
Command
{
...
...
@@ -257,7 +275,7 @@ func makeDefaultExtra() []byte {
Name
string
GoVersion
string
Os
string
}{
uint
(
VersionMajor
<<
16
|
VersionMinor
<<
8
|
VersionPatch
),
C
lientIdentifier
,
runtime
.
Version
(),
runtime
.
GOOS
}
}{
uint
(
versionMajor
<<
16
|
versionMinor
<<
8
|
versionPatch
),
c
lientIdentifier
,
runtime
.
Version
(),
runtime
.
GOOS
}
extra
,
err
:=
rlp
.
EncodeToBytes
(
clientInfo
)
if
err
!=
nil
{
glog
.
V
(
logger
.
Warn
)
.
Infoln
(
"error setting canonical miner information:"
,
err
)
...
...
@@ -275,7 +293,7 @@ func makeDefaultExtra() []byte {
// It creates a default node based on the command line arguments and runs it in
// blocking mode, waiting for it to be shut down.
func
geth
(
ctx
*
cli
.
Context
)
{
node
:=
utils
.
MakeSystemNode
(
ClientIdentifier
,
nodeNameVersion
,
makeDefaultExtra
(),
ctx
)
node
:=
utils
.
MakeSystemNode
(
clientIdentifier
,
verString
,
relConfig
,
makeDefaultExtra
(),
ctx
)
startNode
(
ctx
,
node
)
node
.
Wait
()
}
...
...
@@ -339,7 +357,7 @@ func initGenesis(ctx *cli.Context) {
// same time.
func
console
(
ctx
*
cli
.
Context
)
{
// Create and start the node based on the CLI flags
node
:=
utils
.
MakeSystemNode
(
ClientIdentifier
,
nodeNameVersion
,
makeDefaultExtra
(),
ctx
)
node
:=
utils
.
MakeSystemNode
(
clientIdentifier
,
verString
,
relConfig
,
makeDefaultExtra
(),
ctx
)
startNode
(
ctx
,
node
)
// Attach to the newly started node, and either execute script or become interactive
...
...
@@ -372,7 +390,7 @@ func console(ctx *cli.Context) {
// of the JavaScript files specified as command arguments.
func
execScripts
(
ctx
*
cli
.
Context
)
{
// Create and start the node based on the CLI flags
node
:=
utils
.
MakeSystemNode
(
ClientIdentifier
,
nodeNameVersion
,
makeDefaultExtra
(),
ctx
)
node
:=
utils
.
MakeSystemNode
(
clientIdentifier
,
verString
,
relConfig
,
makeDefaultExtra
(),
ctx
)
startNode
(
ctx
,
node
)
defer
node
.
Stop
()
...
...
@@ -488,11 +506,8 @@ func gpubench(ctx *cli.Context) {
}
func
version
(
c
*
cli
.
Context
)
{
fmt
.
Println
(
ClientIdentifier
)
fmt
.
Println
(
"Version:"
,
Version
)
if
gitCommit
!=
""
{
fmt
.
Println
(
"Git Commit:"
,
gitCommit
)
}
fmt
.
Println
(
clientIdentifier
)
fmt
.
Println
(
"Version:"
,
version
)
fmt
.
Println
(
"Protocol Versions:"
,
eth
.
ProtocolVersions
)
fmt
.
Println
(
"Network Id:"
,
c
.
GlobalInt
(
utils
.
NetworkIdFlag
.
Name
))
fmt
.
Println
(
"Go Version:"
,
runtime
.
Version
())
...
...
cmd/utils/flags.go
View file @
586eddfd
...
...
@@ -34,7 +34,6 @@ import (
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/versions"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
...
...
@@ -49,6 +48,7 @@ import (
"github.com/ethereum/go-ethereum/p2p/nat"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/release"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/whisper"
)
...
...
@@ -642,7 +642,7 @@ func MakePasswordList(ctx *cli.Context) []string {
// MakeSystemNode sets up a local node, configures the services to launch and
// assembles the P2P protocol stack.
func
MakeSystemNode
(
name
,
version
string
,
extra
[]
byte
,
ctx
*
cli
.
Context
)
*
node
.
Node
{
func
MakeSystemNode
(
name
,
version
string
,
relconf
release
.
Config
,
extra
[]
byte
,
ctx
*
cli
.
Context
)
*
node
.
Node
{
// Avoid conflicting network flags
networks
,
netFlags
:=
0
,
[]
cli
.
BoolFlag
{
DevModeFlag
,
TestNetFlag
,
OlympicFlag
}
for
_
,
flag
:=
range
netFlags
{
...
...
@@ -773,12 +773,10 @@ func MakeSystemNode(name, version string, extra []byte, ctx *cli.Context) *node.
Fatalf
(
"Failed to register the Whisper service: %v"
,
err
)
}
}
err
=
stack
.
Register
(
func
(
ctx
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
versions
.
NewVersionCheck
(
ctx
)
})
if
err
!=
nil
{
Fatalf
(
"Failed to register the Version Check service: %v"
,
err
)
if
err
:=
stack
.
Register
(
func
(
ctx
*
node
.
ServiceContext
)
(
node
.
Service
,
error
)
{
return
release
.
NewReleaseService
(
ctx
,
relconf
)
});
err
!=
nil
{
Fatalf
(
"Failed to register the Geth release oracle service: %v"
,
err
)
}
return
stack
}
...
...
eth/api.go
View file @
586eddfd
...
...
@@ -52,14 +52,14 @@ import (
"golang.org/x/net/context"
)
//
E
rrNoCode is returned by call and transact operations for which the requested
//
e
rrNoCode is returned by call and transact operations for which the requested
// recipient contract to operate on does not exist in the state db or does not
// have any code associated with it (i.e. suicided).
//
// Please note, this error string is part of the RPC API and is expected by the
// native contract bindings to signal this particular error. Do not change this
// as it will break all dependent code!
var
E
rrNoCode
=
errors
.
New
(
"no contract code at given address"
)
var
e
rrNoCode
=
errors
.
New
(
"no contract code at given address"
)
const
defaultGas
=
uint64
(
90000
)
...
...
@@ -107,8 +107,11 @@ type PublicEthereumAPI struct {
}
// NewPublicEthereumAPI creates a new Ethereum protocol API.
func
NewPublicEthereumAPI
(
e
*
Ethereum
,
gpo
*
GasPriceOracle
)
*
PublicEthereumAPI
{
return
&
PublicEthereumAPI
{
e
,
gpo
}
func
NewPublicEthereumAPI
(
e
*
Ethereum
)
*
PublicEthereumAPI
{
return
&
PublicEthereumAPI
{
e
:
e
,
gpo
:
e
.
gpo
,
}
}
// GasPrice returns a suggestion for a gas price.
...
...
@@ -717,7 +720,7 @@ func (s *PublicBlockChainAPI) doCall(args CallArgs, blockNr rpc.BlockNumber) (st
// If there's no code to interact with, respond with an appropriate error
if
args
.
To
!=
nil
{
if
code
:=
stateDb
.
GetCode
(
*
args
.
To
);
len
(
code
)
==
0
{
return
"0x"
,
nil
,
E
rrNoCode
return
"0x"
,
nil
,
e
rrNoCode
}
}
// Retrieve the account state object to interact with
...
...
@@ -914,18 +917,17 @@ type PublicTransactionPoolAPI struct {
}
// NewPublicTransactionPoolAPI creates a new RPC service with methods specific for the transaction pool.
func
NewPublicTransactionPoolAPI
(
e
*
Ethereum
,
gpo
*
GasPriceOracle
)
*
PublicTransactionPoolAPI
{
func
NewPublicTransactionPoolAPI
(
e
*
Ethereum
)
*
PublicTransactionPoolAPI
{
api
:=
&
PublicTransactionPoolAPI
{
eventMux
:
e
.
EventMux
()
,
gpo
:
gpo
,
chainDb
:
e
.
ChainDb
()
,
bc
:
e
.
BlockChain
()
,
am
:
e
.
AccountManager
()
,
txPool
:
e
.
TxPool
()
,
miner
:
e
.
Miner
()
,
eventMux
:
e
.
eventMux
,
gpo
:
e
.
gpo
,
chainDb
:
e
.
chainDb
,
bc
:
e
.
blockchain
,
am
:
e
.
accountManager
,
txPool
:
e
.
txPool
,
miner
:
e
.
miner
,
pendingTxSubs
:
make
(
map
[
string
]
rpc
.
Subscription
),
}
go
api
.
subscriptionLoop
()
return
api
...
...
eth/backend.go
View file @
586eddfd
...
...
@@ -119,6 +119,7 @@ type Ethereum struct {
protocolManager
*
ProtocolManager
SolcPath
string
solc
*
compiler
.
Solidity
gpo
*
GasPriceOracle
GpoMinGasPrice
*
big
.
Int
GpoMaxGasPrice
*
big
.
Int
...
...
@@ -260,6 +261,8 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
}
return
nil
,
err
}
eth
.
gpo
=
NewGasPriceOracle
(
eth
)
newPool
:=
core
.
NewTxPool
(
eth
.
chainConfig
,
eth
.
EventMux
(),
eth
.
blockchain
.
State
,
eth
.
blockchain
.
GasLimit
)
eth
.
txPool
=
newPool
...
...
@@ -276,34 +279,31 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
// APIs returns the collection of RPC services the ethereum package offers.
// NOTE, some of these services probably need to be moved to somewhere else.
func
(
s
*
Ethereum
)
APIs
()
[]
rpc
.
API
{
// share gas price oracle in API's
gpo
:=
NewGasPriceOracle
(
s
)
return
[]
rpc
.
API
{
{
Namespace
:
"eth"
,
Version
:
"1.0"
,
Service
:
NewPublicEthereumAPI
(
s
,
gpo
),
Service
:
NewPublicEthereumAPI
(
s
),
Public
:
true
,
},
{
Namespace
:
"eth"
,
Version
:
"1.0"
,
Service
:
NewPublicAccountAPI
(
s
.
AccountManager
()
),
Service
:
NewPublicAccountAPI
(
s
.
accountManager
),
Public
:
true
,
},
{
Namespace
:
"personal"
,
Version
:
"1.0"
,
Service
:
NewPrivateAccountAPI
(
s
.
AccountManager
()
),
Service
:
NewPrivateAccountAPI
(
s
.
accountManager
),
Public
:
false
,
},
{
Namespace
:
"eth"
,
Version
:
"1.0"
,
Service
:
NewPublicBlockChainAPI
(
s
.
chainConfig
,
s
.
BlockChain
(),
s
.
Miner
(),
s
.
ChainDb
(),
gpo
,
s
.
EventMux
(),
s
.
AccountManager
()
),
Service
:
NewPublicBlockChainAPI
(
s
.
chainConfig
,
s
.
blockchain
,
s
.
miner
,
s
.
chainDb
,
s
.
gpo
,
s
.
eventMux
,
s
.
accountManager
),
Public
:
true
,
},
{
Namespace
:
"eth"
,
Version
:
"1.0"
,
Service
:
NewPublicTransactionPoolAPI
(
s
,
gpo
),
Service
:
NewPublicTransactionPoolAPI
(
s
),
Public
:
true
,
},
{
Namespace
:
"eth"
,
...
...
@@ -313,7 +313,7 @@ func (s *Ethereum) APIs() []rpc.API {
},
{
Namespace
:
"eth"
,
Version
:
"1.0"
,
Service
:
downloader
.
NewPublicDownloaderAPI
(
s
.
Downloader
(),
s
.
EventMux
()
),
Service
:
downloader
.
NewPublicDownloaderAPI
(
s
.
protocolManager
.
downloader
,
s
.
eventMux
),
Public
:
true
,
},
{
Namespace
:
"miner"
,
...
...
@@ -328,7 +328,7 @@ func (s *Ethereum) APIs() []rpc.API {
},
{
Namespace
:
"eth"
,
Version
:
"1.0"
,
Service
:
filters
.
NewPublicFilterAPI
(
s
.
ChainDb
(),
s
.
EventMux
()
),
Service
:
filters
.
NewPublicFilterAPI
(
s
.
chainDb
,
s
.
eventMux
),
Public
:
true
,
},
{
Namespace
:
"admin"
,
...
...
@@ -351,7 +351,7 @@ func (s *Ethereum) APIs() []rpc.API {
},
{
Namespace
:
"admin"
,
Version
:
"1.0"
,
Service
:
ethreg
.
NewPrivateRegistarAPI
(
s
.
chainConfig
,
s
.
BlockChain
(),
s
.
ChainDb
(),
s
.
TxPool
(),
s
.
AccountManager
()
),
Service
:
ethreg
.
NewPrivateRegistarAPI
(
s
.
chainConfig
,
s
.
blockchain
,
s
.
chainDb
,
s
.
txPool
,
s
.
accountManager
),
},
}
}
...
...
eth/bind.go
0 → 100644
View file @
586eddfd
// 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
eth
import
(
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
)
// ContractBackend implements bind.ContractBackend with direct calls to Ethereum
// internals to support operating on contracts within subprotocols like eth and
// swarm.
//
// Internally this backend uses the already exposed API endpoints of the Ethereum
// object. These should be rewritten to internal Go method calls when the Go API
// is refactored to support a clean library use.
type
ContractBackend
struct
{
eapi
*
PublicEthereumAPI
// Wrapper around the Ethereum object to access metadata
bcapi
*
PublicBlockChainAPI
// Wrapper around the blockchain to access chain data
txapi
*
PublicTransactionPoolAPI
// Wrapper around the transaction pool to access transaction data
}
// NewContractBackend creates a new native contract backend using an existing
// Etheruem object.
func
NewContractBackend
(
eth
*
Ethereum
)
*
ContractBackend
{
return
&
ContractBackend
{
eapi
:
NewPublicEthereumAPI
(
eth
),
bcapi
:
NewPublicBlockChainAPI
(
eth
.
chainConfig
,
eth
.
blockchain
,
eth
.
miner
,
eth
.
chainDb
,
eth
.
gpo
,
eth
.
eventMux
,
eth
.
accountManager
),
txapi
:
NewPublicTransactionPoolAPI
(
eth
),
}
}
// ContractCall implements bind.ContractCaller executing an Ethereum contract
// call with the specified data as the input. The pending flag requests execution
// against the pending block, not the stable head of the chain.
func
(
b
*
ContractBackend
)
ContractCall
(
contract
common
.
Address
,
data
[]
byte
,
pending
bool
)
([]
byte
,
error
)
{
// Convert the input args to the API spec
args
:=
CallArgs
{
To
:
&
contract
,
Data
:
common
.
ToHex
(
data
),
}
block
:=
rpc
.
LatestBlockNumber
if
pending
{
block
=
rpc
.
PendingBlockNumber
}
// Execute the call and convert the output back to Go types
out
,
err
:=
b
.
bcapi
.
Call
(
args
,
block
)
if
err
==
errNoCode
{
err
=
bind
.
ErrNoCode
}
return
common
.
FromHex
(
out
),
err
}
// PendingAccountNonce implements bind.ContractTransactor retrieving the current
// pending nonce associated with an account.
func
(
b
*
ContractBackend
)
PendingAccountNonce
(
account
common
.
Address
)
(
uint64
,
error
)
{
out
,
err
:=
b
.
txapi
.
GetTransactionCount
(
account
,
rpc
.
PendingBlockNumber
)
return
out
.
Uint64
(),
err
}
// SuggestGasPrice implements bind.ContractTransactor retrieving the currently
// suggested gas price to allow a timely execution of a transaction.
func
(
b
*
ContractBackend
)
SuggestGasPrice
()
(
*
big
.
Int
,
error
)
{
return
b
.
eapi
.
GasPrice
(),
nil
}
// EstimateGasLimit implements bind.ContractTransactor triing 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
(
b
*
ContractBackend
)
EstimateGasLimit
(
sender
common
.
Address
,
contract
*
common
.
Address
,
value
*
big
.
Int
,
data
[]
byte
)
(
*
big
.
Int
,
error
)
{
out
,
err
:=
b
.
bcapi
.
EstimateGas
(
CallArgs
{
From
:
sender
,
To
:
contract
,
Value
:
*
rpc
.
NewHexNumber
(
value
),
Data
:
common
.
ToHex
(
data
),
})
if
err
==
errNoCode
{
err
=
bind
.
ErrNoCode
}
return
out
.
BigInt
(),
err
}
// SendTransaction implements bind.ContractTransactor injects the transaction
// into the pending pool for execution.
func
(
b
*
ContractBackend
)
SendTransaction
(
tx
*
types
.
Transaction
)
error
{
raw
,
_
:=
rlp
.
EncodeToBytes
(
tx
)
_
,
err
:=
b
.
txapi
.
SendRawTransaction
(
common
.
ToHex
(
raw
))
return
err
}
node/node.go
View file @
586eddfd
...
...
@@ -311,7 +311,7 @@ func (n *Node) startIPC(apis []rpc.API) error {
glog
.
V
(
logger
.
Error
)
.
Infof
(
"IPC accept failed: %v"
,
err
)
continue
}
go
handler
.
ServeCodec
(
rpc
.
NewJSONCodec
(
conn
),
rpc
.
OptionMethodInvocation
|
rpc
.
OptionSubscriptions
)
go
handler
.
ServeCodec
(
rpc
.
NewJSONCodec
(
conn
),
rpc
.
OptionMethodInvocation
|
rpc
.
OptionSubscriptions
)
}
}()
// All listeners booted successfully
...
...
@@ -530,7 +530,6 @@ func (n *Node) Server() *p2p.Server {
}
// Service retrieves a currently running service registered of a specific type.
// NOTE: must be called with double pointer to service
func
(
n
*
Node
)
Service
(
service
interface
{})
error
{
n
.
lock
.
RLock
()
defer
n
.
lock
.
RUnlock
()
...
...
node/service.go
View file @
586eddfd
...
...
@@ -68,7 +68,7 @@ type ServiceConstructor func(ctx *ServiceContext) (Service, error)
// - Restart logic is not required as the node will create a fresh instance
// every time a service is started.
type
Service
interface
{
// Protocol retrieves the P2P protocols the service wishes to start.
// Protocol
s
retrieves the P2P protocols the service wishes to start.
Protocols
()
[]
p2p
.
Protocol
// APIs retrieves the list of RPC descriptors the service provides
...
...
contracts/
release/contract.go
→
release/contract.go
View file @
586eddfd
This diff is collapsed.
Click to expand it.
contracts/
release/contract.sol
→
release/contract.sol
View file @
586eddfd
...
...
@@ -19,7 +19,7 @@
// check for new releases automatically without the need to consult a central
// repository.
//
// The contract takes a vote based approach on both assigning authori
z
ed signers
// The contract takes a vote based approach on both assigning authori
s
ed signers
// as well as signing off on new Geth releases.
//
// Note, when a signer is demoted, the currently pending release is auto-nuked.
...
...
@@ -45,8 +45,8 @@ contract ReleaseOracle {
}
// Oracle authorization details
mapping(address => bool) authori
z
ed; // Set of accounts allowed to vote on updating the contract
address[]
signers;
// List of addresses currently accepted as signers
mapping(address => bool) authori
s
ed; // Set of accounts allowed to vote on updating the contract
address[]
voters;
// List of addresses currently accepted as signers
// Various proposals being voted on
mapping(address => Votes) authProps; // Currently running user authorization proposals
...
...
@@ -57,38 +57,47 @@ contract ReleaseOracle {
// isSigner is a modifier to authorize contract transactions.
modifier isSigner() {
if (authori
z
ed[msg.sender]) {
if (authori
s
ed[msg.sender]) {
_
}
}
// Constructor to assign the creator as the sole valid signer.
function ReleaseOracle() {
authorized[msg.sender] = true;
signers.push(msg.sender);
// Constructor to assign the initial set of signers.
function ReleaseOracle(address[] signers) {
// If no signers were specified, assign the creator as the sole signer
if (signers.length == 0) {
authorised[msg.sender] = true;
voters.push(msg.sender);
return;
}
// Otherwise assign the individual signers one by one
for (uint i = 0; i < signers.length; i++) {
authorised[signers[i]] = true;
voters.push(signers[i]);
}
}
//
S
igners is an accessor method to retrieve all te signers (public accessor
//
s
igners is an accessor method to retrieve all te signers (public accessor
// generates an indexed one, not a retreive-all version).
function
S
igners() constant returns(address[]) {
return
sign
ers;
function
s
igners() constant returns(address[]) {
return
vot
ers;
}
//
A
uthProposals retrieves the list of addresses that authorization proposals
//
a
uthProposals retrieves the list of addresses that authorization proposals
// are currently being voted on.
function
A
uthProposals() constant returns(address[]) {
function
a
uthProposals() constant returns(address[]) {
return authPend;
}
//
A
uthVotes retrieves the current authorization votes for a particular user
//
a
uthVotes retrieves the current authorization votes for a particular user
// to promote him into the list of signers, or demote him from there.
function
A
uthVotes(address user) constant returns(address[] promote, address[] demote) {
function
a
uthVotes(address user) constant returns(address[] promote, address[] demote) {
return (authProps[user].pass, authProps[user].fail);
}
//
C
urrentVersion retrieves the semantic version, commit hash and release time
//
c
urrentVersion retrieves the semantic version, commit hash and release time
// of the currently votec active release.
function
C
urrentVersion() constant returns (uint32 major, uint32 minor, uint32 patch, bytes20 commit, uint time) {
function
c
urrentVersion() constant returns (uint32 major, uint32 minor, uint32 patch, bytes20 commit, uint time) {
if (releases.length == 0) {
return (0, 0, 0, 0, 0);
}
...
...
@@ -97,38 +106,38 @@ contract ReleaseOracle {
return (release.major, release.minor, release.patch, release.commit, release.time);
}
//
P
roposedVersion retrieves the semantic version, commit hash and the current
//
p
roposedVersion retrieves the semantic version, commit hash and the current
// votes for the next proposed release.
function
P
roposedVersion() constant returns (uint32 major, uint32 minor, uint32 patch, bytes20 commit, address[] pass, address[] fail) {
function
p
roposedVersion() constant returns (uint32 major, uint32 minor, uint32 patch, bytes20 commit, address[] pass, address[] fail) {
return (verProp.major, verProp.minor, verProp.patch, verProp.commit, verProp.votes.pass, verProp.votes.fail);
}
//
P
romote pitches in on a voting campaign to promote a new user to a signer
//
p
romote pitches in on a voting campaign to promote a new user to a signer
// position.
function
P
romote(address user) {
function
p
romote(address user) {
updateSigner(user, true);
}
//
Demote pitches in on a voting campaign to demote an authoriz
ed user from
//
demote pitches in on a voting campaign to demote an authoris
ed user from
// its signer position.
function
D
emote(address user) {
function
d
emote(address user) {
updateSigner(user, false);
}
//
R
elease votes for a particular version to be included as the next release.
function
R
elease(uint32 major, uint32 minor, uint32 patch, bytes20 commit) {
//
r
elease votes for a particular version to be included as the next release.
function
r
elease(uint32 major, uint32 minor, uint32 patch, bytes20 commit) {
updateRelease(major, minor, patch, commit, true);
}
//
N
uke votes for the currently proposed version to not be included as the next
//
n
uke votes for the currently proposed version to not be included as the next
// release. Nuking doesn't require a specific version number for simplicity.
function
N
uke() {
function
n
uke() {
updateRelease(0, 0, 0, 0, false);
}
// updateSigner marks a vote for changing the status of an Ethereum user, either
// for or against the user being an authori
z
ed signer.
function updateSigner(address user, bool authorize) isSigner {
// for or against the user being an authori
s
ed signer.
function updateSigner(address user, bool authorize) i
nternal i
sSigner {
// Gather the current votes and ensure we don't double vote
Votes votes = authProps[user];
for (uint i = 0; i < votes.pass.length; i++) {
...
...
@@ -148,26 +157,26 @@ contract ReleaseOracle {
// Cast the vote and return if the proposal cannot be resolved yet
if (authorize) {
votes.pass.push(msg.sender);
if (votes.pass.length <=
sign
ers.length / 2) {
if (votes.pass.length <=
vot
ers.length / 2) {
return;
}
} else {
votes.fail.push(msg.sender);
if (votes.fail.length <=
sign
ers.length / 2) {
if (votes.fail.length <=
vot
ers.length / 2) {
return;
}
}
// Proposal resolved in our favor, execute whatever we voted on
if (authorize && !authori
z
ed[user]) {
authori
z
ed[user] = true;
sign
ers.push(user);
} else if (!authorize && authori
z
ed[user]) {
authori
z
ed[user] = false;
if (authorize && !authori
s
ed[user]) {
authori
s
ed[user] = true;
vot
ers.push(user);
} else if (!authorize && authori
s
ed[user]) {
authori
s
ed[user] = false;
for (i = 0; i <
sign
ers.length; i++) {
if (
sign
ers[i] == user) {
signers[i] = signers[sign
ers.length - 1];
sign
ers.length--;
for (i = 0; i <
vot
ers.length; i++) {
if (
vot
ers[i] == user) {
voters[i] = voters[vot
ers.length - 1];
vot
ers.length--;
delete verProp; // Nuke any version proposal (no suprise releases!)
break;
...
...
@@ -188,7 +197,7 @@ contract ReleaseOracle {
// updateRelease votes for a particular version to be included as the next release,
// or for the currently proposed release to be nuked out.
function updateRelease(uint32 major, uint32 minor, uint32 patch, bytes20 commit, bool release) isSigner {
function updateRelease(uint32 major, uint32 minor, uint32 patch, bytes20 commit, bool release) i
nternal i
sSigner {
// Skip nuke votes if no proposal is pending
if (!release && verProp.votes.pass.length == 0) {
return;
...
...
@@ -219,12 +228,12 @@ contract ReleaseOracle {
// Cast the vote and return if the proposal cannot be resolved yet
if (release) {
votes.pass.push(msg.sender);
if (votes.pass.length <=
sign
ers.length / 2) {
if (votes.pass.length <=
vot
ers.length / 2) {
return;
}
} else {
votes.fail.push(msg.sender);
if (votes.fail.length <=
sign
ers.length / 2) {
if (votes.fail.length <=
vot
ers.length / 2) {
return;
}
}
...
...
contracts/
release/contract_test.go
→
release/contract_test.go
View file @
586eddfd
...
...
@@ -42,7 +42,7 @@ func setupReleaseTest(t *testing.T, prefund ...*ecdsa.PrivateKey) (*ecdsa.Privat
sim
:=
backends
.
NewSimulatedBackend
(
accounts
...
)
// Deploy a version oracle contract, commit and return
_
,
_
,
oracle
,
err
:=
DeployReleaseOracle
(
auth
,
sim
)
_
,
_
,
oracle
,
err
:=
DeployReleaseOracle
(
auth
,
sim
,
[]
common
.
Address
{
auth
.
From
}
)
if
err
!=
nil
{
t
.
Fatalf
(
"Failed to deploy version contract: %v"
,
err
)
}
...
...
@@ -239,7 +239,7 @@ func TestVersionRelease(t *testing.T) {
// Propose release with half voters and check that the release does not yet go through
for
j
:=
0
;
j
<
(
i
+
1
)
/
2
;
j
++
{
if
_
,
err
=
oracle
.
Release
(
bind
.
NewKeyedTransactor
(
keys
[
j
]),
uint32
(
i
),
uint32
(
i
+
1
),
uint32
(
i
+
2
),
[
20
]
byte
{});
err
!=
nil
{
if
_
,
err
=
oracle
.
Release
(
bind
.
NewKeyedTransactor
(
keys
[
j
]),
uint32
(
i
),
uint32
(
i
+
1
),
uint32
(
i
+
2
),
[
20
]
byte
{
byte
(
i
+
3
)
});
err
!=
nil
{
t
.
Fatalf
(
"Iter #%d: failed valid release attempt: %v"
,
i
,
err
)
}
}
...
...
@@ -254,8 +254,8 @@ func TestVersionRelease(t *testing.T) {
}
// Pass the release and check that it became the next version
verMajor
,
verMinor
,
verPatch
,
verCommit
=
uint32
(
i
),
uint32
(
i
+
1
),
uint32
(
i
+
2
),
[
20
]
byte
{}
if
_
,
err
=
oracle
.
Release
(
bind
.
NewKeyedTransactor
(
keys
[(
i
+
1
)
/
2
]),
uint32
(
i
),
uint32
(
i
+
1
),
uint32
(
i
+
2
),
[
20
]
byte
{});
err
!=
nil
{
verMajor
,
verMinor
,
verPatch
,
verCommit
=
uint32
(
i
),
uint32
(
i
+
1
),
uint32
(
i
+
2
),
[
20
]
byte
{
byte
(
i
+
3
)
}
if
_
,
err
=
oracle
.
Release
(
bind
.
NewKeyedTransactor
(
keys
[(
i
+
1
)
/
2
]),
uint32
(
i
),
uint32
(
i
+
1
),
uint32
(
i
+
2
),
[
20
]
byte
{
byte
(
i
+
3
)
});
err
!=
nil
{
t
.
Fatalf
(
"Iter #%d: failed valid release completion attempt: %v"
,
i
,
err
)
}
sim
.
Commit
()
...
...
@@ -293,7 +293,7 @@ func TestVersionNuking(t *testing.T) {
for
i
:=
1
;
i
<
(
len
(
keys
)
+
1
)
/
2
;
i
++
{
// Propose release with an initial set of signers
for
j
:=
0
;
j
<
i
;
j
++
{
if
_
,
err
:=
oracle
.
Release
(
bind
.
NewKeyedTransactor
(
keys
[
j
]),
uint32
(
i
),
uint32
(
i
+
1
),
uint32
(
i
+
2
),
[
20
]
byte
{});
err
!=
nil
{
if
_
,
err
:=
oracle
.
Release
(
bind
.
NewKeyedTransactor
(
keys
[
j
]),
uint32
(
i
),
uint32
(
i
+
1
),
uint32
(
i
+
2
),
[
20
]
byte
{
byte
(
i
+
3
)
});
err
!=
nil
{
t
.
Fatalf
(
"Iter #%d: failed valid proposal attempt: %v"
,
i
,
err
)
}
}
...
...
@@ -344,7 +344,7 @@ func TestVersionAutoNuke(t *testing.T) {
sim
.
Commit
()
}
// Make a release proposal and check it's existence
if
_
,
err
:=
oracle
.
Release
(
bind
.
NewKeyedTransactor
(
keys
[
0
]),
1
,
2
,
3
,
[
20
]
byte
{});
err
!=
nil
{
if
_
,
err
:=
oracle
.
Release
(
bind
.
NewKeyedTransactor
(
keys
[
0
]),
1
,
2
,
3
,
[
20
]
byte
{
4
});
err
!=
nil
{
t
.
Fatalf
(
"Failed valid proposal attempt: %v"
,
err
)
}
sim
.
Commit
()
...
...
contracts/
release/generator.go
→
release/generator.go
View file @
586eddfd
File moved
release/release.go
0 → 100644
View file @
586eddfd
// 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 release contains the node service that tracks client releases.
package
release
import
(
"fmt"
"strings"
"time"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/rpc"
)
// Interval to check for new releases
const
releaseRecheckInterval
=
time
.
Hour
// Config contains the configurations of the release service.
type
Config
struct
{
Oracle
common
.
Address
// Ethereum address of the release oracle
Major
uint32
// Major version component of the release
Minor
uint32
// Minor version component of the release
Patch
uint32
// Patch version component of the release
Commit
[
20
]
byte
// Git SHA1 commit hash of the release
}
// ReleaseService is a node service that periodically checks the blockchain for
// newly released versions of the client being run and issues a warning to the
// user about it.
type
ReleaseService
struct
{
config
Config
// Current version to check releases against
oracle
*
ReleaseOracle
// Native binding to the release oracle contract
quit
chan
chan
error
// Quit channel to terminate the version checker
}
// NewReleaseService creates a new service to periodically check for new client
// releases and notify the user of such.
func
NewReleaseService
(
ctx
*
node
.
ServiceContext
,
config
Config
)
(
node
.
Service
,
error
)
{
// Retrieve the Ethereum service dependency to access the blockchain
var
ethereum
*
eth
.
Ethereum
if
err
:=
ctx
.
Service
(
&
ethereum
);
err
!=
nil
{
return
nil
,
err
}
// Construct the release service
contract
,
err
:=
NewReleaseOracle
(
config
.
Oracle
,
eth
.
NewContractBackend
(
ethereum
))
if
err
!=
nil
{
return
nil
,
err
}
return
&
ReleaseService
{
config
:
config
,
oracle
:
contract
,
quit
:
make
(
chan
chan
error
),
},
nil
}
// Protocols returns an empty list of P2P protocols as the release service does
// not have a networking component.
func
(
r
*
ReleaseService
)
Protocols
()
[]
p2p
.
Protocol
{
return
nil
}
// APIs returns an empty list of RPC descriptors as the release service does not
// expose any functioanlity to the outside world.
func
(
r
*
ReleaseService
)
APIs
()
[]
rpc
.
API
{
return
nil
}
// Start spawns the periodic version checker goroutine
func
(
r
*
ReleaseService
)
Start
(
server
*
p2p
.
Server
)
error
{
go
r
.
checker
()
return
nil
}
// Stop terminates all goroutines belonging to the service, blocking until they
// are all terminated.
func
(
r
*
ReleaseService
)
Stop
()
error
{
errc
:=
make
(
chan
error
)
r
.
quit
<-
errc
return
<-
errc
}
// checker runs indefinitely in the background, periodically checking for new
// client releases.
func
(
r
*
ReleaseService
)
checker
()
{
// Set up the timers to periodically check for releases
timer
:=
time
.
NewTimer
(
0
)
// Immediately fire a version check
defer
timer
.
Stop
()
for
{
select
{
// If the time arrived, check for a new release
case
<-
timer
.
C
:
// Rechedule the timer before continuing
timer
.
Reset
(
releaseRecheckInterval
)
// Retrieve the current version, and handle missing contracts gracefully
version
,
err
:=
r
.
oracle
.
CurrentVersion
(
nil
)
if
err
!=
nil
{
if
err
==
bind
.
ErrNoCode
{
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Release oracle not found at %x"
,
r
.
config
.
Oracle
)
continue
}
glog
.
V
(
logger
.
Error
)
.
Infof
(
"Failed to retrieve current release: %v"
,
err
)
continue
}
// Version was successfully retrieved, notify if newer than ours
if
version
.
Major
>
r
.
config
.
Major
||
(
version
.
Major
==
r
.
config
.
Major
&&
version
.
Minor
>
r
.
config
.
Minor
)
||
(
version
.
Major
==
r
.
config
.
Major
&&
version
.
Minor
==
r
.
config
.
Minor
&&
version
.
Patch
>
r
.
config
.
Patch
)
{
warning
:=
fmt
.
Sprintf
(
"Client v%d.%d.%d-%x seems older than the latest upstream release v%d.%d.%d-%x"
,
r
.
config
.
Major
,
r
.
config
.
Minor
,
r
.
config
.
Patch
,
r
.
config
.
Commit
[
:
4
],
version
.
Major
,
version
.
Minor
,
version
.
Patch
,
version
.
Commit
[
:
4
])
howtofix
:=
fmt
.
Sprintf
(
"Please check https://github.com/ethereum/go-ethereum/releases for new releases"
)
separator
:=
strings
.
Repeat
(
"-"
,
len
(
warning
))
glog
.
V
(
logger
.
Warn
)
.
Info
(
separator
)
glog
.
V
(
logger
.
Warn
)
.
Info
(
warning
)
glog
.
V
(
logger
.
Warn
)
.
Info
(
howtofix
)
glog
.
V
(
logger
.
Warn
)
.
Info
(
separator
)
}
else
{
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"Client v%d.%d.%d-%x seems up to date with upstream v%d.%d.%d-%x"
,
r
.
config
.
Major
,
r
.
config
.
Minor
,
r
.
config
.
Patch
,
r
.
config
.
Commit
[
:
4
],
version
.
Major
,
version
.
Minor
,
version
.
Patch
,
version
.
Commit
[
:
4
])
}
// If termination was requested, return
case
errc
:=
<-
r
.
quit
:
errc
<-
nil
return
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment