accounts/abi/bind: support event filtering in abigen
This commit is contained in:
@ -7,17 +7,19 @@ import (
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
ethereum "github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"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/event"
|
||||
)
|
||||
|
||||
// ChequebookABI is the input ABI used to generate the binding from.
|
||||
const ChequebookABI = "[{\"constant\":false,\"inputs\":[],\"name\":\"kill\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"address\"}],\"name\":\"sent\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"beneficiary\",\"type\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\"},{\"name\":\"sig_v\",\"type\":\"uint8\"},{\"name\":\"sig_r\",\"type\":\"bytes32\"},{\"name\":\"sig_s\",\"type\":\"bytes32\"}],\"name\":\"cash\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"deadbeat\",\"type\":\"address\"}],\"name\":\"Overdraft\",\"type\":\"event\"}]"
|
||||
|
||||
// ChequebookBin is the compiled bytecode used for deploying new contracts.
|
||||
const ChequebookBin = `0x606060405260008054600160a060020a033316600160a060020a03199091161790556102ec806100306000396000f3006060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b581146100585780637bf786f81461006b578063fbf788d61461009c575b005b341561006357600080fd5b6100566100ca565b341561007657600080fd5b61008a600160a060020a03600435166100f1565b60405190815260200160405180910390f35b34156100a757600080fd5b610056600160a060020a036004351660243560ff60443516606435608435610103565b60005433600160a060020a03908116911614156100ef57600054600160a060020a0316ff5b565b60016020526000908152604090205481565b600160a060020a0385166000908152600160205260408120548190861161012957600080fd5b3087876040516c01000000000000000000000000600160a060020a03948516810282529290931690910260148301526028820152604801604051809103902091506001828686866040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156101cf57600080fd5b505060206040510351600054600160a060020a039081169116146101f257600080fd5b50600160a060020a03808716600090815260016020526040902054860390301631811161026257600160a060020a0387166000818152600160205260409081902088905582156108fc0290839051600060405180830381858888f19350505050151561025d57600080fd5b6102b7565b6000547f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f97890600160a060020a0316604051600160a060020a03909116815260200160405180910390a186600160a060020a0316ff5b505050505050505600a165627a7a7230582014e927522ca5cd8f68529ac4d3b9cdf36d40e09d8a33b70008248d1abebf79680029`
|
||||
const ChequebookBin = `0x606060405260008054600160a060020a033316600160a060020a03199091161790556102ec806100306000396000f3006060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b581146100585780637bf786f81461006b578063fbf788d61461009c575b005b341561006357600080fd5b6100566100ca565b341561007657600080fd5b61008a600160a060020a03600435166100f1565b60405190815260200160405180910390f35b34156100a757600080fd5b610056600160a060020a036004351660243560ff60443516606435608435610103565b60005433600160a060020a03908116911614156100ef57600054600160a060020a0316ff5b565b60016020526000908152604090205481565b600160a060020a0385166000908152600160205260408120548190861161012957600080fd5b3087876040516c01000000000000000000000000600160a060020a03948516810282529290931690910260148301526028820152604801604051809103902091506001828686866040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156101cf57600080fd5b505060206040510351600054600160a060020a039081169116146101f257600080fd5b50600160a060020a03808716600090815260016020526040902054860390301631811161026257600160a060020a0387166000818152600160205260409081902088905582156108fc0290839051600060405180830381858888f19350505050151561025d57600080fd5b6102b7565b6000547f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f97890600160a060020a0316604051600160a060020a03909116815260200160405180910390a186600160a060020a0316ff5b505050505050505600a165627a7a72305820533e856fc37e3d64d1706bcc7dfb6b1d490c8d566ea498d9d01ec08965a896ca0029`
|
||||
|
||||
// DeployChequebook deploys a new Ethereum contract, binding an instance of Chequebook to it.
|
||||
func DeployChequebook(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Chequebook, error) {
|
||||
@ -29,13 +31,14 @@ func DeployChequebook(auth *bind.TransactOpts, backend bind.ContractBackend) (co
|
||||
if err != nil {
|
||||
return common.Address{}, nil, nil, err
|
||||
}
|
||||
return address, tx, &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}}, nil
|
||||
return address, tx, &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}, ChequebookFilterer: ChequebookFilterer{contract: contract}}, nil
|
||||
}
|
||||
|
||||
// Chequebook is an auto generated Go binding around an Ethereum contract.
|
||||
type Chequebook struct {
|
||||
ChequebookCaller // Read-only binding to the contract
|
||||
ChequebookTransactor // Write-only binding to the contract
|
||||
ChequebookFilterer // Log filterer for contract events
|
||||
}
|
||||
|
||||
// ChequebookCaller is an auto generated read-only Go binding around an Ethereum contract.
|
||||
@ -48,6 +51,11 @@ type ChequebookTransactor struct {
|
||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||
}
|
||||
|
||||
// ChequebookFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
|
||||
type ChequebookFilterer struct {
|
||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||
}
|
||||
|
||||
// ChequebookSession is an auto generated Go binding around an Ethereum contract,
|
||||
// with pre-set call and transact options.
|
||||
type ChequebookSession struct {
|
||||
@ -87,16 +95,16 @@ type ChequebookTransactorRaw struct {
|
||||
|
||||
// NewChequebook creates a new instance of Chequebook, bound to a specific deployed contract.
|
||||
func NewChequebook(address common.Address, backend bind.ContractBackend) (*Chequebook, error) {
|
||||
contract, err := bindChequebook(address, backend, backend)
|
||||
contract, err := bindChequebook(address, backend, backend, backend)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}}, nil
|
||||
return &Chequebook{ChequebookCaller: ChequebookCaller{contract: contract}, ChequebookTransactor: ChequebookTransactor{contract: contract}, ChequebookFilterer: ChequebookFilterer{contract: contract}}, nil
|
||||
}
|
||||
|
||||
// NewChequebookCaller creates a new read-only instance of Chequebook, bound to a specific deployed contract.
|
||||
func NewChequebookCaller(address common.Address, caller bind.ContractCaller) (*ChequebookCaller, error) {
|
||||
contract, err := bindChequebook(address, caller, nil)
|
||||
contract, err := bindChequebook(address, caller, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -105,20 +113,29 @@ func NewChequebookCaller(address common.Address, caller bind.ContractCaller) (*C
|
||||
|
||||
// NewChequebookTransactor creates a new write-only instance of Chequebook, bound to a specific deployed contract.
|
||||
func NewChequebookTransactor(address common.Address, transactor bind.ContractTransactor) (*ChequebookTransactor, error) {
|
||||
contract, err := bindChequebook(address, nil, transactor)
|
||||
contract, err := bindChequebook(address, nil, transactor, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ChequebookTransactor{contract: contract}, nil
|
||||
}
|
||||
|
||||
// NewChequebookFilterer creates a new log filterer instance of Chequebook, bound to a specific deployed contract.
|
||||
func NewChequebookFilterer(address common.Address, filterer bind.ContractFilterer) (*ChequebookFilterer, error) {
|
||||
contract, err := bindChequebook(address, nil, nil, filterer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ChequebookFilterer{contract: contract}, nil
|
||||
}
|
||||
|
||||
// bindChequebook binds a generic wrapper to an already deployed contract.
|
||||
func bindChequebook(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
|
||||
func bindChequebook(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
|
||||
parsed, err := abi.JSON(strings.NewReader(ChequebookABI))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bind.NewBoundContract(address, parsed, caller, transactor), nil
|
||||
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
|
||||
}
|
||||
|
||||
// Call invokes the (constant) contract method with params as input values and
|
||||
@ -226,3 +243,125 @@ func (_Chequebook *ChequebookSession) Kill() (*types.Transaction, error) {
|
||||
func (_Chequebook *ChequebookTransactorSession) Kill() (*types.Transaction, error) {
|
||||
return _Chequebook.Contract.Kill(&_Chequebook.TransactOpts)
|
||||
}
|
||||
|
||||
// ChequebookOverdraftIterator is returned from FilterOverdraft and is used to iterate over the raw logs and unpacked data for Overdraft events raised by the Chequebook contract.
|
||||
type ChequebookOverdraftIterator struct {
|
||||
Event *ChequebookOverdraft // Event containing the contract specifics and raw log
|
||||
|
||||
contract *bind.BoundContract // Generic contract to use for unpacking event data
|
||||
event string // Event name to use for unpacking event data
|
||||
|
||||
logs chan types.Log // Log channel receiving the found contract events
|
||||
sub ethereum.Subscription // Subscription for errors, completion and termination
|
||||
done bool // Whether the subscription completed delivering logs
|
||||
fail error // Occurred error to stop iteration
|
||||
}
|
||||
|
||||
// Next advances the iterator to the subsequent event, returning whether there
|
||||
// are any more events found. In case of a retrieval or parsing error, false is
|
||||
// returned and Error() can be queried for the exact failure.
|
||||
func (it *ChequebookOverdraftIterator) Next() bool {
|
||||
// If the iterator failed, stop iterating
|
||||
if it.fail != nil {
|
||||
return false
|
||||
}
|
||||
// If the iterator completed, deliver directly whatever's available
|
||||
if it.done {
|
||||
select {
|
||||
case log := <-it.logs:
|
||||
it.Event = new(ChequebookOverdraft)
|
||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||
it.fail = err
|
||||
return false
|
||||
}
|
||||
it.Event.Raw = log
|
||||
return true
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
// Iterator still in progress, wait for either a data or an error event
|
||||
select {
|
||||
case log := <-it.logs:
|
||||
it.Event = new(ChequebookOverdraft)
|
||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||
it.fail = err
|
||||
return false
|
||||
}
|
||||
it.Event.Raw = log
|
||||
return true
|
||||
|
||||
case err := <-it.sub.Err():
|
||||
it.done = true
|
||||
it.fail = err
|
||||
return it.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// Error retruned any retrieval or parsing error occurred during filtering.
|
||||
func (it *ChequebookOverdraftIterator) Error() error {
|
||||
return it.fail
|
||||
}
|
||||
|
||||
// Close terminates the iteration process, releasing any pending underlying
|
||||
// resources.
|
||||
func (it *ChequebookOverdraftIterator) Close() error {
|
||||
it.sub.Unsubscribe()
|
||||
return nil
|
||||
}
|
||||
|
||||
// ChequebookOverdraft represents a Overdraft event raised by the Chequebook contract.
|
||||
type ChequebookOverdraft struct {
|
||||
Deadbeat common.Address
|
||||
Raw types.Log // Blockchain specific contextual infos
|
||||
}
|
||||
|
||||
// FilterOverdraft is a free log retrieval operation binding the contract event 0x2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f978.
|
||||
//
|
||||
// Solidity: event Overdraft(deadbeat address)
|
||||
func (_Chequebook *ChequebookFilterer) FilterOverdraft(opts *bind.FilterOpts) (*ChequebookOverdraftIterator, error) {
|
||||
|
||||
logs, sub, err := _Chequebook.contract.FilterLogs(opts, "Overdraft")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ChequebookOverdraftIterator{contract: _Chequebook.contract, event: "Overdraft", logs: logs, sub: sub}, nil
|
||||
}
|
||||
|
||||
// WatchOverdraft is a free log subscription operation binding the contract event 0x2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f978.
|
||||
//
|
||||
// Solidity: event Overdraft(deadbeat address)
|
||||
func (_Chequebook *ChequebookFilterer) WatchOverdraft(opts *bind.WatchOpts, sink chan<- *ChequebookOverdraft) (event.Subscription, error) {
|
||||
|
||||
logs, sub, err := _Chequebook.contract.WatchLogs(opts, "Overdraft")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return event.NewSubscription(func(quit <-chan struct{}) error {
|
||||
defer sub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case log := <-logs:
|
||||
// New log arrived, parse the event and forward to the user
|
||||
event := new(ChequebookOverdraft)
|
||||
if err := _Chequebook.contract.UnpackLog(event, "Overdraft", log); err != nil {
|
||||
return err
|
||||
}
|
||||
event.Raw = log
|
||||
|
||||
select {
|
||||
case sink <- event:
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
return nil
|
||||
}
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
@ -2,4 +2,4 @@ package contract
|
||||
|
||||
// ContractDeployedCode is used to detect suicides. This constant needs to be
|
||||
// updated when the contract code is changed.
|
||||
const ContractDeployedCode = "0x6060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b581146100585780637bf786f81461006b578063fbf788d61461009c575b005b341561006357600080fd5b6100566100ca565b341561007657600080fd5b61008a600160a060020a03600435166100f1565b60405190815260200160405180910390f35b34156100a757600080fd5b610056600160a060020a036004351660243560ff60443516606435608435610103565b60005433600160a060020a03908116911614156100ef57600054600160a060020a0316ff5b565b60016020526000908152604090205481565b600160a060020a0385166000908152600160205260408120548190861161012957600080fd5b3087876040516c01000000000000000000000000600160a060020a03948516810282529290931690910260148301526028820152604801604051809103902091506001828686866040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156101cf57600080fd5b505060206040510351600054600160a060020a039081169116146101f257600080fd5b50600160a060020a03808716600090815260016020526040902054860390301631811161026257600160a060020a0387166000818152600160205260409081902088905582156108fc0290839051600060405180830381858888f19350505050151561025d57600080fd5b6102b7565b6000547f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f97890600160a060020a0316604051600160a060020a03909116815260200160405180910390a186600160a060020a0316ff5b505050505050505600a165627a7a7230582014e927522ca5cd8f68529ac4d3b9cdf36d40e09d8a33b70008248d1abebf79680029"
|
||||
const ContractDeployedCode = "0x6060604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b581146100585780637bf786f81461006b578063fbf788d61461009c575b005b341561006357600080fd5b6100566100ca565b341561007657600080fd5b61008a600160a060020a03600435166100f1565b60405190815260200160405180910390f35b34156100a757600080fd5b610056600160a060020a036004351660243560ff60443516606435608435610103565b60005433600160a060020a03908116911614156100ef57600054600160a060020a0316ff5b565b60016020526000908152604090205481565b600160a060020a0385166000908152600160205260408120548190861161012957600080fd5b3087876040516c01000000000000000000000000600160a060020a03948516810282529290931690910260148301526028820152604801604051809103902091506001828686866040516000815260200160405260006040516020015260405193845260ff90921660208085019190915260408085019290925260608401929092526080909201915160208103908084039060008661646e5a03f115156101cf57600080fd5b505060206040510351600054600160a060020a039081169116146101f257600080fd5b50600160a060020a03808716600090815260016020526040902054860390301631811161026257600160a060020a0387166000818152600160205260409081902088905582156108fc0290839051600060405180830381858888f19350505050151561025d57600080fd5b6102b7565b6000547f2250e2993c15843b32621c89447cc589ee7a9f049c026986e545d3c2c0c6f97890600160a060020a0316604051600160a060020a03909116815260200160405180910390a186600160a060020a0316ff5b505050505050505600a165627a7a72305820533e856fc37e3d64d1706bcc7dfb6b1d490c8d566ea498d9d01ec08965a896ca0029"
|
||||
|
@ -6,17 +6,19 @@ package contract
|
||||
import (
|
||||
"strings"
|
||||
|
||||
ethereum "github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi"
|
||||
"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/event"
|
||||
)
|
||||
|
||||
// ENSABI is the input ABI used to generate the binding from.
|
||||
const ENSABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"resolver\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"label\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setSubnodeOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"setTTL\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"}],\"name\":\"ttl\",\"outputs\":[{\"name\":\"\",\"type\":\"uint64\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"setResolver\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"node\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"label\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"NewOwner\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"resolver\",\"type\":\"address\"}],\"name\":\"NewResolver\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"node\",\"type\":\"bytes32\"},{\"indexed\":false,\"name\":\"ttl\",\"type\":\"uint64\"}],\"name\":\"NewTTL\",\"type\":\"event\"}]"
|
||||
|
||||
// ENSBin is the compiled bytecode used for deploying new contracts.
|
||||
const ENSBin = `0x6060604052341561000f57600080fd5b60008080526020527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb58054600160a060020a033316600160a060020a0319909116179055610503806100626000396000f3006060604052600436106100825763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630178b8bf811461008757806302571be3146100b957806306ab5923146100cf57806314ab9038146100f657806316a25cbd146101195780631896f70a1461014c5780635b0fc9c31461016e575b600080fd5b341561009257600080fd5b61009d600435610190565b604051600160a060020a03909116815260200160405180910390f35b34156100c457600080fd5b61009d6004356101ae565b34156100da57600080fd5b6100f4600435602435600160a060020a03604435166101c9565b005b341561010157600080fd5b6100f460043567ffffffffffffffff6024351661028b565b341561012457600080fd5b61012f600435610357565b60405167ffffffffffffffff909116815260200160405180910390f35b341561015757600080fd5b6100f4600435600160a060020a036024351661038e565b341561017957600080fd5b6100f4600435600160a060020a0360243516610434565b600090815260208190526040902060010154600160a060020a031690565b600090815260208190526040902054600160a060020a031690565b600083815260208190526040812054849033600160a060020a039081169116146101f257600080fd5b8484604051918252602082015260409081019051908190039020915083857fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8285604051600160a060020a03909116815260200160405180910390a3506000908152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790555050565b600082815260208190526040902054829033600160a060020a039081169116146102b457600080fd5b827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa688360405167ffffffffffffffff909116815260200160405180910390a250600091825260208290526040909120600101805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60009081526020819052604090206001015474010000000000000000000000000000000000000000900467ffffffffffffffff1690565b600082815260208190526040902054829033600160a060020a039081169116146103b757600080fd5b827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120600101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055565b600082815260208190526040902054829033600160a060020a0390811691161461045d57600080fd5b827fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26683604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555600a165627a7a7230582087c335a130f7bd19015451f7e1dc0e44cdeb5b64393f51a105ee00160711fcff0029`
|
||||
const ENSBin = `0x6060604052341561000f57600080fd5b60008080526020527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb58054600160a060020a033316600160a060020a0319909116179055610503806100626000396000f3006060604052600436106100825763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630178b8bf811461008757806302571be3146100b957806306ab5923146100cf57806314ab9038146100f657806316a25cbd146101195780631896f70a1461014c5780635b0fc9c31461016e575b600080fd5b341561009257600080fd5b61009d600435610190565b604051600160a060020a03909116815260200160405180910390f35b34156100c457600080fd5b61009d6004356101ae565b34156100da57600080fd5b6100f4600435602435600160a060020a03604435166101c9565b005b341561010157600080fd5b6100f460043567ffffffffffffffff6024351661028b565b341561012457600080fd5b61012f600435610357565b60405167ffffffffffffffff909116815260200160405180910390f35b341561015757600080fd5b6100f4600435600160a060020a036024351661038e565b341561017957600080fd5b6100f4600435600160a060020a0360243516610434565b600090815260208190526040902060010154600160a060020a031690565b600090815260208190526040902054600160a060020a031690565b600083815260208190526040812054849033600160a060020a039081169116146101f257600080fd5b8484604051918252602082015260409081019051908190039020915083857fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8285604051600160a060020a03909116815260200160405180910390a3506000908152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03929092169190911790555050565b600082815260208190526040902054829033600160a060020a039081169116146102b457600080fd5b827f1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa688360405167ffffffffffffffff909116815260200160405180910390a250600091825260208290526040909120600101805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b60009081526020819052604090206001015474010000000000000000000000000000000000000000900467ffffffffffffffff1690565b600082815260208190526040902054829033600160a060020a039081169116146103b757600080fd5b827f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a083604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120600101805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03909216919091179055565b600082815260208190526040902054829033600160a060020a0390811691161461045d57600080fd5b827fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d26683604051600160a060020a03909116815260200160405180910390a250600091825260208290526040909120805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555600a165627a7a72305820f4c798d4c84c9912f389f64631e85e8d16c3e6644f8c2e1579936015c7d5f6660029`
|
||||
|
||||
// DeployENS deploys a new Ethereum contract, binding an instance of ENS to it.
|
||||
func DeployENS(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *ENS, error) {
|
||||
@ -28,13 +30,14 @@ func DeployENS(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Ad
|
||||
if err != nil {
|
||||
return common.Address{}, nil, nil, err
|
||||
}
|
||||
return address, tx, &ENS{ENSCaller: ENSCaller{contract: contract}, ENSTransactor: ENSTransactor{contract: contract}}, nil
|
||||
return address, tx, &ENS{ENSCaller: ENSCaller{contract: contract}, ENSTransactor: ENSTransactor{contract: contract}, ENSFilterer: ENSFilterer{contract: contract}}, nil
|
||||
}
|
||||
|
||||
// ENS is an auto generated Go binding around an Ethereum contract.
|
||||
type ENS struct {
|
||||
ENSCaller // Read-only binding to the contract
|
||||
ENSTransactor // Write-only binding to the contract
|
||||
ENSFilterer // Log filterer for contract events
|
||||
}
|
||||
|
||||
// ENSCaller is an auto generated read-only Go binding around an Ethereum contract.
|
||||
@ -47,6 +50,11 @@ type ENSTransactor struct {
|
||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||
}
|
||||
|
||||
// ENSFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
|
||||
type ENSFilterer struct {
|
||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||
}
|
||||
|
||||
// ENSSession is an auto generated Go binding around an Ethereum contract,
|
||||
// with pre-set call and transact options.
|
||||
type ENSSession struct {
|
||||
@ -86,16 +94,16 @@ type ENSTransactorRaw struct {
|
||||
|
||||
// NewENS creates a new instance of ENS, bound to a specific deployed contract.
|
||||
func NewENS(address common.Address, backend bind.ContractBackend) (*ENS, error) {
|
||||
contract, err := bindENS(address, backend, backend)
|
||||
contract, err := bindENS(address, backend, backend, backend)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ENS{ENSCaller: ENSCaller{contract: contract}, ENSTransactor: ENSTransactor{contract: contract}}, nil
|
||||
return &ENS{ENSCaller: ENSCaller{contract: contract}, ENSTransactor: ENSTransactor{contract: contract}, ENSFilterer: ENSFilterer{contract: contract}}, nil
|
||||
}
|
||||
|
||||
// NewENSCaller creates a new read-only instance of ENS, bound to a specific deployed contract.
|
||||
func NewENSCaller(address common.Address, caller bind.ContractCaller) (*ENSCaller, error) {
|
||||
contract, err := bindENS(address, caller, nil)
|
||||
contract, err := bindENS(address, caller, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -104,20 +112,29 @@ func NewENSCaller(address common.Address, caller bind.ContractCaller) (*ENSCalle
|
||||
|
||||
// NewENSTransactor creates a new write-only instance of ENS, bound to a specific deployed contract.
|
||||
func NewENSTransactor(address common.Address, transactor bind.ContractTransactor) (*ENSTransactor, error) {
|
||||
contract, err := bindENS(address, nil, transactor)
|
||||
contract, err := bindENS(address, nil, transactor, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ENSTransactor{contract: contract}, nil
|
||||
}
|
||||
|
||||
// NewENSFilterer creates a new log filterer instance of ENS, bound to a specific deployed contract.
|
||||
func NewENSFilterer(address common.Address, filterer bind.ContractFilterer) (*ENSFilterer, error) {
|
||||
contract, err := bindENS(address, nil, nil, filterer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ENSFilterer{contract: contract}, nil
|
||||
}
|
||||
|
||||
// bindENS binds a generic wrapper to an already deployed contract.
|
||||
func bindENS(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
|
||||
func bindENS(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
|
||||
parsed, err := abi.JSON(strings.NewReader(ENSABI))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bind.NewBoundContract(address, parsed, caller, transactor), nil
|
||||
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
|
||||
}
|
||||
|
||||
// Call invokes the (constant) contract method with params as input values and
|
||||
@ -319,3 +336,544 @@ func (_ENS *ENSSession) SetTTL(node [32]byte, ttl uint64) (*types.Transaction, e
|
||||
func (_ENS *ENSTransactorSession) SetTTL(node [32]byte, ttl uint64) (*types.Transaction, error) {
|
||||
return _ENS.Contract.SetTTL(&_ENS.TransactOpts, node, ttl)
|
||||
}
|
||||
|
||||
// ENSNewOwnerIterator is returned from FilterNewOwner and is used to iterate over the raw logs and unpacked data for NewOwner events raised by the ENS contract.
|
||||
type ENSNewOwnerIterator struct {
|
||||
Event *ENSNewOwner // Event containing the contract specifics and raw log
|
||||
|
||||
contract *bind.BoundContract // Generic contract to use for unpacking event data
|
||||
event string // Event name to use for unpacking event data
|
||||
|
||||
logs chan types.Log // Log channel receiving the found contract events
|
||||
sub ethereum.Subscription // Subscription for errors, completion and termination
|
||||
done bool // Whether the subscription completed delivering logs
|
||||
fail error // Occurred error to stop iteration
|
||||
}
|
||||
|
||||
// Next advances the iterator to the subsequent event, returning whether there
|
||||
// are any more events found. In case of a retrieval or parsing error, false is
|
||||
// returned and Error() can be queried for the exact failure.
|
||||
func (it *ENSNewOwnerIterator) Next() bool {
|
||||
// If the iterator failed, stop iterating
|
||||
if it.fail != nil {
|
||||
return false
|
||||
}
|
||||
// If the iterator completed, deliver directly whatever's available
|
||||
if it.done {
|
||||
select {
|
||||
case log := <-it.logs:
|
||||
it.Event = new(ENSNewOwner)
|
||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||
it.fail = err
|
||||
return false
|
||||
}
|
||||
it.Event.Raw = log
|
||||
return true
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
// Iterator still in progress, wait for either a data or an error event
|
||||
select {
|
||||
case log := <-it.logs:
|
||||
it.Event = new(ENSNewOwner)
|
||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||
it.fail = err
|
||||
return false
|
||||
}
|
||||
it.Event.Raw = log
|
||||
return true
|
||||
|
||||
case err := <-it.sub.Err():
|
||||
it.done = true
|
||||
it.fail = err
|
||||
return it.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// Error retruned any retrieval or parsing error occurred during filtering.
|
||||
func (it *ENSNewOwnerIterator) Error() error {
|
||||
return it.fail
|
||||
}
|
||||
|
||||
// Close terminates the iteration process, releasing any pending underlying
|
||||
// resources.
|
||||
func (it *ENSNewOwnerIterator) Close() error {
|
||||
it.sub.Unsubscribe()
|
||||
return nil
|
||||
}
|
||||
|
||||
// ENSNewOwner represents a NewOwner event raised by the ENS contract.
|
||||
type ENSNewOwner struct {
|
||||
Node [32]byte
|
||||
Label [32]byte
|
||||
Owner common.Address
|
||||
Raw types.Log // Blockchain specific contextual infos
|
||||
}
|
||||
|
||||
// FilterNewOwner is a free log retrieval operation binding the contract event 0xce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e82.
|
||||
//
|
||||
// Solidity: event NewOwner(node indexed bytes32, label indexed bytes32, owner address)
|
||||
func (_ENS *ENSFilterer) FilterNewOwner(opts *bind.FilterOpts, node [][32]byte, label [][32]byte) (*ENSNewOwnerIterator, error) {
|
||||
|
||||
var nodeRule []interface{}
|
||||
for _, nodeItem := range node {
|
||||
nodeRule = append(nodeRule, nodeItem)
|
||||
}
|
||||
var labelRule []interface{}
|
||||
for _, labelItem := range label {
|
||||
labelRule = append(labelRule, labelItem)
|
||||
}
|
||||
|
||||
logs, sub, err := _ENS.contract.FilterLogs(opts, "NewOwner", nodeRule, labelRule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ENSNewOwnerIterator{contract: _ENS.contract, event: "NewOwner", logs: logs, sub: sub}, nil
|
||||
}
|
||||
|
||||
// WatchNewOwner is a free log subscription operation binding the contract event 0xce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e82.
|
||||
//
|
||||
// Solidity: event NewOwner(node indexed bytes32, label indexed bytes32, owner address)
|
||||
func (_ENS *ENSFilterer) WatchNewOwner(opts *bind.WatchOpts, sink chan<- *ENSNewOwner, node [][32]byte, label [][32]byte) (event.Subscription, error) {
|
||||
|
||||
var nodeRule []interface{}
|
||||
for _, nodeItem := range node {
|
||||
nodeRule = append(nodeRule, nodeItem)
|
||||
}
|
||||
var labelRule []interface{}
|
||||
for _, labelItem := range label {
|
||||
labelRule = append(labelRule, labelItem)
|
||||
}
|
||||
|
||||
logs, sub, err := _ENS.contract.WatchLogs(opts, "NewOwner", nodeRule, labelRule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return event.NewSubscription(func(quit <-chan struct{}) error {
|
||||
defer sub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case log := <-logs:
|
||||
// New log arrived, parse the event and forward to the user
|
||||
event := new(ENSNewOwner)
|
||||
if err := _ENS.contract.UnpackLog(event, "NewOwner", log); err != nil {
|
||||
return err
|
||||
}
|
||||
event.Raw = log
|
||||
|
||||
select {
|
||||
case sink <- event:
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
return nil
|
||||
}
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
// ENSNewResolverIterator is returned from FilterNewResolver and is used to iterate over the raw logs and unpacked data for NewResolver events raised by the ENS contract.
|
||||
type ENSNewResolverIterator struct {
|
||||
Event *ENSNewResolver // Event containing the contract specifics and raw log
|
||||
|
||||
contract *bind.BoundContract // Generic contract to use for unpacking event data
|
||||
event string // Event name to use for unpacking event data
|
||||
|
||||
logs chan types.Log // Log channel receiving the found contract events
|
||||
sub ethereum.Subscription // Subscription for errors, completion and termination
|
||||
done bool // Whether the subscription completed delivering logs
|
||||
fail error // Occurred error to stop iteration
|
||||
}
|
||||
|
||||
// Next advances the iterator to the subsequent event, returning whether there
|
||||
// are any more events found. In case of a retrieval or parsing error, false is
|
||||
// returned and Error() can be queried for the exact failure.
|
||||
func (it *ENSNewResolverIterator) Next() bool {
|
||||
// If the iterator failed, stop iterating
|
||||
if it.fail != nil {
|
||||
return false
|
||||
}
|
||||
// If the iterator completed, deliver directly whatever's available
|
||||
if it.done {
|
||||
select {
|
||||
case log := <-it.logs:
|
||||
it.Event = new(ENSNewResolver)
|
||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||
it.fail = err
|
||||
return false
|
||||
}
|
||||
it.Event.Raw = log
|
||||
return true
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
// Iterator still in progress, wait for either a data or an error event
|
||||
select {
|
||||
case log := <-it.logs:
|
||||
it.Event = new(ENSNewResolver)
|
||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||
it.fail = err
|
||||
return false
|
||||
}
|
||||
it.Event.Raw = log
|
||||
return true
|
||||
|
||||
case err := <-it.sub.Err():
|
||||
it.done = true
|
||||
it.fail = err
|
||||
return it.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// Error retruned any retrieval or parsing error occurred during filtering.
|
||||
func (it *ENSNewResolverIterator) Error() error {
|
||||
return it.fail
|
||||
}
|
||||
|
||||
// Close terminates the iteration process, releasing any pending underlying
|
||||
// resources.
|
||||
func (it *ENSNewResolverIterator) Close() error {
|
||||
it.sub.Unsubscribe()
|
||||
return nil
|
||||
}
|
||||
|
||||
// ENSNewResolver represents a NewResolver event raised by the ENS contract.
|
||||
type ENSNewResolver struct {
|
||||
Node [32]byte
|
||||
Resolver common.Address
|
||||
Raw types.Log // Blockchain specific contextual infos
|
||||
}
|
||||
|
||||
// FilterNewResolver is a free log retrieval operation binding the contract event 0x335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0.
|
||||
//
|
||||
// Solidity: event NewResolver(node indexed bytes32, resolver address)
|
||||
func (_ENS *ENSFilterer) FilterNewResolver(opts *bind.FilterOpts, node [][32]byte) (*ENSNewResolverIterator, error) {
|
||||
|
||||
var nodeRule []interface{}
|
||||
for _, nodeItem := range node {
|
||||
nodeRule = append(nodeRule, nodeItem)
|
||||
}
|
||||
|
||||
logs, sub, err := _ENS.contract.FilterLogs(opts, "NewResolver", nodeRule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ENSNewResolverIterator{contract: _ENS.contract, event: "NewResolver", logs: logs, sub: sub}, nil
|
||||
}
|
||||
|
||||
// WatchNewResolver is a free log subscription operation binding the contract event 0x335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0.
|
||||
//
|
||||
// Solidity: event NewResolver(node indexed bytes32, resolver address)
|
||||
func (_ENS *ENSFilterer) WatchNewResolver(opts *bind.WatchOpts, sink chan<- *ENSNewResolver, node [][32]byte) (event.Subscription, error) {
|
||||
|
||||
var nodeRule []interface{}
|
||||
for _, nodeItem := range node {
|
||||
nodeRule = append(nodeRule, nodeItem)
|
||||
}
|
||||
|
||||
logs, sub, err := _ENS.contract.WatchLogs(opts, "NewResolver", nodeRule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return event.NewSubscription(func(quit <-chan struct{}) error {
|
||||
defer sub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case log := <-logs:
|
||||
// New log arrived, parse the event and forward to the user
|
||||
event := new(ENSNewResolver)
|
||||
if err := _ENS.contract.UnpackLog(event, "NewResolver", log); err != nil {
|
||||
return err
|
||||
}
|
||||
event.Raw = log
|
||||
|
||||
select {
|
||||
case sink <- event:
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
return nil
|
||||
}
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
// ENSNewTTLIterator is returned from FilterNewTTL and is used to iterate over the raw logs and unpacked data for NewTTL events raised by the ENS contract.
|
||||
type ENSNewTTLIterator struct {
|
||||
Event *ENSNewTTL // Event containing the contract specifics and raw log
|
||||
|
||||
contract *bind.BoundContract // Generic contract to use for unpacking event data
|
||||
event string // Event name to use for unpacking event data
|
||||
|
||||
logs chan types.Log // Log channel receiving the found contract events
|
||||
sub ethereum.Subscription // Subscription for errors, completion and termination
|
||||
done bool // Whether the subscription completed delivering logs
|
||||
fail error // Occurred error to stop iteration
|
||||
}
|
||||
|
||||
// Next advances the iterator to the subsequent event, returning whether there
|
||||
// are any more events found. In case of a retrieval or parsing error, false is
|
||||
// returned and Error() can be queried for the exact failure.
|
||||
func (it *ENSNewTTLIterator) Next() bool {
|
||||
// If the iterator failed, stop iterating
|
||||
if it.fail != nil {
|
||||
return false
|
||||
}
|
||||
// If the iterator completed, deliver directly whatever's available
|
||||
if it.done {
|
||||
select {
|
||||
case log := <-it.logs:
|
||||
it.Event = new(ENSNewTTL)
|
||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||
it.fail = err
|
||||
return false
|
||||
}
|
||||
it.Event.Raw = log
|
||||
return true
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
// Iterator still in progress, wait for either a data or an error event
|
||||
select {
|
||||
case log := <-it.logs:
|
||||
it.Event = new(ENSNewTTL)
|
||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||
it.fail = err
|
||||
return false
|
||||
}
|
||||
it.Event.Raw = log
|
||||
return true
|
||||
|
||||
case err := <-it.sub.Err():
|
||||
it.done = true
|
||||
it.fail = err
|
||||
return it.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// Error retruned any retrieval or parsing error occurred during filtering.
|
||||
func (it *ENSNewTTLIterator) Error() error {
|
||||
return it.fail
|
||||
}
|
||||
|
||||
// Close terminates the iteration process, releasing any pending underlying
|
||||
// resources.
|
||||
func (it *ENSNewTTLIterator) Close() error {
|
||||
it.sub.Unsubscribe()
|
||||
return nil
|
||||
}
|
||||
|
||||
// ENSNewTTL represents a NewTTL event raised by the ENS contract.
|
||||
type ENSNewTTL struct {
|
||||
Node [32]byte
|
||||
Ttl uint64
|
||||
Raw types.Log // Blockchain specific contextual infos
|
||||
}
|
||||
|
||||
// FilterNewTTL is a free log retrieval operation binding the contract event 0x1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68.
|
||||
//
|
||||
// Solidity: event NewTTL(node indexed bytes32, ttl uint64)
|
||||
func (_ENS *ENSFilterer) FilterNewTTL(opts *bind.FilterOpts, node [][32]byte) (*ENSNewTTLIterator, error) {
|
||||
|
||||
var nodeRule []interface{}
|
||||
for _, nodeItem := range node {
|
||||
nodeRule = append(nodeRule, nodeItem)
|
||||
}
|
||||
|
||||
logs, sub, err := _ENS.contract.FilterLogs(opts, "NewTTL", nodeRule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ENSNewTTLIterator{contract: _ENS.contract, event: "NewTTL", logs: logs, sub: sub}, nil
|
||||
}
|
||||
|
||||
// WatchNewTTL is a free log subscription operation binding the contract event 0x1d4f9bbfc9cab89d66e1a1562f2233ccbf1308cb4f63de2ead5787adddb8fa68.
|
||||
//
|
||||
// Solidity: event NewTTL(node indexed bytes32, ttl uint64)
|
||||
func (_ENS *ENSFilterer) WatchNewTTL(opts *bind.WatchOpts, sink chan<- *ENSNewTTL, node [][32]byte) (event.Subscription, error) {
|
||||
|
||||
var nodeRule []interface{}
|
||||
for _, nodeItem := range node {
|
||||
nodeRule = append(nodeRule, nodeItem)
|
||||
}
|
||||
|
||||
logs, sub, err := _ENS.contract.WatchLogs(opts, "NewTTL", nodeRule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return event.NewSubscription(func(quit <-chan struct{}) error {
|
||||
defer sub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case log := <-logs:
|
||||
// New log arrived, parse the event and forward to the user
|
||||
event := new(ENSNewTTL)
|
||||
if err := _ENS.contract.UnpackLog(event, "NewTTL", log); err != nil {
|
||||
return err
|
||||
}
|
||||
event.Raw = log
|
||||
|
||||
select {
|
||||
case sink <- event:
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
return nil
|
||||
}
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
||||
// ENSTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the ENS contract.
|
||||
type ENSTransferIterator struct {
|
||||
Event *ENSTransfer // Event containing the contract specifics and raw log
|
||||
|
||||
contract *bind.BoundContract // Generic contract to use for unpacking event data
|
||||
event string // Event name to use for unpacking event data
|
||||
|
||||
logs chan types.Log // Log channel receiving the found contract events
|
||||
sub ethereum.Subscription // Subscription for errors, completion and termination
|
||||
done bool // Whether the subscription completed delivering logs
|
||||
fail error // Occurred error to stop iteration
|
||||
}
|
||||
|
||||
// Next advances the iterator to the subsequent event, returning whether there
|
||||
// are any more events found. In case of a retrieval or parsing error, false is
|
||||
// returned and Error() can be queried for the exact failure.
|
||||
func (it *ENSTransferIterator) Next() bool {
|
||||
// If the iterator failed, stop iterating
|
||||
if it.fail != nil {
|
||||
return false
|
||||
}
|
||||
// If the iterator completed, deliver directly whatever's available
|
||||
if it.done {
|
||||
select {
|
||||
case log := <-it.logs:
|
||||
it.Event = new(ENSTransfer)
|
||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||
it.fail = err
|
||||
return false
|
||||
}
|
||||
it.Event.Raw = log
|
||||
return true
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
// Iterator still in progress, wait for either a data or an error event
|
||||
select {
|
||||
case log := <-it.logs:
|
||||
it.Event = new(ENSTransfer)
|
||||
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
|
||||
it.fail = err
|
||||
return false
|
||||
}
|
||||
it.Event.Raw = log
|
||||
return true
|
||||
|
||||
case err := <-it.sub.Err():
|
||||
it.done = true
|
||||
it.fail = err
|
||||
return it.Next()
|
||||
}
|
||||
}
|
||||
|
||||
// Error retruned any retrieval or parsing error occurred during filtering.
|
||||
func (it *ENSTransferIterator) Error() error {
|
||||
return it.fail
|
||||
}
|
||||
|
||||
// Close terminates the iteration process, releasing any pending underlying
|
||||
// resources.
|
||||
func (it *ENSTransferIterator) Close() error {
|
||||
it.sub.Unsubscribe()
|
||||
return nil
|
||||
}
|
||||
|
||||
// ENSTransfer represents a Transfer event raised by the ENS contract.
|
||||
type ENSTransfer struct {
|
||||
Node [32]byte
|
||||
Owner common.Address
|
||||
Raw types.Log // Blockchain specific contextual infos
|
||||
}
|
||||
|
||||
// FilterTransfer is a free log retrieval operation binding the contract event 0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266.
|
||||
//
|
||||
// Solidity: event Transfer(node indexed bytes32, owner address)
|
||||
func (_ENS *ENSFilterer) FilterTransfer(opts *bind.FilterOpts, node [][32]byte) (*ENSTransferIterator, error) {
|
||||
|
||||
var nodeRule []interface{}
|
||||
for _, nodeItem := range node {
|
||||
nodeRule = append(nodeRule, nodeItem)
|
||||
}
|
||||
|
||||
logs, sub, err := _ENS.contract.FilterLogs(opts, "Transfer", nodeRule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ENSTransferIterator{contract: _ENS.contract, event: "Transfer", logs: logs, sub: sub}, nil
|
||||
}
|
||||
|
||||
// WatchTransfer is a free log subscription operation binding the contract event 0xd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266.
|
||||
//
|
||||
// Solidity: event Transfer(node indexed bytes32, owner address)
|
||||
func (_ENS *ENSFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *ENSTransfer, node [][32]byte) (event.Subscription, error) {
|
||||
|
||||
var nodeRule []interface{}
|
||||
for _, nodeItem := range node {
|
||||
nodeRule = append(nodeRule, nodeItem)
|
||||
}
|
||||
|
||||
logs, sub, err := _ENS.contract.WatchLogs(opts, "Transfer", nodeRule)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return event.NewSubscription(func(quit <-chan struct{}) error {
|
||||
defer sub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case log := <-logs:
|
||||
// New log arrived, parse the event and forward to the user
|
||||
event := new(ENSTransfer)
|
||||
if err := _ENS.contract.UnpackLog(event, "Transfer", log); err != nil {
|
||||
return err
|
||||
}
|
||||
event.Raw = log
|
||||
|
||||
select {
|
||||
case sink <- event:
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
return nil
|
||||
}
|
||||
case err := <-sub.Err():
|
||||
return err
|
||||
case <-quit:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}), nil
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ import (
|
||||
const FIFSRegistrarABI = "[{\"constant\":false,\"inputs\":[{\"name\":\"subnode\",\"type\":\"bytes32\"},{\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"register\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"ensAddr\",\"type\":\"address\"},{\"name\":\"node\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"}]"
|
||||
|
||||
// FIFSRegistrarBin is the compiled bytecode used for deploying new contracts.
|
||||
const FIFSRegistrarBin = `0x6060604052341561000f57600080fd5b604051604080610224833981016040528080519190602001805160008054600160a060020a03909516600160a060020a03199095169490941790935550506001556101c58061005f6000396000f3006060604052600436106100275763ffffffff60e060020a600035041663d22057a9811461002c575b600080fd5b341561003757600080fd5b61004e600435600160a060020a0360243516610050565b005b816000806001548360405191825260208201526040908101905190819003902060008054919350600160a060020a03909116906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156100c857600080fd5b6102c65a03f115156100d957600080fd5b5050506040518051915050600160a060020a0381161580159061010e575033600160a060020a031681600160a060020a031614155b1561011857600080fd5b600054600154600160a060020a03909116906306ab592390878760405160e060020a63ffffffff861602815260048101939093526024830191909152600160a060020a03166044820152606401600060405180830381600087803b151561017e57600080fd5b6102c65a03f1151561018f57600080fd5b50505050505050505600a165627a7a723058209b0c0f4ed76e4fe49a71d4b838ab3d00d6bad29021172db7ced9f36abcafbf510029`
|
||||
const FIFSRegistrarBin = `0x6060604052341561000f57600080fd5b604051604080610224833981016040528080519190602001805160008054600160a060020a03909516600160a060020a03199095169490941790935550506001556101c58061005f6000396000f3006060604052600436106100275763ffffffff60e060020a600035041663d22057a9811461002c575b600080fd5b341561003757600080fd5b61004e600435600160a060020a0360243516610050565b005b816000806001548360405191825260208201526040908101905190819003902060008054919350600160a060020a03909116906302571be39084906040516020015260405160e060020a63ffffffff84160281526004810191909152602401602060405180830381600087803b15156100c857600080fd5b6102c65a03f115156100d957600080fd5b5050506040518051915050600160a060020a0381161580159061010e575033600160a060020a031681600160a060020a031614155b1561011857600080fd5b600054600154600160a060020a03909116906306ab592390878760405160e060020a63ffffffff861602815260048101939093526024830191909152600160a060020a03166044820152606401600060405180830381600087803b151561017e57600080fd5b6102c65a03f1151561018f57600080fd5b50505050505050505600a165627a7a723058206fb963cb168d5e3a51af12cd6bb23e324dbd32dd4954f43653ba27e66b68ea650029`
|
||||
|
||||
// DeployFIFSRegistrar deploys a new Ethereum contract, binding an instance of FIFSRegistrar to it.
|
||||
func DeployFIFSRegistrar(auth *bind.TransactOpts, backend bind.ContractBackend, ensAddr common.Address, node [32]byte) (common.Address, *types.Transaction, *FIFSRegistrar, error) {
|
||||
@ -28,13 +28,14 @@ func DeployFIFSRegistrar(auth *bind.TransactOpts, backend bind.ContractBackend,
|
||||
if err != nil {
|
||||
return common.Address{}, nil, nil, err
|
||||
}
|
||||
return address, tx, &FIFSRegistrar{FIFSRegistrarCaller: FIFSRegistrarCaller{contract: contract}, FIFSRegistrarTransactor: FIFSRegistrarTransactor{contract: contract}}, nil
|
||||
return address, tx, &FIFSRegistrar{FIFSRegistrarCaller: FIFSRegistrarCaller{contract: contract}, FIFSRegistrarTransactor: FIFSRegistrarTransactor{contract: contract}, FIFSRegistrarFilterer: FIFSRegistrarFilterer{contract: contract}}, nil
|
||||
}
|
||||
|
||||
// FIFSRegistrar is an auto generated Go binding around an Ethereum contract.
|
||||
type FIFSRegistrar struct {
|
||||
FIFSRegistrarCaller // Read-only binding to the contract
|
||||
FIFSRegistrarTransactor // Write-only binding to the contract
|
||||
FIFSRegistrarFilterer // Log filterer for contract events
|
||||
}
|
||||
|
||||
// FIFSRegistrarCaller is an auto generated read-only Go binding around an Ethereum contract.
|
||||
@ -47,6 +48,11 @@ type FIFSRegistrarTransactor struct {
|
||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||
}
|
||||
|
||||
// FIFSRegistrarFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
|
||||
type FIFSRegistrarFilterer struct {
|
||||
contract *bind.BoundContract // Generic contract wrapper for the low level calls
|
||||
}
|
||||
|
||||
// FIFSRegistrarSession is an auto generated Go binding around an Ethereum contract,
|
||||
// with pre-set call and transact options.
|
||||
type FIFSRegistrarSession struct {
|
||||
@ -86,16 +92,16 @@ type FIFSRegistrarTransactorRaw struct {
|
||||
|
||||
// NewFIFSRegistrar creates a new instance of FIFSRegistrar, bound to a specific deployed contract.
|
||||
func NewFIFSRegistrar(address common.Address, backend bind.ContractBackend) (*FIFSRegistrar, error) {
|
||||
contract, err := bindFIFSRegistrar(address, backend, backend)
|
||||
contract, err := bindFIFSRegistrar(address, backend, backend, backend)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &FIFSRegistrar{FIFSRegistrarCaller: FIFSRegistrarCaller{contract: contract}, FIFSRegistrarTransactor: FIFSRegistrarTransactor{contract: contract}}, nil
|
||||
return &FIFSRegistrar{FIFSRegistrarCaller: FIFSRegistrarCaller{contract: contract}, FIFSRegistrarTransactor: FIFSRegistrarTransactor{contract: contract}, FIFSRegistrarFilterer: FIFSRegistrarFilterer{contract: contract}}, nil
|
||||
}
|
||||
|
||||
// NewFIFSRegistrarCaller creates a new read-only instance of FIFSRegistrar, bound to a specific deployed contract.
|
||||
func NewFIFSRegistrarCaller(address common.Address, caller bind.ContractCaller) (*FIFSRegistrarCaller, error) {
|
||||
contract, err := bindFIFSRegistrar(address, caller, nil)
|
||||
contract, err := bindFIFSRegistrar(address, caller, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -104,20 +110,29 @@ func NewFIFSRegistrarCaller(address common.Address, caller bind.ContractCaller)
|
||||
|
||||
// NewFIFSRegistrarTransactor creates a new write-only instance of FIFSRegistrar, bound to a specific deployed contract.
|
||||
func NewFIFSRegistrarTransactor(address common.Address, transactor bind.ContractTransactor) (*FIFSRegistrarTransactor, error) {
|
||||
contract, err := bindFIFSRegistrar(address, nil, transactor)
|
||||
contract, err := bindFIFSRegistrar(address, nil, transactor, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &FIFSRegistrarTransactor{contract: contract}, nil
|
||||
}
|
||||
|
||||
// NewFIFSRegistrarFilterer creates a new log filterer instance of FIFSRegistrar, bound to a specific deployed contract.
|
||||
func NewFIFSRegistrarFilterer(address common.Address, filterer bind.ContractFilterer) (*FIFSRegistrarFilterer, error) {
|
||||
contract, err := bindFIFSRegistrar(address, nil, nil, filterer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &FIFSRegistrarFilterer{contract: contract}, nil
|
||||
}
|
||||
|
||||
// bindFIFSRegistrar binds a generic wrapper to an already deployed contract.
|
||||
func bindFIFSRegistrar(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
|
||||
func bindFIFSRegistrar(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
|
||||
parsed, err := abi.JSON(strings.NewReader(FIFSRegistrarABI))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bind.NewBoundContract(address, parsed, caller, transactor), nil
|
||||
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
|
||||
}
|
||||
|
||||
// Call invokes the (constant) contract method with params as input values and
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -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/>.
|
||||
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
// ReleaseOracle is an Ethereum contract to store the current and previous
|
||||
// versions of the go-ethereum implementation. Its goal is to allow Geth to
|
||||
// check for new releases automatically without the need to consult a central
|
||||
// repository.
|
||||
//
|
||||
// The contract takes a vote based approach on both assigning authorised signers
|
||||
// as well as signing off on new Geth releases.
|
||||
//
|
||||
// Note, when a signer is demoted, the currently pending release is auto-nuked.
|
||||
// The reason is to prevent suprises where a demotion actually tilts the votes
|
||||
// in favor of one voter party and pushing out a new release as a consequence of
|
||||
// a simple demotion.
|
||||
contract ReleaseOracle {
|
||||
// Votes is an internal data structure to count votes on a specific proposal
|
||||
struct Votes {
|
||||
address[] pass; // List of signers voting to pass a proposal
|
||||
address[] fail; // List of signers voting to fail a proposal
|
||||
}
|
||||
|
||||
// Version is the version details of a particular Geth release
|
||||
struct Version {
|
||||
uint32 major; // Major version component of the release
|
||||
uint32 minor; // Minor version component of the release
|
||||
uint32 patch; // Patch version component of the release
|
||||
bytes20 commit; // Git SHA1 commit hash of the release
|
||||
|
||||
uint64 time; // Timestamp of the release approval
|
||||
Votes votes; // Votes that passed this release
|
||||
}
|
||||
|
||||
// Oracle authorization details
|
||||
mapping(address => bool) authorised; // 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
|
||||
address[] authPend; // List of addresses being voted on (map indexes)
|
||||
|
||||
Version verProp; // Currently proposed release being voted on
|
||||
Version[] releases; // All the positively voted releases
|
||||
|
||||
// isSigner is a modifier to authorize contract transactions.
|
||||
modifier isSigner() {
|
||||
if (authorised[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]);
|
||||
}
|
||||
}
|
||||
|
||||
// signers is an accessor method to retrieve all the signers (public accessor
|
||||
// generates an indexed one, not a retrieve-all version).
|
||||
function signers() constant returns(address[]) {
|
||||
return voters;
|
||||
}
|
||||
|
||||
// authProposals retrieves the list of addresses that authorization proposals
|
||||
// are currently being voted on.
|
||||
function authProposals() constant returns(address[]) {
|
||||
return authPend;
|
||||
}
|
||||
|
||||
// authVotes retrieves the current authorization votes for a particular user
|
||||
// to promote him into the list of signers, or demote him from there.
|
||||
function authVotes(address user) constant returns(address[] promote, address[] demote) {
|
||||
return (authProps[user].pass, authProps[user].fail);
|
||||
}
|
||||
|
||||
// currentVersion retrieves the semantic version, commit hash and release time
|
||||
// of the currently votec active release.
|
||||
function currentVersion() constant returns (uint32 major, uint32 minor, uint32 patch, bytes20 commit, uint time) {
|
||||
if (releases.length == 0) {
|
||||
return (0, 0, 0, 0, 0);
|
||||
}
|
||||
var release = releases[releases.length - 1];
|
||||
|
||||
return (release.major, release.minor, release.patch, release.commit, release.time);
|
||||
}
|
||||
|
||||
// proposedVersion retrieves the semantic version, commit hash and the current
|
||||
// votes for the next proposed release.
|
||||
function proposedVersion() 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);
|
||||
}
|
||||
|
||||
// promote pitches in on a voting campaign to promote a new user to a signer
|
||||
// position.
|
||||
function promote(address user) {
|
||||
updateSigner(user, true);
|
||||
}
|
||||
|
||||
// demote pitches in on a voting campaign to demote an authorised user from
|
||||
// its signer position.
|
||||
function demote(address user) {
|
||||
updateSigner(user, false);
|
||||
}
|
||||
|
||||
// release votes for a particular version to be included as the next release.
|
||||
function release(uint32 major, uint32 minor, uint32 patch, bytes20 commit) {
|
||||
updateRelease(major, minor, patch, commit, true);
|
||||
}
|
||||
|
||||
// nuke 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 nuke() {
|
||||
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 authorised signer.
|
||||
function updateSigner(address user, bool authorize) internal isSigner {
|
||||
// Gather the current votes and ensure we don't double vote
|
||||
Votes votes = authProps[user];
|
||||
for (uint i = 0; i < votes.pass.length; i++) {
|
||||
if (votes.pass[i] == msg.sender) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < votes.fail.length; i++) {
|
||||
if (votes.fail[i] == msg.sender) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If no authorization proposal is open, add the user to the index for later lookups
|
||||
if (votes.pass.length == 0 && votes.fail.length == 0) {
|
||||
authPend.push(user);
|
||||
}
|
||||
// Cast the vote and return if the proposal cannot be resolved yet
|
||||
if (authorize) {
|
||||
votes.pass.push(msg.sender);
|
||||
if (votes.pass.length <= voters.length / 2) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
votes.fail.push(msg.sender);
|
||||
if (votes.fail.length <= voters.length / 2) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Proposal resolved in our favor, execute whatever we voted on
|
||||
if (authorize && !authorised[user]) {
|
||||
authorised[user] = true;
|
||||
voters.push(user);
|
||||
} else if (!authorize && authorised[user]) {
|
||||
authorised[user] = false;
|
||||
|
||||
for (i = 0; i < voters.length; i++) {
|
||||
if (voters[i] == user) {
|
||||
voters[i] = voters[voters.length - 1];
|
||||
voters.length--;
|
||||
|
||||
delete verProp; // Nuke any version proposal (no surprise releases!)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Finally delete the resolved proposal, index and garbage collect
|
||||
delete authProps[user];
|
||||
|
||||
for (i = 0; i < authPend.length; i++) {
|
||||
if (authPend[i] == user) {
|
||||
authPend[i] = authPend[authPend.length - 1];
|
||||
authPend.length--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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) internal isSigner {
|
||||
// Skip nuke votes if no proposal is pending
|
||||
if (!release && verProp.votes.pass.length == 0) {
|
||||
return;
|
||||
}
|
||||
// Mark a new release if no proposal is pending
|
||||
if (verProp.votes.pass.length == 0) {
|
||||
verProp.major = major;
|
||||
verProp.minor = minor;
|
||||
verProp.patch = patch;
|
||||
verProp.commit = commit;
|
||||
}
|
||||
// Make sure positive votes match the current proposal
|
||||
if (release && (verProp.major != major || verProp.minor != minor || verProp.patch != patch || verProp.commit != commit)) {
|
||||
return;
|
||||
}
|
||||
// Gather the current votes and ensure we don't double vote
|
||||
Votes votes = verProp.votes;
|
||||
for (uint i = 0; i < votes.pass.length; i++) {
|
||||
if (votes.pass[i] == msg.sender) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < votes.fail.length; i++) {
|
||||
if (votes.fail[i] == msg.sender) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Cast the vote and return if the proposal cannot be resolved yet
|
||||
if (release) {
|
||||
votes.pass.push(msg.sender);
|
||||
if (votes.pass.length <= voters.length / 2) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
votes.fail.push(msg.sender);
|
||||
if (votes.fail.length <= voters.length / 2) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Proposal resolved in our favor, execute whatever we voted on
|
||||
if (release) {
|
||||
verProp.time = uint64(now);
|
||||
releases.push(verProp);
|
||||
delete verProp;
|
||||
} else {
|
||||
delete verProp;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,374 +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 release
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
// setupReleaseTest creates a blockchain simulator and deploys a version oracle
|
||||
// contract for testing.
|
||||
func setupReleaseTest(t *testing.T, prefund ...*ecdsa.PrivateKey) (*ecdsa.PrivateKey, *ReleaseOracle, *backends.SimulatedBackend) {
|
||||
// Generate a new random account and a funded simulator
|
||||
key, _ := crypto.GenerateKey()
|
||||
auth := bind.NewKeyedTransactor(key)
|
||||
|
||||
alloc := core.GenesisAlloc{auth.From: {Balance: big.NewInt(10000000000)}}
|
||||
for _, key := range prefund {
|
||||
alloc[crypto.PubkeyToAddress(key.PublicKey)] = core.GenesisAccount{Balance: big.NewInt(10000000000)}
|
||||
}
|
||||
sim := backends.NewSimulatedBackend(alloc)
|
||||
|
||||
// Deploy a version oracle contract, commit and return
|
||||
_, _, oracle, err := DeployReleaseOracle(auth, sim, []common.Address{auth.From})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to deploy version contract: %v", err)
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
return key, oracle, sim
|
||||
}
|
||||
|
||||
// Tests that the version contract can be deployed and the creator is assigned
|
||||
// the sole authorized signer.
|
||||
func TestContractCreation(t *testing.T) {
|
||||
key, oracle, _ := setupReleaseTest(t)
|
||||
|
||||
owner := crypto.PubkeyToAddress(key.PublicKey)
|
||||
signers, err := oracle.Signers(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to retrieve list of signers: %v", err)
|
||||
}
|
||||
if len(signers) != 1 || signers[0] != owner {
|
||||
t.Fatalf("Initial signer mismatch: have %v, want %v", signers, owner)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that subsequent signers can be promoted, each requiring half plus one
|
||||
// votes for it to pass through.
|
||||
func TestSignerPromotion(t *testing.T) {
|
||||
// Prefund a few accounts to authorize with and create the oracle
|
||||
keys := make([]*ecdsa.PrivateKey, 5)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
keys[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
key, oracle, sim := setupReleaseTest(t, keys...)
|
||||
|
||||
// Gradually promote the keys, until all are authorized
|
||||
keys = append([]*ecdsa.PrivateKey{key}, keys...)
|
||||
for i := 1; i < len(keys); i++ {
|
||||
// Check that no votes are accepted from the not yet authorized user
|
||||
if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[i]), common.Address{}); err != nil {
|
||||
t.Fatalf("Iter #%d: failed invalid promotion attempt: %v", i, err)
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
pend, err := oracle.AuthProposals(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Iter #%d: failed to retrieve active proposals: %v", i, err)
|
||||
}
|
||||
if len(pend) != 0 {
|
||||
t.Fatalf("Iter #%d: proposal count mismatch: have %d, want 0", i, len(pend))
|
||||
}
|
||||
// Promote with half - 1 voters and check that the user's not yet authorized
|
||||
for j := 0; j < i/2; j++ {
|
||||
if _, err = oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
|
||||
}
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
signers, err := oracle.Signers(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Iter #%d: failed to retrieve list of signers: %v", i, err)
|
||||
}
|
||||
if len(signers) != i {
|
||||
t.Fatalf("Iter #%d: signer count mismatch: have %v, want %v", i, len(signers), i)
|
||||
}
|
||||
// Promote with the last one needed to pass the promotion
|
||||
if _, err = oracle.Promote(bind.NewKeyedTransactor(keys[i/2]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid promotion completion attempt: %v", i, err)
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
signers, err = oracle.Signers(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Iter #%d: failed to retrieve list of signers: %v", i, err)
|
||||
}
|
||||
if len(signers) != i+1 {
|
||||
t.Fatalf("Iter #%d: signer count mismatch: have %v, want %v", i, len(signers), i+1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that subsequent signers can be demoted, each requiring half plus one
|
||||
// votes for it to pass through.
|
||||
func TestSignerDemotion(t *testing.T) {
|
||||
// Prefund a few accounts to authorize with and create the oracle
|
||||
keys := make([]*ecdsa.PrivateKey, 5)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
keys[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
key, oracle, sim := setupReleaseTest(t, keys...)
|
||||
|
||||
// Authorize all the keys as valid signers and verify cardinality
|
||||
keys = append([]*ecdsa.PrivateKey{key}, keys...)
|
||||
for i := 1; i < len(keys); i++ {
|
||||
for j := 0; j <= i/2; j++ {
|
||||
if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
|
||||
}
|
||||
}
|
||||
sim.Commit()
|
||||
}
|
||||
signers, err := oracle.Signers(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to retrieve list of signers: %v", err)
|
||||
}
|
||||
if len(signers) != len(keys) {
|
||||
t.Fatalf("Signer count mismatch: have %v, want %v", len(signers), len(keys))
|
||||
}
|
||||
// Gradually demote users until we run out of signers
|
||||
for i := len(keys) - 1; i >= 0; i-- {
|
||||
// Demote with half - 1 voters and check that the user's not yet dropped
|
||||
for j := 0; j < (i+1)/2; j++ {
|
||||
if _, err = oracle.Demote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid demotion attempt: %v", len(keys)-i, err)
|
||||
}
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
signers, err := oracle.Signers(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Iter #%d: failed to retrieve list of signers: %v", len(keys)-i, err)
|
||||
}
|
||||
if len(signers) != i+1 {
|
||||
t.Fatalf("Iter #%d: signer count mismatch: have %v, want %v", len(keys)-i, len(signers), i+1)
|
||||
}
|
||||
// Demote with the last one needed to pass the demotion
|
||||
if _, err = oracle.Demote(bind.NewKeyedTransactor(keys[(i+1)/2]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid demotion completion attempt: %v", i, err)
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
signers, err = oracle.Signers(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Iter #%d: failed to retrieve list of signers: %v", len(keys)-i, err)
|
||||
}
|
||||
if len(signers) != i {
|
||||
t.Fatalf("Iter #%d: signer count mismatch: have %v, want %v", len(keys)-i, len(signers), i)
|
||||
}
|
||||
// Check that no votes are accepted from the already demoted users
|
||||
if _, err = oracle.Promote(bind.NewKeyedTransactor(keys[i]), common.Address{}); err != nil {
|
||||
t.Fatalf("Iter #%d: failed invalid promotion attempt: %v", i, err)
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
pend, err := oracle.AuthProposals(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Iter #%d: failed to retrieve active proposals: %v", i, err)
|
||||
}
|
||||
if len(pend) != 0 {
|
||||
t.Fatalf("Iter #%d: proposal count mismatch: have %d, want 0", i, len(pend))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that new versions can be released, honouring both voting rights as well
|
||||
// as the minimum required vote count.
|
||||
func TestVersionRelease(t *testing.T) {
|
||||
// Prefund a few accounts to authorize with and create the oracle
|
||||
keys := make([]*ecdsa.PrivateKey, 5)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
keys[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
key, oracle, sim := setupReleaseTest(t, keys...)
|
||||
|
||||
// Track the "current release"
|
||||
var (
|
||||
verMajor = uint32(0)
|
||||
verMinor = uint32(0)
|
||||
verPatch = uint32(0)
|
||||
verCommit = [20]byte{}
|
||||
)
|
||||
// Gradually push releases, always requiring more signers than previously
|
||||
keys = append([]*ecdsa.PrivateKey{key}, keys...)
|
||||
for i := 1; i < len(keys); i++ {
|
||||
// Check that no votes are accepted from the not yet authorized user
|
||||
if _, err := oracle.Release(bind.NewKeyedTransactor(keys[i]), 0, 0, 0, [20]byte{0}); err != nil {
|
||||
t.Fatalf("Iter #%d: failed invalid release attempt: %v", i, err)
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
prop, err := oracle.ProposedVersion(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Iter #%d: failed to retrieve active proposal: %v", i, err)
|
||||
}
|
||||
if len(prop.Pass) != 0 {
|
||||
t.Fatalf("Iter #%d: proposal vote count mismatch: have %d, want 0", i, len(prop.Pass))
|
||||
}
|
||||
// Authorize the user to make releases
|
||||
for j := 0; j <= i/2; j++ {
|
||||
if _, err = oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
|
||||
}
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
// 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{byte(i + 3)}); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid release attempt: %v", i, err)
|
||||
}
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
ver, err := oracle.CurrentVersion(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Iter #%d: failed to retrieve current version: %v", i, err)
|
||||
}
|
||||
if ver.Major != verMajor || ver.Minor != verMinor || ver.Patch != verPatch || ver.Commit != verCommit {
|
||||
t.Fatalf("Iter #%d: version mismatch: have %d.%d.%d-%x, want %d.%d.%d-%x", i, ver.Major, ver.Minor, ver.Patch, ver.Commit, verMajor, verMinor, verPatch, verCommit)
|
||||
}
|
||||
|
||||
// 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{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()
|
||||
|
||||
ver, err = oracle.CurrentVersion(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Iter #%d: failed to retrieve current version: %v", i, err)
|
||||
}
|
||||
if ver.Major != verMajor || ver.Minor != verMinor || ver.Patch != verPatch || ver.Commit != verCommit {
|
||||
t.Fatalf("Iter #%d: version mismatch: have %d.%d.%d-%x, want %d.%d.%d-%x", i, ver.Major, ver.Minor, ver.Patch, ver.Commit, verMajor, verMinor, verPatch, verCommit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that proposed versions can be nuked out of existence.
|
||||
func TestVersionNuking(t *testing.T) {
|
||||
// Prefund a few accounts to authorize with and create the oracle
|
||||
keys := make([]*ecdsa.PrivateKey, 9)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
keys[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
key, oracle, sim := setupReleaseTest(t, keys...)
|
||||
|
||||
// Authorize all the keys as valid signers
|
||||
keys = append([]*ecdsa.PrivateKey{key}, keys...)
|
||||
for i := 1; i < len(keys); i++ {
|
||||
for j := 0; j <= i/2; j++ {
|
||||
if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
|
||||
}
|
||||
}
|
||||
sim.Commit()
|
||||
}
|
||||
// Propose releases with more and more keys, always retaining enough users to nuke the proposals
|
||||
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{byte(i + 3)}); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid proposal attempt: %v", i, err)
|
||||
}
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
prop, err := oracle.ProposedVersion(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Iter #%d: failed to retrieve active proposal: %v", i, err)
|
||||
}
|
||||
if len(prop.Pass) != i {
|
||||
t.Fatalf("Iter #%d: proposal vote count mismatch: have %d, want %d", i, len(prop.Pass), i)
|
||||
}
|
||||
// Nuke the release with half+1 voters
|
||||
for j := i; j <= i+(len(keys)+1)/2; j++ {
|
||||
if _, err := oracle.Nuke(bind.NewKeyedTransactor(keys[j])); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid nuke attempt: %v", i, err)
|
||||
}
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
prop, err = oracle.ProposedVersion(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Iter #%d: failed to retrieve active proposal: %v", i, err)
|
||||
}
|
||||
if len(prop.Pass) != 0 || len(prop.Fail) != 0 {
|
||||
t.Fatalf("Iter #%d: proposal vote count mismatch: have %d/%d pass/fail, want 0/0", i, len(prop.Pass), len(prop.Fail))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that demoting a signer will auto-nuke the currently pending release.
|
||||
func TestVersionAutoNuke(t *testing.T) {
|
||||
// Prefund a few accounts to authorize with and create the oracle
|
||||
keys := make([]*ecdsa.PrivateKey, 5)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
keys[i], _ = crypto.GenerateKey()
|
||||
}
|
||||
key, oracle, sim := setupReleaseTest(t, keys...)
|
||||
|
||||
// Authorize all the keys as valid signers
|
||||
keys = append([]*ecdsa.PrivateKey{key}, keys...)
|
||||
for i := 1; i < len(keys); i++ {
|
||||
for j := 0; j <= i/2; j++ {
|
||||
if _, err := oracle.Promote(bind.NewKeyedTransactor(keys[j]), crypto.PubkeyToAddress(keys[i].PublicKey)); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid promotion attempt: %v", i, err)
|
||||
}
|
||||
}
|
||||
sim.Commit()
|
||||
}
|
||||
// Make a release proposal and check it's existence
|
||||
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()
|
||||
|
||||
prop, err := oracle.ProposedVersion(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to retrieve active proposal: %v", err)
|
||||
}
|
||||
if len(prop.Pass) != 1 {
|
||||
t.Fatalf("Proposal vote count mismatch: have %d, want 1", len(prop.Pass))
|
||||
}
|
||||
// Demote a signer and check release proposal deletion
|
||||
for i := 0; i <= len(keys)/2; i++ {
|
||||
if _, err := oracle.Demote(bind.NewKeyedTransactor(keys[i]), crypto.PubkeyToAddress(keys[len(keys)-1].PublicKey)); err != nil {
|
||||
t.Fatalf("Iter #%d: failed valid demotion attempt: %v", i, err)
|
||||
}
|
||||
}
|
||||
sim.Commit()
|
||||
|
||||
prop, err = oracle.ProposedVersion(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to retrieve active proposal: %v", err)
|
||||
}
|
||||
if len(prop.Pass) != 0 {
|
||||
t.Fatalf("Proposal vote count mismatch: have %d, want 0", len(prop.Pass))
|
||||
}
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
// Copyright 2015 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
|
||||
|
||||
//go:generate abigen --sol ./contract.sol --pkg release --out ./contract.go
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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/internal/ethapi"
|
||||
"github.com/ethereum/go-ethereum/les"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"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 apiBackend ethapi.Backend
|
||||
var ethereum *eth.Ethereum
|
||||
if err := ctx.Service(ðereum); err == nil {
|
||||
apiBackend = ethereum.ApiBackend
|
||||
} else {
|
||||
var ethereum *les.LightEthereum
|
||||
if err := ctx.Service(ðereum); err == nil {
|
||||
apiBackend = ethereum.ApiBackend
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// Construct the release service
|
||||
contract, err := NewReleaseOracle(config.Oracle, eth.NewContractBackend(apiBackend))
|
||||
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 {
|
||||
case <-timer.C:
|
||||
// Rechedule the timer before continuing
|
||||
timer.Reset(releaseRecheckInterval)
|
||||
r.checkVersion()
|
||||
case errc := <-r.quit:
|
||||
errc <- nil
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *ReleaseService) checkVersion() {
|
||||
// Retrieve the current version, and handle missing contracts gracefully
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
opts := &bind.CallOpts{Context: ctx}
|
||||
defer cancel()
|
||||
|
||||
version, err := r.oracle.CurrentVersion(opts)
|
||||
if err != nil {
|
||||
if err == bind.ErrNoCode {
|
||||
log.Debug("Release oracle not found", "contract", r.config.Oracle)
|
||||
} else if err != les.ErrNoPeers {
|
||||
log.Error("Failed to retrieve current release", "err", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
// 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))
|
||||
|
||||
log.Warn(separator)
|
||||
log.Warn(warning)
|
||||
log.Warn(howtofix)
|
||||
log.Warn(separator)
|
||||
} else {
|
||||
log.Debug("Client seems up to date with upstream",
|
||||
"local", fmt.Sprintf("v%d.%d.%d-%x", r.config.Major, r.config.Minor, r.config.Patch, r.config.Commit[:4]),
|
||||
"upstream", fmt.Sprintf("v%d.%d.%d-%x", version.Major, version.Minor, version.Patch, version.Commit[:4]))
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user