Commit 4eb077d6 authored by 贾浩@五瓣科技's avatar 贾浩@五瓣科技

update

parent c9d8c942
Pipeline #669 canceled with stages
......@@ -7,3 +7,4 @@ gen
.DS_Store
*.exe
build
data
\ No newline at end of file
.PHONY: default all clean dev
GOBIN = $(shell pwd)/build
GOBIN = $(shell pwd)/build/bin
GOVERSION=$(shell go version | awk '{print $$3}')
GITHASH=$(shell git show -s --format=%H)
......@@ -19,13 +19,15 @@ BUILD_FLAGS=-ldflags "\
witness:
# go build -o MetaNet
go build $(BUILD_FLAGS) -o=${GOBIN}/$@ ./cmd
go build $(BUILD_FLAGS) -v -o=${GOBIN}/$@ ./cmd/witness
dev:
go build $(BUILD_FLAGS) -o=${GOBIN}/$@ -gcflags "all=-N -l" ./cmd
go build $(BUILD_FLAGS) -v -o=${GOBIN}/$@ -gcflags "all=-N -l" ./cmd/witness
clean:
rm -fr build
rm -rf build
cleandb:
rm -rf data/*
\ No newline at end of file
package api
import (
"bytes"
"context"
"errors"
"math/big"
"net"
"witness/core"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
witnessv1 "github.com/odysseus/odysseus-protocol/gen/proto/go/witness/v1"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
)
type Server struct {
witnessv1.UnimplementedWitnessServiceServer
w *core.Witness
}
func (s *Server) WitnessStatus(ctx context.Context, req *witnessv1.WitnessStatusRequest) (resp *witnessv1.WitnessStatusResponse, err error) {
return nil, nil
}
func (s *Server) PushProof(ctx context.Context, req *witnessv1.PushProofRequest) (resp *witnessv1.PushProofResponse, err error) {
resp = &witnessv1.PushProofResponse{}
proofs := req.GetProofs()
if len(proofs) == 0 {
return nil, errors.New("no proofs provided")
}
miner := common.HexToAddress(req.MinerAddress)
reward := common.HexToAddress(req.RewardAddress)
validatedProofs := make([]*witnessv1.ValidatedProof, 0, len(proofs))
log.WithFields(log.Fields{"miner": miner, "reward": reward, "proofs": len(proofs)}).Debug("push proof")
for _, proof := range proofs {
hashPayload := append(append([]byte(proof.TaskId), proof.ReqHash...), proof.RespHash...)
containerPubKey, err := crypto.SigToPub(crypto.Keccak256(hashPayload), proof.ContainerSignature)
if err != nil {
log.WithError(err).Error("failed to verify container signature")
return nil, err
}
containerSigner := crypto.PubkeyToAddress(*containerPubKey)
verified := s.w.IsContainerAddress(containerSigner)
if !verified {
log.WithFields(log.Fields{"signer": containerSigner}).Error("invalid container signature")
return nil, errors.New("invalid container signature")
}
minerHashPayload := append(append([]byte(proof.TaskId), proof.ReqHash...), proof.RespHash...)
minerPubKey, err := crypto.SigToPub(crypto.Keccak256(minerHashPayload), proof.MinerSignature)
if err != nil {
log.WithError(err).Error("failed to verify miner signature")
return nil, err
}
minerAddress := crypto.PubkeyToAddress(*minerPubKey)
if minerAddress.Hex() != miner.Hex() {
log.WithFields(log.Fields{"miner": miner, "signer": minerAddress}).Error("invalid miner address")
return nil, errors.New("invalid miner address")
}
managerHashPayload := bytes.NewBuffer(hashPayload)
managerHashPayload.Write(reward.Bytes())
managerHashPayload.Write(miner.Bytes())
managerHashPayload.Write(proof.ContainerSignature)
managerHashPayload.Write(proof.MinerSignature)
managerHashPayload.Write(big.NewInt(int64(proof.Workload)).Bytes())
managerPubKey, err := crypto.SigToPub(crypto.Keccak256(managerHashPayload.Bytes()), proof.ManagerSignature)
if err != nil {
log.WithError(err).Error("failed to verify manager signature")
return nil, err
}
managerSigner := crypto.PubkeyToAddress(*managerPubKey)
verified = s.w.IsNMAddress(managerSigner)
if !verified {
log.WithFields(log.Fields{"signer": managerSigner}).Error("invalid manager signature")
return nil, errors.New("invalid manager signature")
}
resp.Workload += proof.Workload
validatedProofs = append(validatedProofs, &witnessv1.ValidatedProof{
Workload: proof.Workload,
})
}
s.w.AddPendingProof(miner, validatedProofs)
return resp, nil
}
func (s *Server) GetMinerProof(ctx context.Context, req *witnessv1.GetMinerProofRequest) (*witnessv1.GetMinerProofResponse, error) {
return nil, nil
}
func (s *Server) GetProof(ctx context.Context, req *witnessv1.GetProofRequest) (*witnessv1.GetProofResponse, error) {
return nil, nil
}
func (s *Server) GetWithdrawProof(ctx context.Context, req *witnessv1.GetWithdrawProofRequest) (*witnessv1.GetWithdrawProofResponse, error) {
return nil, nil
}
func StartGRPC(listenAddress string, w *core.Witness) {
ln, err := net.Listen("tcp", listenAddress)
if err != nil {
log.WithError(err).Errorf("failed to listen on %s", listenAddress)
return
}
log.WithField("listen", listenAddress).Info("start gRPC server")
server := grpc.NewServer(grpc.MaxRecvMsgSize(1024*1024*1024), grpc.MaxSendMsgSize(1024*1024*1024))
witnessv1.RegisterWitnessServiceServer(server, &Server{w: w})
grpc_prometheus.Register(server)
err = server.Serve(ln)
if err != nil {
log.WithError(err).Error("failed to serve")
return
}
server.Stop()
}
package api
import (
"context"
"testing"
witnessv1 "github.com/odysseus/odysseus-protocol/gen/proto/go/witness/v1"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestClient(t *testing.T) {
client, err := grpc.Dial("127.0.0.1:9431", grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithDefaultCallOptions(
grpc.MaxCallRecvMsgSize(1024*1024*1024),
grpc.MaxCallSendMsgSize(1024*1024*1024)),
)
if err != nil {
panic(err)
}
gc := witnessv1.NewWitnessServiceClient(client)
req := &witnessv1.PushProofRequest{
Proofs: []*witnessv1.Proof{
{
Workload: 10,
TaskId: "1",
ReqHash: []byte("req"),
RespHash: []byte("resp"),
ManagerSignature: nil,
ContainerSignature: nil,
MinerSignature: nil,
},
},
RewardAddress: "",
MinerAddress: "",
}
resp, err := gc.PushProof(context.Background(), req)
if err != nil {
log.Fatal(err)
}
log.Info(resp.Workload)
}
package api
import (
"encoding/json"
)
type jsonrpcMessage struct {
Version string `json:"jsonrpc"`
ID json.RawMessage `json:"id"`
Method string `json:"method,omitempty"`
Params json.RawMessage `json:"params,omitempty"`
Error *jsonError `json:"error,omitempty"`
Result json.RawMessage `json:"result,omitempty"`
}
type jsonError struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}
package api
import (
"github.com/prometheus/client_golang/prometheus"
)
var (
_ = prometheus.AlreadyRegisteredError{}
)
package api
import (
"encoding/json"
"net/http"
"witness/core"
"github.com/ethereum/go-ethereum/common"
geth "github.com/ethereum/go-ethereum/mobile"
log "github.com/sirupsen/logrus"
)
var witness *core.Witness
func rpcHandle(w http.ResponseWriter, r *http.Request) {
req := &jsonrpcMessage{}
resp := &jsonrpcMessage{}
if r.Method != "POST" {
w.Write([]byte("method not allowed"))
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
w.Header().Set("Content-Type", "application/json")
contentType := r.Header.Get("Content-Type")
if contentType != "application/json" {
resp.Error = &jsonError{
Code: -32600,
Message: "invalid Content-Type header",
}
resp.Version = "2.0"
_ = json.NewEncoder(w).Encode(resp)
return
}
err := json.NewDecoder(r.Body).Decode(req)
if err != nil {
resp.Error = &jsonError{
Code: -32603,
Message: err.Error(),
}
resp.Version = "2.0"
_ = json.NewEncoder(w).Encode(resp)
return
}
if req.Version != "2.0" {
resp.Error = &jsonError{
Code: -32600,
Message: "invalid jsonrpc version",
}
resp.Version = "2.0"
_ = json.NewEncoder(w).Encode(resp)
return
}
resp.Version = req.Version
resp.ID = req.ID
switch req.Method {
case "getWithdrawProofs":
getWithdrawProofs(req.Params, resp)
_ = json.NewEncoder(w).Encode(resp)
return
case "getPendingWorkload":
getPendingWorkload(req.Params, resp)
_ = json.NewEncoder(w).Encode(resp)
return
default:
resp.Error = &jsonError{
Code: -32601,
Message: "method not found",
}
_ = json.NewEncoder(w).Encode(resp)
return
}
}
func getWithdrawProofs(params []byte, resp *jsonrpcMessage) {
addressList := make([]string, 0)
err := json.Unmarshal(params, &addressList)
if err != nil || len(addressList) != 1 {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
_, err = geth.NewAddressFromHex(addressList[0])
if err != nil {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
workload, proofs := witness.GetMerkleProof(common.HexToAddress(addressList[0]))
temp := map[string]interface{}{
"workload": workload,
"proofs": proofs,
}
resp.Result, _ = json.Marshal(temp)
return
}
func getPendingWorkload(params []byte, resp *jsonrpcMessage) {
addressList := make([]string, 0)
err := json.Unmarshal(params, &addressList)
if err != nil || len(addressList) != 1 {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
_, err = geth.NewAddressFromHex(addressList[0])
if err != nil {
resp.Error = &jsonError{
Code: -32602,
Message: "invalid params",
}
return
}
workload := witness.GetPendingWorkload(common.HexToAddress(addressList[0]))
temp := map[string]interface{}{
"workload": workload,
}
resp.Result, _ = json.Marshal(temp)
return
}
func StartJSONRPC(listenAddress string, w *core.Witness) {
witness = w
http.HandleFunc("/", rpcHandle)
log.WithField("listen", listenAddress).Info("start JSON-RPC server")
err := http.ListenAndServe(listenAddress, nil)
if err != nil {
log.WithError(err).Fatal("failed to start JSON-RPC server")
}
}
package main
import (
"fmt"
"os"
"witness/version"
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
var (
appFlags = []cli.Flag{
configFileFlag,
grpcListenAddrFlag,
rpcListenAddrFlag,
rpcHostFlag,
storeContractFlag,
rewardContractFlag,
}
)
func main() {
// run()
fmt.Println(version.GOVersion)
}
func run() {
app := cli.App{}
app.Name = "witness"
app.Usage = "this is witness"
app.Version = version.Version
app.Before = func(c *cli.Context) error {
return loadFlagsFromConfig(c, appFlags)
}
if err := app.Run(os.Args); err != nil {
log.Error(err)
}
}
......@@ -12,6 +12,26 @@ var (
Name: "config",
Aliases: []string{"c"},
Usage: "The path to the config file",
Value: "config.toml",
}
dataDirFlag = &cli.StringFlag{
Name: "data-dir",
Aliases: []string{"d"},
Usage: "The path to the data directory",
Value: "data",
}
metricsListenAddrFlag = &cli.StringFlag{
Name: "metrics-listen",
Usage: "The listen address of the metrics server",
Value: "0.0.0.0:9429",
}
logLevelFlag = &cli.StringFlag{
Name: "log-level",
Usage: "The log level",
Value: "info",
}
grpcListenAddrFlag = &cli.StringFlag{
......@@ -26,7 +46,13 @@ var (
Value: "0.0.0.0:9431",
}
rpcHostFlag = &cli.StringFlag{
privateKeyFlag = &cli.StringFlag{
Name: "private-key",
Usage: "The private key of the account",
EnvVars: []string{"PRIVATE_KEY"},
}
chainRPCFlag = &cli.StringFlag{
Name: "chain-rpc",
Usage: "The host of the chain json rpc server",
}
......@@ -36,8 +62,8 @@ var (
Usage: "The address of the store contract",
}
rewardContractFlag = &cli.StringFlag{
Name: "reward-contract",
witnessContractFlag = &cli.StringFlag{
Name: "witness-contract",
Usage: "The address of the reward contract",
}
)
......
package main
import (
"net/http"
"os"
"witness/api"
"witness/conf"
"witness/core"
"witness/version"
"github.com/prometheus/client_golang/prometheus/promhttp"
log "github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)
var (
appFlags = []cli.Flag{
configFileFlag,
dataDirFlag,
metricsListenAddrFlag,
logLevelFlag,
grpcListenAddrFlag,
rpcListenAddrFlag,
privateKeyFlag,
chainRPCFlag,
storeContractFlag,
witnessContractFlag,
}
)
func main() {
app := cli.App{}
app.Flags = wrapFlags(appFlags)
app.Name = "witness"
app.Usage = "this is witness"
app.Version = version.Version
app.Before = func(c *cli.Context) error {
return loadFlagsFromConfig(c, app.Flags)
}
app.Action = func(context *cli.Context) error {
run(context)
return nil
}
if err := app.Run(os.Args); err != nil {
log.Error(err)
}
}
func run(ctx *cli.Context) {
cfg := &conf.Config{
MetricsListenAddr: ctx.String(metricsListenAddrFlag.Name),
LogLevel: ctx.String(logLevelFlag.Name),
GRPCListenAddr: ctx.String(grpcListenAddrFlag.Name),
RPCListenAddr: ctx.String(rpcListenAddrFlag.Name),
PrivateKey: ctx.String(privateKeyFlag.Name),
ChainRPC: ctx.String(chainRPCFlag.Name),
StoreContract: ctx.String(storeContractFlag.Name),
WitnessContract: ctx.String(witnessContractFlag.Name),
DataDir: ctx.String(dataDirFlag.Name),
}
setLogLevel(cfg.LogLevel)
runMetrics(cfg.MetricsListenAddr)
w := core.NewWitness(cfg)
runGrpcServer(cfg.GRPCListenAddr, w)
runJSONRPCServer(cfg.RPCListenAddr, w)
select {}
}
func setLogLevel(level string) {
_level, err := log.ParseLevel(level)
if err != nil {
log.WithError(err).Error("failed to parse log level")
return
}
log.WithField("log level", _level).Info("set log level")
log.SetLevel(_level)
}
func runMetrics(listen string) {
http.Handle("/metrics", promhttp.Handler())
log.WithField("listen", listen).Info("start prometheus metrics server")
go func() {
if err := http.ListenAndServe(listen, nil); err != nil {
log.WithError(err).Error("failed to start prometheus metrics server")
}
}()
}
func runGrpcServer(listen string, w *core.Witness) {
go api.StartGRPC(listen, w)
}
func runJSONRPCServer(listen string, w *core.Witness) {
go api.StartJSONRPC(listen, w)
}
package conf
type Config struct {
MetricsListenAddr string
LogLevel string
GRPCListenAddr string
RPCListenAddr string
ChainRPC string
PrivateKey string
StoreContract string
WitnessContract string
RewardContract string
DataDir string
}
grpc-listen = "0.0.0.0:9430"
log-level = "debug"
rpc-listen = "0.0.0.0:9431"
metrics-listen = "0.0.0.0:8425"
chain-rpc = "https://1rpc.io/eth"
grpc-listen = "0.0.0.0:9431"
store-contract = "0x0000000000000000000000000000000000000000"
rpc-listen = "0.0.0.0:9442"
reward-contract = "0x0000000000000000000000000000000000000000"
\ No newline at end of file
chain-rpc = "https://1rpc.io/holesky"
private-key = "529f4efb80ac534f17d873104c71881c0970dbd5a886f183f63c5c6bb7a1fcd9"
store-contract = "0x7Cd36Bc2a477f60A14f08442179B2f626bE026Ea"
witness-contract = "0xf49133dD7B7ed75fA0f877413D293c05Bff0D8F0"
\ No newline at end of file
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package contract
import (
"errors"
"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"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
)
// AddressStorageMetaData contains all meta data concerning the AddressStorage contract.
var AddressStorageMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"ok\",\"type\":\"bool\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"ContainerAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"ok\",\"type\":\"bool\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"NmAddressChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"getContainerAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNmAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"isContainerAddress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"isNmAddress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"ok\",\"type\":\"bool\"}],\"name\":\"setContainerAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"ok\",\"type\":\"bool\"}],\"name\":\"setNmAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
}
// AddressStorageABI is the input ABI used to generate the binding from.
// Deprecated: Use AddressStorageMetaData.ABI instead.
var AddressStorageABI = AddressStorageMetaData.ABI
// AddressStorage is an auto generated Go binding around an Ethereum contract.
type AddressStorage struct {
AddressStorageCaller // Read-only binding to the contract
AddressStorageTransactor // Write-only binding to the contract
AddressStorageFilterer // Log filterer for contract events
}
// AddressStorageCaller is an auto generated read-only Go binding around an Ethereum contract.
type AddressStorageCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// AddressStorageTransactor is an auto generated write-only Go binding around an Ethereum contract.
type AddressStorageTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// AddressStorageFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type AddressStorageFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// AddressStorageSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type AddressStorageSession struct {
Contract *AddressStorage // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// AddressStorageCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type AddressStorageCallerSession struct {
Contract *AddressStorageCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// AddressStorageTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type AddressStorageTransactorSession struct {
Contract *AddressStorageTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// AddressStorageRaw is an auto generated low-level Go binding around an Ethereum contract.
type AddressStorageRaw struct {
Contract *AddressStorage // Generic contract binding to access the raw methods on
}
// AddressStorageCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type AddressStorageCallerRaw struct {
Contract *AddressStorageCaller // Generic read-only contract binding to access the raw methods on
}
// AddressStorageTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type AddressStorageTransactorRaw struct {
Contract *AddressStorageTransactor // Generic write-only contract binding to access the raw methods on
}
// NewAddressStorage creates a new instance of AddressStorage, bound to a specific deployed contract.
func NewAddressStorage(address common.Address, backend bind.ContractBackend) (*AddressStorage, error) {
contract, err := bindAddressStorage(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &AddressStorage{AddressStorageCaller: AddressStorageCaller{contract: contract}, AddressStorageTransactor: AddressStorageTransactor{contract: contract}, AddressStorageFilterer: AddressStorageFilterer{contract: contract}}, nil
}
// NewAddressStorageCaller creates a new read-only instance of AddressStorage, bound to a specific deployed contract.
func NewAddressStorageCaller(address common.Address, caller bind.ContractCaller) (*AddressStorageCaller, error) {
contract, err := bindAddressStorage(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &AddressStorageCaller{contract: contract}, nil
}
// NewAddressStorageTransactor creates a new write-only instance of AddressStorage, bound to a specific deployed contract.
func NewAddressStorageTransactor(address common.Address, transactor bind.ContractTransactor) (*AddressStorageTransactor, error) {
contract, err := bindAddressStorage(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &AddressStorageTransactor{contract: contract}, nil
}
// NewAddressStorageFilterer creates a new log filterer instance of AddressStorage, bound to a specific deployed contract.
func NewAddressStorageFilterer(address common.Address, filterer bind.ContractFilterer) (*AddressStorageFilterer, error) {
contract, err := bindAddressStorage(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &AddressStorageFilterer{contract: contract}, nil
}
// bindAddressStorage binds a generic wrapper to an already deployed contract.
func bindAddressStorage(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(AddressStorageABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_AddressStorage *AddressStorageRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _AddressStorage.Contract.AddressStorageCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_AddressStorage *AddressStorageRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _AddressStorage.Contract.AddressStorageTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_AddressStorage *AddressStorageRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _AddressStorage.Contract.AddressStorageTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_AddressStorage *AddressStorageCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _AddressStorage.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_AddressStorage *AddressStorageTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _AddressStorage.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_AddressStorage *AddressStorageTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _AddressStorage.Contract.contract.Transact(opts, method, params...)
}
// GetContainerAddresses is a free data retrieval call binding the contract method 0xd402ae97.
//
// Solidity: function getContainerAddresses() view returns(address[])
func (_AddressStorage *AddressStorageCaller) GetContainerAddresses(opts *bind.CallOpts) ([]common.Address, error) {
var out []interface{}
err := _AddressStorage.contract.Call(opts, &out, "getContainerAddresses")
if err != nil {
return *new([]common.Address), err
}
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address)
return out0, err
}
// GetContainerAddresses is a free data retrieval call binding the contract method 0xd402ae97.
//
// Solidity: function getContainerAddresses() view returns(address[])
func (_AddressStorage *AddressStorageSession) GetContainerAddresses() ([]common.Address, error) {
return _AddressStorage.Contract.GetContainerAddresses(&_AddressStorage.CallOpts)
}
// GetContainerAddresses is a free data retrieval call binding the contract method 0xd402ae97.
//
// Solidity: function getContainerAddresses() view returns(address[])
func (_AddressStorage *AddressStorageCallerSession) GetContainerAddresses() ([]common.Address, error) {
return _AddressStorage.Contract.GetContainerAddresses(&_AddressStorage.CallOpts)
}
// GetNmAddresses is a free data retrieval call binding the contract method 0x09c22170.
//
// Solidity: function getNmAddresses() view returns(address[])
func (_AddressStorage *AddressStorageCaller) GetNmAddresses(opts *bind.CallOpts) ([]common.Address, error) {
var out []interface{}
err := _AddressStorage.contract.Call(opts, &out, "getNmAddresses")
if err != nil {
return *new([]common.Address), err
}
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address)
return out0, err
}
// GetNmAddresses is a free data retrieval call binding the contract method 0x09c22170.
//
// Solidity: function getNmAddresses() view returns(address[])
func (_AddressStorage *AddressStorageSession) GetNmAddresses() ([]common.Address, error) {
return _AddressStorage.Contract.GetNmAddresses(&_AddressStorage.CallOpts)
}
// GetNmAddresses is a free data retrieval call binding the contract method 0x09c22170.
//
// Solidity: function getNmAddresses() view returns(address[])
func (_AddressStorage *AddressStorageCallerSession) GetNmAddresses() ([]common.Address, error) {
return _AddressStorage.Contract.GetNmAddresses(&_AddressStorage.CallOpts)
}
// IsContainerAddress is a free data retrieval call binding the contract method 0x6b7f9e9d.
//
// Solidity: function isContainerAddress(address addr) view returns(bool)
func (_AddressStorage *AddressStorageCaller) IsContainerAddress(opts *bind.CallOpts, addr common.Address) (bool, error) {
var out []interface{}
err := _AddressStorage.contract.Call(opts, &out, "isContainerAddress", addr)
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, err
}
// IsContainerAddress is a free data retrieval call binding the contract method 0x6b7f9e9d.
//
// Solidity: function isContainerAddress(address addr) view returns(bool)
func (_AddressStorage *AddressStorageSession) IsContainerAddress(addr common.Address) (bool, error) {
return _AddressStorage.Contract.IsContainerAddress(&_AddressStorage.CallOpts, addr)
}
// IsContainerAddress is a free data retrieval call binding the contract method 0x6b7f9e9d.
//
// Solidity: function isContainerAddress(address addr) view returns(bool)
func (_AddressStorage *AddressStorageCallerSession) IsContainerAddress(addr common.Address) (bool, error) {
return _AddressStorage.Contract.IsContainerAddress(&_AddressStorage.CallOpts, addr)
}
// IsNmAddress is a free data retrieval call binding the contract method 0x5434152c.
//
// Solidity: function isNmAddress(address addr) view returns(bool)
func (_AddressStorage *AddressStorageCaller) IsNmAddress(opts *bind.CallOpts, addr common.Address) (bool, error) {
var out []interface{}
err := _AddressStorage.contract.Call(opts, &out, "isNmAddress", addr)
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, err
}
// IsNmAddress is a free data retrieval call binding the contract method 0x5434152c.
//
// Solidity: function isNmAddress(address addr) view returns(bool)
func (_AddressStorage *AddressStorageSession) IsNmAddress(addr common.Address) (bool, error) {
return _AddressStorage.Contract.IsNmAddress(&_AddressStorage.CallOpts, addr)
}
// IsNmAddress is a free data retrieval call binding the contract method 0x5434152c.
//
// Solidity: function isNmAddress(address addr) view returns(bool)
func (_AddressStorage *AddressStorageCallerSession) IsNmAddress(addr common.Address) (bool, error) {
return _AddressStorage.Contract.IsNmAddress(&_AddressStorage.CallOpts, addr)
}
// Owner is a free data retrieval call binding the contract method 0x8da5cb5b.
//
// Solidity: function owner() view returns(address)
func (_AddressStorage *AddressStorageCaller) Owner(opts *bind.CallOpts) (common.Address, error) {
var out []interface{}
err := _AddressStorage.contract.Call(opts, &out, "owner")
if err != nil {
return *new(common.Address), err
}
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
return out0, err
}
// Owner is a free data retrieval call binding the contract method 0x8da5cb5b.
//
// Solidity: function owner() view returns(address)
func (_AddressStorage *AddressStorageSession) Owner() (common.Address, error) {
return _AddressStorage.Contract.Owner(&_AddressStorage.CallOpts)
}
// Owner is a free data retrieval call binding the contract method 0x8da5cb5b.
//
// Solidity: function owner() view returns(address)
func (_AddressStorage *AddressStorageCallerSession) Owner() (common.Address, error) {
return _AddressStorage.Contract.Owner(&_AddressStorage.CallOpts)
}
// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6.
//
// Solidity: function renounceOwnership() returns()
func (_AddressStorage *AddressStorageTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) {
return _AddressStorage.contract.Transact(opts, "renounceOwnership")
}
// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6.
//
// Solidity: function renounceOwnership() returns()
func (_AddressStorage *AddressStorageSession) RenounceOwnership() (*types.Transaction, error) {
return _AddressStorage.Contract.RenounceOwnership(&_AddressStorage.TransactOpts)
}
// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6.
//
// Solidity: function renounceOwnership() returns()
func (_AddressStorage *AddressStorageTransactorSession) RenounceOwnership() (*types.Transaction, error) {
return _AddressStorage.Contract.RenounceOwnership(&_AddressStorage.TransactOpts)
}
// SetContainerAddress is a paid mutator transaction binding the contract method 0x0a96de56.
//
// Solidity: function setContainerAddress(address addr, bool ok) returns()
func (_AddressStorage *AddressStorageTransactor) SetContainerAddress(opts *bind.TransactOpts, addr common.Address, ok bool) (*types.Transaction, error) {
return _AddressStorage.contract.Transact(opts, "setContainerAddress", addr, ok)
}
// SetContainerAddress is a paid mutator transaction binding the contract method 0x0a96de56.
//
// Solidity: function setContainerAddress(address addr, bool ok) returns()
func (_AddressStorage *AddressStorageSession) SetContainerAddress(addr common.Address, ok bool) (*types.Transaction, error) {
return _AddressStorage.Contract.SetContainerAddress(&_AddressStorage.TransactOpts, addr, ok)
}
// SetContainerAddress is a paid mutator transaction binding the contract method 0x0a96de56.
//
// Solidity: function setContainerAddress(address addr, bool ok) returns()
func (_AddressStorage *AddressStorageTransactorSession) SetContainerAddress(addr common.Address, ok bool) (*types.Transaction, error) {
return _AddressStorage.Contract.SetContainerAddress(&_AddressStorage.TransactOpts, addr, ok)
}
// SetNmAddress is a paid mutator transaction binding the contract method 0x7e46327f.
//
// Solidity: function setNmAddress(address addr, bool ok) returns()
func (_AddressStorage *AddressStorageTransactor) SetNmAddress(opts *bind.TransactOpts, addr common.Address, ok bool) (*types.Transaction, error) {
return _AddressStorage.contract.Transact(opts, "setNmAddress", addr, ok)
}
// SetNmAddress is a paid mutator transaction binding the contract method 0x7e46327f.
//
// Solidity: function setNmAddress(address addr, bool ok) returns()
func (_AddressStorage *AddressStorageSession) SetNmAddress(addr common.Address, ok bool) (*types.Transaction, error) {
return _AddressStorage.Contract.SetNmAddress(&_AddressStorage.TransactOpts, addr, ok)
}
// SetNmAddress is a paid mutator transaction binding the contract method 0x7e46327f.
//
// Solidity: function setNmAddress(address addr, bool ok) returns()
func (_AddressStorage *AddressStorageTransactorSession) SetNmAddress(addr common.Address, ok bool) (*types.Transaction, error) {
return _AddressStorage.Contract.SetNmAddress(&_AddressStorage.TransactOpts, addr, ok)
}
// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b.
//
// Solidity: function transferOwnership(address newOwner) returns()
func (_AddressStorage *AddressStorageTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) {
return _AddressStorage.contract.Transact(opts, "transferOwnership", newOwner)
}
// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b.
//
// Solidity: function transferOwnership(address newOwner) returns()
func (_AddressStorage *AddressStorageSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) {
return _AddressStorage.Contract.TransferOwnership(&_AddressStorage.TransactOpts, newOwner)
}
// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b.
//
// Solidity: function transferOwnership(address newOwner) returns()
func (_AddressStorage *AddressStorageTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) {
return _AddressStorage.Contract.TransferOwnership(&_AddressStorage.TransactOpts, newOwner)
}
// AddressStorageContainerAddressChangedIterator is returned from FilterContainerAddressChanged and is used to iterate over the raw logs and unpacked data for ContainerAddressChanged events raised by the AddressStorage contract.
type AddressStorageContainerAddressChangedIterator struct {
Event *AddressStorageContainerAddressChanged // 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 *AddressStorageContainerAddressChangedIterator) 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(AddressStorageContainerAddressChanged)
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(AddressStorageContainerAddressChanged)
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 returns any retrieval or parsing error occurred during filtering.
func (it *AddressStorageContainerAddressChangedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *AddressStorageContainerAddressChangedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// AddressStorageContainerAddressChanged represents a ContainerAddressChanged event raised by the AddressStorage contract.
type AddressStorageContainerAddressChanged struct {
Addr common.Address
Ok bool
Count *big.Int
Raw types.Log // Blockchain specific contextual infos
}
// FilterContainerAddressChanged is a free log retrieval operation binding the contract event 0xb6c9f6ac88ad75d755e223ce407f77c17d1fa1c7934be2cd127e8373d1b909f9.
//
// Solidity: event ContainerAddressChanged(address indexed addr, bool indexed ok, uint256 indexed count)
func (_AddressStorage *AddressStorageFilterer) FilterContainerAddressChanged(opts *bind.FilterOpts, addr []common.Address, ok []bool, count []*big.Int) (*AddressStorageContainerAddressChangedIterator, error) {
var addrRule []interface{}
for _, addrItem := range addr {
addrRule = append(addrRule, addrItem)
}
var okRule []interface{}
for _, okItem := range ok {
okRule = append(okRule, okItem)
}
var countRule []interface{}
for _, countItem := range count {
countRule = append(countRule, countItem)
}
logs, sub, err := _AddressStorage.contract.FilterLogs(opts, "ContainerAddressChanged", addrRule, okRule, countRule)
if err != nil {
return nil, err
}
return &AddressStorageContainerAddressChangedIterator{contract: _AddressStorage.contract, event: "ContainerAddressChanged", logs: logs, sub: sub}, nil
}
// WatchContainerAddressChanged is a free log subscription operation binding the contract event 0xb6c9f6ac88ad75d755e223ce407f77c17d1fa1c7934be2cd127e8373d1b909f9.
//
// Solidity: event ContainerAddressChanged(address indexed addr, bool indexed ok, uint256 indexed count)
func (_AddressStorage *AddressStorageFilterer) WatchContainerAddressChanged(opts *bind.WatchOpts, sink chan<- *AddressStorageContainerAddressChanged, addr []common.Address, ok []bool, count []*big.Int) (event.Subscription, error) {
var addrRule []interface{}
for _, addrItem := range addr {
addrRule = append(addrRule, addrItem)
}
var okRule []interface{}
for _, okItem := range ok {
okRule = append(okRule, okItem)
}
var countRule []interface{}
for _, countItem := range count {
countRule = append(countRule, countItem)
}
logs, sub, err := _AddressStorage.contract.WatchLogs(opts, "ContainerAddressChanged", addrRule, okRule, countRule)
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(AddressStorageContainerAddressChanged)
if err := _AddressStorage.contract.UnpackLog(event, "ContainerAddressChanged", 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
}
// ParseContainerAddressChanged is a log parse operation binding the contract event 0xb6c9f6ac88ad75d755e223ce407f77c17d1fa1c7934be2cd127e8373d1b909f9.
//
// Solidity: event ContainerAddressChanged(address indexed addr, bool indexed ok, uint256 indexed count)
func (_AddressStorage *AddressStorageFilterer) ParseContainerAddressChanged(log types.Log) (*AddressStorageContainerAddressChanged, error) {
event := new(AddressStorageContainerAddressChanged)
if err := _AddressStorage.contract.UnpackLog(event, "ContainerAddressChanged", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// AddressStorageNmAddressChangedIterator is returned from FilterNmAddressChanged and is used to iterate over the raw logs and unpacked data for NmAddressChanged events raised by the AddressStorage contract.
type AddressStorageNmAddressChangedIterator struct {
Event *AddressStorageNmAddressChanged // 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 *AddressStorageNmAddressChangedIterator) 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(AddressStorageNmAddressChanged)
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(AddressStorageNmAddressChanged)
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 returns any retrieval or parsing error occurred during filtering.
func (it *AddressStorageNmAddressChangedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *AddressStorageNmAddressChangedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// AddressStorageNmAddressChanged represents a NmAddressChanged event raised by the AddressStorage contract.
type AddressStorageNmAddressChanged struct {
Addr common.Address
Ok bool
Count *big.Int
Raw types.Log // Blockchain specific contextual infos
}
// FilterNmAddressChanged is a free log retrieval operation binding the contract event 0x5c3c7702d99e901d207a52039106e72877dbf05ee667a72bde8568d651ae97bd.
//
// Solidity: event NmAddressChanged(address indexed addr, bool indexed ok, uint256 indexed count)
func (_AddressStorage *AddressStorageFilterer) FilterNmAddressChanged(opts *bind.FilterOpts, addr []common.Address, ok []bool, count []*big.Int) (*AddressStorageNmAddressChangedIterator, error) {
var addrRule []interface{}
for _, addrItem := range addr {
addrRule = append(addrRule, addrItem)
}
var okRule []interface{}
for _, okItem := range ok {
okRule = append(okRule, okItem)
}
var countRule []interface{}
for _, countItem := range count {
countRule = append(countRule, countItem)
}
logs, sub, err := _AddressStorage.contract.FilterLogs(opts, "NmAddressChanged", addrRule, okRule, countRule)
if err != nil {
return nil, err
}
return &AddressStorageNmAddressChangedIterator{contract: _AddressStorage.contract, event: "NmAddressChanged", logs: logs, sub: sub}, nil
}
// WatchNmAddressChanged is a free log subscription operation binding the contract event 0x5c3c7702d99e901d207a52039106e72877dbf05ee667a72bde8568d651ae97bd.
//
// Solidity: event NmAddressChanged(address indexed addr, bool indexed ok, uint256 indexed count)
func (_AddressStorage *AddressStorageFilterer) WatchNmAddressChanged(opts *bind.WatchOpts, sink chan<- *AddressStorageNmAddressChanged, addr []common.Address, ok []bool, count []*big.Int) (event.Subscription, error) {
var addrRule []interface{}
for _, addrItem := range addr {
addrRule = append(addrRule, addrItem)
}
var okRule []interface{}
for _, okItem := range ok {
okRule = append(okRule, okItem)
}
var countRule []interface{}
for _, countItem := range count {
countRule = append(countRule, countItem)
}
logs, sub, err := _AddressStorage.contract.WatchLogs(opts, "NmAddressChanged", addrRule, okRule, countRule)
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(AddressStorageNmAddressChanged)
if err := _AddressStorage.contract.UnpackLog(event, "NmAddressChanged", 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
}
// ParseNmAddressChanged is a log parse operation binding the contract event 0x5c3c7702d99e901d207a52039106e72877dbf05ee667a72bde8568d651ae97bd.
//
// Solidity: event NmAddressChanged(address indexed addr, bool indexed ok, uint256 indexed count)
func (_AddressStorage *AddressStorageFilterer) ParseNmAddressChanged(log types.Log) (*AddressStorageNmAddressChanged, error) {
event := new(AddressStorageNmAddressChanged)
if err := _AddressStorage.contract.UnpackLog(event, "NmAddressChanged", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// AddressStorageOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the AddressStorage contract.
type AddressStorageOwnershipTransferredIterator struct {
Event *AddressStorageOwnershipTransferred // 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 *AddressStorageOwnershipTransferredIterator) 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(AddressStorageOwnershipTransferred)
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(AddressStorageOwnershipTransferred)
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 returns any retrieval or parsing error occurred during filtering.
func (it *AddressStorageOwnershipTransferredIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *AddressStorageOwnershipTransferredIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// AddressStorageOwnershipTransferred represents a OwnershipTransferred event raised by the AddressStorage contract.
type AddressStorageOwnershipTransferred struct {
PreviousOwner common.Address
NewOwner common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
//
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_AddressStorage *AddressStorageFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*AddressStorageOwnershipTransferredIterator, error) {
var previousOwnerRule []interface{}
for _, previousOwnerItem := range previousOwner {
previousOwnerRule = append(previousOwnerRule, previousOwnerItem)
}
var newOwnerRule []interface{}
for _, newOwnerItem := range newOwner {
newOwnerRule = append(newOwnerRule, newOwnerItem)
}
logs, sub, err := _AddressStorage.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule)
if err != nil {
return nil, err
}
return &AddressStorageOwnershipTransferredIterator{contract: _AddressStorage.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil
}
// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
//
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_AddressStorage *AddressStorageFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *AddressStorageOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) {
var previousOwnerRule []interface{}
for _, previousOwnerItem := range previousOwner {
previousOwnerRule = append(previousOwnerRule, previousOwnerItem)
}
var newOwnerRule []interface{}
for _, newOwnerItem := range newOwner {
newOwnerRule = append(newOwnerRule, newOwnerItem)
}
logs, sub, err := _AddressStorage.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule)
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(AddressStorageOwnershipTransferred)
if err := _AddressStorage.contract.UnpackLog(event, "OwnershipTransferred", 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
}
// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
//
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_AddressStorage *AddressStorageFilterer) ParseOwnershipTransferred(log types.Log) (*AddressStorageOwnershipTransferred, error) {
event := new(AddressStorageOwnershipTransferred)
if err := _AddressStorage.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package contract
import (
"errors"
"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"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
)
// WitnessMetaData contains all meta data concerning the Witness contract.
var WitnessMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"dailyDistribution\",\"type\":\"uint256\"}],\"name\":\"DailyDistributionChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"date\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"merkleSumRoot\",\"type\":\"bytes32\"}],\"name\":\"MerkleRootChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"merkleSumRoot\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"dailySubmitCount\",\"type\":\"uint256\"}],\"name\":\"MerkleRootSubmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"merkleRootThreshold\",\"type\":\"uint256\"}],\"name\":\"MerkleRootThresholdChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"ok\",\"type\":\"bool\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"WitnessChanged\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"dailyDistribution\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"dailyMerkleRootMap\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dailyMerkleRootSubmitCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"dailyMerkleRootSubmitCountMap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"dailyMerkleRootSubmittedMap\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"dailyMerkleRootVerifiedMap\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"name\":\"dailyMerkleSumRootMap\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDailyDistribution\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWitnesses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"isWitness\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastMerkleRootUpdate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleRootThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleSumRoot\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_dailyDistribution\",\"type\":\"uint256\"}],\"name\":\"setDailyDistribution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_merkleRootThreshold\",\"type\":\"uint256\"}],\"name\":\"setRootThreshold\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"ok\",\"type\":\"bool\"}],\"name\":\"setWitness\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_date\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_merkleSumRoot\",\"type\":\"bytes32\"}],\"name\":\"submitMerkleRoot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"witnessAddressMap\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"witnessCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
}
// WitnessABI is the input ABI used to generate the binding from.
// Deprecated: Use WitnessMetaData.ABI instead.
var WitnessABI = WitnessMetaData.ABI
// Witness is an auto generated Go binding around an Ethereum contract.
type Witness struct {
WitnessCaller // Read-only binding to the contract
WitnessTransactor // Write-only binding to the contract
WitnessFilterer // Log filterer for contract events
}
// WitnessCaller is an auto generated read-only Go binding around an Ethereum contract.
type WitnessCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// WitnessTransactor is an auto generated write-only Go binding around an Ethereum contract.
type WitnessTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// WitnessFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type WitnessFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// WitnessSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type WitnessSession struct {
Contract *Witness // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// WitnessCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type WitnessCallerSession struct {
Contract *WitnessCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// WitnessTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type WitnessTransactorSession struct {
Contract *WitnessTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// WitnessRaw is an auto generated low-level Go binding around an Ethereum contract.
type WitnessRaw struct {
Contract *Witness // Generic contract binding to access the raw methods on
}
// WitnessCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type WitnessCallerRaw struct {
Contract *WitnessCaller // Generic read-only contract binding to access the raw methods on
}
// WitnessTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type WitnessTransactorRaw struct {
Contract *WitnessTransactor // Generic write-only contract binding to access the raw methods on
}
// NewWitness creates a new instance of Witness, bound to a specific deployed contract.
func NewWitness(address common.Address, backend bind.ContractBackend) (*Witness, error) {
contract, err := bindWitness(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &Witness{WitnessCaller: WitnessCaller{contract: contract}, WitnessTransactor: WitnessTransactor{contract: contract}, WitnessFilterer: WitnessFilterer{contract: contract}}, nil
}
// NewWitnessCaller creates a new read-only instance of Witness, bound to a specific deployed contract.
func NewWitnessCaller(address common.Address, caller bind.ContractCaller) (*WitnessCaller, error) {
contract, err := bindWitness(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &WitnessCaller{contract: contract}, nil
}
// NewWitnessTransactor creates a new write-only instance of Witness, bound to a specific deployed contract.
func NewWitnessTransactor(address common.Address, transactor bind.ContractTransactor) (*WitnessTransactor, error) {
contract, err := bindWitness(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &WitnessTransactor{contract: contract}, nil
}
// NewWitnessFilterer creates a new log filterer instance of Witness, bound to a specific deployed contract.
func NewWitnessFilterer(address common.Address, filterer bind.ContractFilterer) (*WitnessFilterer, error) {
contract, err := bindWitness(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &WitnessFilterer{contract: contract}, nil
}
// bindWitness binds a generic wrapper to an already deployed contract.
func bindWitness(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(WitnessABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_Witness *WitnessRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _Witness.Contract.WitnessCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_Witness *WitnessRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Witness.Contract.WitnessTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_Witness *WitnessRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _Witness.Contract.WitnessTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_Witness *WitnessCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _Witness.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_Witness *WitnessTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Witness.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_Witness *WitnessTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _Witness.Contract.contract.Transact(opts, method, params...)
}
// DailyDistribution is a free data retrieval call binding the contract method 0xde8f55af.
//
// Solidity: function dailyDistribution() view returns(uint256)
func (_Witness *WitnessCaller) DailyDistribution(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "dailyDistribution")
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// DailyDistribution is a free data retrieval call binding the contract method 0xde8f55af.
//
// Solidity: function dailyDistribution() view returns(uint256)
func (_Witness *WitnessSession) DailyDistribution() (*big.Int, error) {
return _Witness.Contract.DailyDistribution(&_Witness.CallOpts)
}
// DailyDistribution is a free data retrieval call binding the contract method 0xde8f55af.
//
// Solidity: function dailyDistribution() view returns(uint256)
func (_Witness *WitnessCallerSession) DailyDistribution() (*big.Int, error) {
return _Witness.Contract.DailyDistribution(&_Witness.CallOpts)
}
// DailyMerkleRootMap is a free data retrieval call binding the contract method 0x933c2732.
//
// Solidity: function dailyMerkleRootMap(string ) view returns(bytes32)
func (_Witness *WitnessCaller) DailyMerkleRootMap(opts *bind.CallOpts, arg0 string) ([32]byte, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "dailyMerkleRootMap", arg0)
if err != nil {
return *new([32]byte), err
}
out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
return out0, err
}
// DailyMerkleRootMap is a free data retrieval call binding the contract method 0x933c2732.
//
// Solidity: function dailyMerkleRootMap(string ) view returns(bytes32)
func (_Witness *WitnessSession) DailyMerkleRootMap(arg0 string) ([32]byte, error) {
return _Witness.Contract.DailyMerkleRootMap(&_Witness.CallOpts, arg0)
}
// DailyMerkleRootMap is a free data retrieval call binding the contract method 0x933c2732.
//
// Solidity: function dailyMerkleRootMap(string ) view returns(bytes32)
func (_Witness *WitnessCallerSession) DailyMerkleRootMap(arg0 string) ([32]byte, error) {
return _Witness.Contract.DailyMerkleRootMap(&_Witness.CallOpts, arg0)
}
// DailyMerkleRootSubmitCount is a free data retrieval call binding the contract method 0xeb6dd75e.
//
// Solidity: function dailyMerkleRootSubmitCount() view returns(uint256)
func (_Witness *WitnessCaller) DailyMerkleRootSubmitCount(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "dailyMerkleRootSubmitCount")
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// DailyMerkleRootSubmitCount is a free data retrieval call binding the contract method 0xeb6dd75e.
//
// Solidity: function dailyMerkleRootSubmitCount() view returns(uint256)
func (_Witness *WitnessSession) DailyMerkleRootSubmitCount() (*big.Int, error) {
return _Witness.Contract.DailyMerkleRootSubmitCount(&_Witness.CallOpts)
}
// DailyMerkleRootSubmitCount is a free data retrieval call binding the contract method 0xeb6dd75e.
//
// Solidity: function dailyMerkleRootSubmitCount() view returns(uint256)
func (_Witness *WitnessCallerSession) DailyMerkleRootSubmitCount() (*big.Int, error) {
return _Witness.Contract.DailyMerkleRootSubmitCount(&_Witness.CallOpts)
}
// DailyMerkleRootSubmitCountMap is a free data retrieval call binding the contract method 0x1ff9cbaa.
//
// Solidity: function dailyMerkleRootSubmitCountMap(string , bytes32 ) view returns(uint256)
func (_Witness *WitnessCaller) DailyMerkleRootSubmitCountMap(opts *bind.CallOpts, arg0 string, arg1 [32]byte) (*big.Int, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "dailyMerkleRootSubmitCountMap", arg0, arg1)
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// DailyMerkleRootSubmitCountMap is a free data retrieval call binding the contract method 0x1ff9cbaa.
//
// Solidity: function dailyMerkleRootSubmitCountMap(string , bytes32 ) view returns(uint256)
func (_Witness *WitnessSession) DailyMerkleRootSubmitCountMap(arg0 string, arg1 [32]byte) (*big.Int, error) {
return _Witness.Contract.DailyMerkleRootSubmitCountMap(&_Witness.CallOpts, arg0, arg1)
}
// DailyMerkleRootSubmitCountMap is a free data retrieval call binding the contract method 0x1ff9cbaa.
//
// Solidity: function dailyMerkleRootSubmitCountMap(string , bytes32 ) view returns(uint256)
func (_Witness *WitnessCallerSession) DailyMerkleRootSubmitCountMap(arg0 string, arg1 [32]byte) (*big.Int, error) {
return _Witness.Contract.DailyMerkleRootSubmitCountMap(&_Witness.CallOpts, arg0, arg1)
}
// DailyMerkleRootSubmittedMap is a free data retrieval call binding the contract method 0x9b6c4c33.
//
// Solidity: function dailyMerkleRootSubmittedMap(string , address ) view returns(bool)
func (_Witness *WitnessCaller) DailyMerkleRootSubmittedMap(opts *bind.CallOpts, arg0 string, arg1 common.Address) (bool, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "dailyMerkleRootSubmittedMap", arg0, arg1)
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, err
}
// DailyMerkleRootSubmittedMap is a free data retrieval call binding the contract method 0x9b6c4c33.
//
// Solidity: function dailyMerkleRootSubmittedMap(string , address ) view returns(bool)
func (_Witness *WitnessSession) DailyMerkleRootSubmittedMap(arg0 string, arg1 common.Address) (bool, error) {
return _Witness.Contract.DailyMerkleRootSubmittedMap(&_Witness.CallOpts, arg0, arg1)
}
// DailyMerkleRootSubmittedMap is a free data retrieval call binding the contract method 0x9b6c4c33.
//
// Solidity: function dailyMerkleRootSubmittedMap(string , address ) view returns(bool)
func (_Witness *WitnessCallerSession) DailyMerkleRootSubmittedMap(arg0 string, arg1 common.Address) (bool, error) {
return _Witness.Contract.DailyMerkleRootSubmittedMap(&_Witness.CallOpts, arg0, arg1)
}
// DailyMerkleRootVerifiedMap is a free data retrieval call binding the contract method 0x0b89bee2.
//
// Solidity: function dailyMerkleRootVerifiedMap(string ) view returns(bool)
func (_Witness *WitnessCaller) DailyMerkleRootVerifiedMap(opts *bind.CallOpts, arg0 string) (bool, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "dailyMerkleRootVerifiedMap", arg0)
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, err
}
// DailyMerkleRootVerifiedMap is a free data retrieval call binding the contract method 0x0b89bee2.
//
// Solidity: function dailyMerkleRootVerifiedMap(string ) view returns(bool)
func (_Witness *WitnessSession) DailyMerkleRootVerifiedMap(arg0 string) (bool, error) {
return _Witness.Contract.DailyMerkleRootVerifiedMap(&_Witness.CallOpts, arg0)
}
// DailyMerkleRootVerifiedMap is a free data retrieval call binding the contract method 0x0b89bee2.
//
// Solidity: function dailyMerkleRootVerifiedMap(string ) view returns(bool)
func (_Witness *WitnessCallerSession) DailyMerkleRootVerifiedMap(arg0 string) (bool, error) {
return _Witness.Contract.DailyMerkleRootVerifiedMap(&_Witness.CallOpts, arg0)
}
// DailyMerkleSumRootMap is a free data retrieval call binding the contract method 0x61bc5c39.
//
// Solidity: function dailyMerkleSumRootMap(string ) view returns(bytes32)
func (_Witness *WitnessCaller) DailyMerkleSumRootMap(opts *bind.CallOpts, arg0 string) ([32]byte, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "dailyMerkleSumRootMap", arg0)
if err != nil {
return *new([32]byte), err
}
out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
return out0, err
}
// DailyMerkleSumRootMap is a free data retrieval call binding the contract method 0x61bc5c39.
//
// Solidity: function dailyMerkleSumRootMap(string ) view returns(bytes32)
func (_Witness *WitnessSession) DailyMerkleSumRootMap(arg0 string) ([32]byte, error) {
return _Witness.Contract.DailyMerkleSumRootMap(&_Witness.CallOpts, arg0)
}
// DailyMerkleSumRootMap is a free data retrieval call binding the contract method 0x61bc5c39.
//
// Solidity: function dailyMerkleSumRootMap(string ) view returns(bytes32)
func (_Witness *WitnessCallerSession) DailyMerkleSumRootMap(arg0 string) ([32]byte, error) {
return _Witness.Contract.DailyMerkleSumRootMap(&_Witness.CallOpts, arg0)
}
// GetDailyDistribution is a free data retrieval call binding the contract method 0xc75c46c8.
//
// Solidity: function getDailyDistribution() view returns(uint256)
func (_Witness *WitnessCaller) GetDailyDistribution(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "getDailyDistribution")
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// GetDailyDistribution is a free data retrieval call binding the contract method 0xc75c46c8.
//
// Solidity: function getDailyDistribution() view returns(uint256)
func (_Witness *WitnessSession) GetDailyDistribution() (*big.Int, error) {
return _Witness.Contract.GetDailyDistribution(&_Witness.CallOpts)
}
// GetDailyDistribution is a free data retrieval call binding the contract method 0xc75c46c8.
//
// Solidity: function getDailyDistribution() view returns(uint256)
func (_Witness *WitnessCallerSession) GetDailyDistribution() (*big.Int, error) {
return _Witness.Contract.GetDailyDistribution(&_Witness.CallOpts)
}
// GetMerkleRoot is a free data retrieval call binding the contract method 0x49590657.
//
// Solidity: function getMerkleRoot() view returns(bytes32)
func (_Witness *WitnessCaller) GetMerkleRoot(opts *bind.CallOpts) ([32]byte, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "getMerkleRoot")
if err != nil {
return *new([32]byte), err
}
out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
return out0, err
}
// GetMerkleRoot is a free data retrieval call binding the contract method 0x49590657.
//
// Solidity: function getMerkleRoot() view returns(bytes32)
func (_Witness *WitnessSession) GetMerkleRoot() ([32]byte, error) {
return _Witness.Contract.GetMerkleRoot(&_Witness.CallOpts)
}
// GetMerkleRoot is a free data retrieval call binding the contract method 0x49590657.
//
// Solidity: function getMerkleRoot() view returns(bytes32)
func (_Witness *WitnessCallerSession) GetMerkleRoot() ([32]byte, error) {
return _Witness.Contract.GetMerkleRoot(&_Witness.CallOpts)
}
// GetWitnesses is a free data retrieval call binding the contract method 0x96d195bd.
//
// Solidity: function getWitnesses() view returns(address[])
func (_Witness *WitnessCaller) GetWitnesses(opts *bind.CallOpts) ([]common.Address, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "getWitnesses")
if err != nil {
return *new([]common.Address), err
}
out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address)
return out0, err
}
// GetWitnesses is a free data retrieval call binding the contract method 0x96d195bd.
//
// Solidity: function getWitnesses() view returns(address[])
func (_Witness *WitnessSession) GetWitnesses() ([]common.Address, error) {
return _Witness.Contract.GetWitnesses(&_Witness.CallOpts)
}
// GetWitnesses is a free data retrieval call binding the contract method 0x96d195bd.
//
// Solidity: function getWitnesses() view returns(address[])
func (_Witness *WitnessCallerSession) GetWitnesses() ([]common.Address, error) {
return _Witness.Contract.GetWitnesses(&_Witness.CallOpts)
}
// IsWitness is a free data retrieval call binding the contract method 0xfa7643f4.
//
// Solidity: function isWitness(address addr) view returns(bool)
func (_Witness *WitnessCaller) IsWitness(opts *bind.CallOpts, addr common.Address) (bool, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "isWitness", addr)
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, err
}
// IsWitness is a free data retrieval call binding the contract method 0xfa7643f4.
//
// Solidity: function isWitness(address addr) view returns(bool)
func (_Witness *WitnessSession) IsWitness(addr common.Address) (bool, error) {
return _Witness.Contract.IsWitness(&_Witness.CallOpts, addr)
}
// IsWitness is a free data retrieval call binding the contract method 0xfa7643f4.
//
// Solidity: function isWitness(address addr) view returns(bool)
func (_Witness *WitnessCallerSession) IsWitness(addr common.Address) (bool, error) {
return _Witness.Contract.IsWitness(&_Witness.CallOpts, addr)
}
// LastMerkleRootUpdate is a free data retrieval call binding the contract method 0xed86955e.
//
// Solidity: function lastMerkleRootUpdate() view returns(uint256)
func (_Witness *WitnessCaller) LastMerkleRootUpdate(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "lastMerkleRootUpdate")
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// LastMerkleRootUpdate is a free data retrieval call binding the contract method 0xed86955e.
//
// Solidity: function lastMerkleRootUpdate() view returns(uint256)
func (_Witness *WitnessSession) LastMerkleRootUpdate() (*big.Int, error) {
return _Witness.Contract.LastMerkleRootUpdate(&_Witness.CallOpts)
}
// LastMerkleRootUpdate is a free data retrieval call binding the contract method 0xed86955e.
//
// Solidity: function lastMerkleRootUpdate() view returns(uint256)
func (_Witness *WitnessCallerSession) LastMerkleRootUpdate() (*big.Int, error) {
return _Witness.Contract.LastMerkleRootUpdate(&_Witness.CallOpts)
}
// MerkleRoot is a free data retrieval call binding the contract method 0x2eb4a7ab.
//
// Solidity: function merkleRoot() view returns(bytes32)
func (_Witness *WitnessCaller) MerkleRoot(opts *bind.CallOpts) ([32]byte, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "merkleRoot")
if err != nil {
return *new([32]byte), err
}
out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
return out0, err
}
// MerkleRoot is a free data retrieval call binding the contract method 0x2eb4a7ab.
//
// Solidity: function merkleRoot() view returns(bytes32)
func (_Witness *WitnessSession) MerkleRoot() ([32]byte, error) {
return _Witness.Contract.MerkleRoot(&_Witness.CallOpts)
}
// MerkleRoot is a free data retrieval call binding the contract method 0x2eb4a7ab.
//
// Solidity: function merkleRoot() view returns(bytes32)
func (_Witness *WitnessCallerSession) MerkleRoot() ([32]byte, error) {
return _Witness.Contract.MerkleRoot(&_Witness.CallOpts)
}
// MerkleRootThreshold is a free data retrieval call binding the contract method 0x63bd80dd.
//
// Solidity: function merkleRootThreshold() view returns(uint256)
func (_Witness *WitnessCaller) MerkleRootThreshold(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "merkleRootThreshold")
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// MerkleRootThreshold is a free data retrieval call binding the contract method 0x63bd80dd.
//
// Solidity: function merkleRootThreshold() view returns(uint256)
func (_Witness *WitnessSession) MerkleRootThreshold() (*big.Int, error) {
return _Witness.Contract.MerkleRootThreshold(&_Witness.CallOpts)
}
// MerkleRootThreshold is a free data retrieval call binding the contract method 0x63bd80dd.
//
// Solidity: function merkleRootThreshold() view returns(uint256)
func (_Witness *WitnessCallerSession) MerkleRootThreshold() (*big.Int, error) {
return _Witness.Contract.MerkleRootThreshold(&_Witness.CallOpts)
}
// MerkleSumRoot is a free data retrieval call binding the contract method 0x529d7e7c.
//
// Solidity: function merkleSumRoot() view returns(bytes32)
func (_Witness *WitnessCaller) MerkleSumRoot(opts *bind.CallOpts) ([32]byte, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "merkleSumRoot")
if err != nil {
return *new([32]byte), err
}
out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte)
return out0, err
}
// MerkleSumRoot is a free data retrieval call binding the contract method 0x529d7e7c.
//
// Solidity: function merkleSumRoot() view returns(bytes32)
func (_Witness *WitnessSession) MerkleSumRoot() ([32]byte, error) {
return _Witness.Contract.MerkleSumRoot(&_Witness.CallOpts)
}
// MerkleSumRoot is a free data retrieval call binding the contract method 0x529d7e7c.
//
// Solidity: function merkleSumRoot() view returns(bytes32)
func (_Witness *WitnessCallerSession) MerkleSumRoot() ([32]byte, error) {
return _Witness.Contract.MerkleSumRoot(&_Witness.CallOpts)
}
// Owner is a free data retrieval call binding the contract method 0x8da5cb5b.
//
// Solidity: function owner() view returns(address)
func (_Witness *WitnessCaller) Owner(opts *bind.CallOpts) (common.Address, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "owner")
if err != nil {
return *new(common.Address), err
}
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
return out0, err
}
// Owner is a free data retrieval call binding the contract method 0x8da5cb5b.
//
// Solidity: function owner() view returns(address)
func (_Witness *WitnessSession) Owner() (common.Address, error) {
return _Witness.Contract.Owner(&_Witness.CallOpts)
}
// Owner is a free data retrieval call binding the contract method 0x8da5cb5b.
//
// Solidity: function owner() view returns(address)
func (_Witness *WitnessCallerSession) Owner() (common.Address, error) {
return _Witness.Contract.Owner(&_Witness.CallOpts)
}
// WitnessAddressMap is a free data retrieval call binding the contract method 0xfe88504e.
//
// Solidity: function witnessAddressMap(address ) view returns(bool)
func (_Witness *WitnessCaller) WitnessAddressMap(opts *bind.CallOpts, arg0 common.Address) (bool, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "witnessAddressMap", arg0)
if err != nil {
return *new(bool), err
}
out0 := *abi.ConvertType(out[0], new(bool)).(*bool)
return out0, err
}
// WitnessAddressMap is a free data retrieval call binding the contract method 0xfe88504e.
//
// Solidity: function witnessAddressMap(address ) view returns(bool)
func (_Witness *WitnessSession) WitnessAddressMap(arg0 common.Address) (bool, error) {
return _Witness.Contract.WitnessAddressMap(&_Witness.CallOpts, arg0)
}
// WitnessAddressMap is a free data retrieval call binding the contract method 0xfe88504e.
//
// Solidity: function witnessAddressMap(address ) view returns(bool)
func (_Witness *WitnessCallerSession) WitnessAddressMap(arg0 common.Address) (bool, error) {
return _Witness.Contract.WitnessAddressMap(&_Witness.CallOpts, arg0)
}
// WitnessCount is a free data retrieval call binding the contract method 0x75aa85c1.
//
// Solidity: function witnessCount() view returns(uint256)
func (_Witness *WitnessCaller) WitnessCount(opts *bind.CallOpts) (*big.Int, error) {
var out []interface{}
err := _Witness.contract.Call(opts, &out, "witnessCount")
if err != nil {
return *new(*big.Int), err
}
out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
return out0, err
}
// WitnessCount is a free data retrieval call binding the contract method 0x75aa85c1.
//
// Solidity: function witnessCount() view returns(uint256)
func (_Witness *WitnessSession) WitnessCount() (*big.Int, error) {
return _Witness.Contract.WitnessCount(&_Witness.CallOpts)
}
// WitnessCount is a free data retrieval call binding the contract method 0x75aa85c1.
//
// Solidity: function witnessCount() view returns(uint256)
func (_Witness *WitnessCallerSession) WitnessCount() (*big.Int, error) {
return _Witness.Contract.WitnessCount(&_Witness.CallOpts)
}
// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6.
//
// Solidity: function renounceOwnership() returns()
func (_Witness *WitnessTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Witness.contract.Transact(opts, "renounceOwnership")
}
// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6.
//
// Solidity: function renounceOwnership() returns()
func (_Witness *WitnessSession) RenounceOwnership() (*types.Transaction, error) {
return _Witness.Contract.RenounceOwnership(&_Witness.TransactOpts)
}
// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6.
//
// Solidity: function renounceOwnership() returns()
func (_Witness *WitnessTransactorSession) RenounceOwnership() (*types.Transaction, error) {
return _Witness.Contract.RenounceOwnership(&_Witness.TransactOpts)
}
// SetDailyDistribution is a paid mutator transaction binding the contract method 0x2911360a.
//
// Solidity: function setDailyDistribution(uint256 _dailyDistribution) returns()
func (_Witness *WitnessTransactor) SetDailyDistribution(opts *bind.TransactOpts, _dailyDistribution *big.Int) (*types.Transaction, error) {
return _Witness.contract.Transact(opts, "setDailyDistribution", _dailyDistribution)
}
// SetDailyDistribution is a paid mutator transaction binding the contract method 0x2911360a.
//
// Solidity: function setDailyDistribution(uint256 _dailyDistribution) returns()
func (_Witness *WitnessSession) SetDailyDistribution(_dailyDistribution *big.Int) (*types.Transaction, error) {
return _Witness.Contract.SetDailyDistribution(&_Witness.TransactOpts, _dailyDistribution)
}
// SetDailyDistribution is a paid mutator transaction binding the contract method 0x2911360a.
//
// Solidity: function setDailyDistribution(uint256 _dailyDistribution) returns()
func (_Witness *WitnessTransactorSession) SetDailyDistribution(_dailyDistribution *big.Int) (*types.Transaction, error) {
return _Witness.Contract.SetDailyDistribution(&_Witness.TransactOpts, _dailyDistribution)
}
// SetRootThreshold is a paid mutator transaction binding the contract method 0x718b08a8.
//
// Solidity: function setRootThreshold(uint256 _merkleRootThreshold) returns()
func (_Witness *WitnessTransactor) SetRootThreshold(opts *bind.TransactOpts, _merkleRootThreshold *big.Int) (*types.Transaction, error) {
return _Witness.contract.Transact(opts, "setRootThreshold", _merkleRootThreshold)
}
// SetRootThreshold is a paid mutator transaction binding the contract method 0x718b08a8.
//
// Solidity: function setRootThreshold(uint256 _merkleRootThreshold) returns()
func (_Witness *WitnessSession) SetRootThreshold(_merkleRootThreshold *big.Int) (*types.Transaction, error) {
return _Witness.Contract.SetRootThreshold(&_Witness.TransactOpts, _merkleRootThreshold)
}
// SetRootThreshold is a paid mutator transaction binding the contract method 0x718b08a8.
//
// Solidity: function setRootThreshold(uint256 _merkleRootThreshold) returns()
func (_Witness *WitnessTransactorSession) SetRootThreshold(_merkleRootThreshold *big.Int) (*types.Transaction, error) {
return _Witness.Contract.SetRootThreshold(&_Witness.TransactOpts, _merkleRootThreshold)
}
// SetWitness is a paid mutator transaction binding the contract method 0x7643244a.
//
// Solidity: function setWitness(address addr, bool ok) returns()
func (_Witness *WitnessTransactor) SetWitness(opts *bind.TransactOpts, addr common.Address, ok bool) (*types.Transaction, error) {
return _Witness.contract.Transact(opts, "setWitness", addr, ok)
}
// SetWitness is a paid mutator transaction binding the contract method 0x7643244a.
//
// Solidity: function setWitness(address addr, bool ok) returns()
func (_Witness *WitnessSession) SetWitness(addr common.Address, ok bool) (*types.Transaction, error) {
return _Witness.Contract.SetWitness(&_Witness.TransactOpts, addr, ok)
}
// SetWitness is a paid mutator transaction binding the contract method 0x7643244a.
//
// Solidity: function setWitness(address addr, bool ok) returns()
func (_Witness *WitnessTransactorSession) SetWitness(addr common.Address, ok bool) (*types.Transaction, error) {
return _Witness.Contract.SetWitness(&_Witness.TransactOpts, addr, ok)
}
// SubmitMerkleRoot is a paid mutator transaction binding the contract method 0xb51d7c96.
//
// Solidity: function submitMerkleRoot(string _date, bytes32 _merkleRoot, bytes32 _merkleSumRoot) returns()
func (_Witness *WitnessTransactor) SubmitMerkleRoot(opts *bind.TransactOpts, _date string, _merkleRoot [32]byte, _merkleSumRoot [32]byte) (*types.Transaction, error) {
return _Witness.contract.Transact(opts, "submitMerkleRoot", _date, _merkleRoot, _merkleSumRoot)
}
// SubmitMerkleRoot is a paid mutator transaction binding the contract method 0xb51d7c96.
//
// Solidity: function submitMerkleRoot(string _date, bytes32 _merkleRoot, bytes32 _merkleSumRoot) returns()
func (_Witness *WitnessSession) SubmitMerkleRoot(_date string, _merkleRoot [32]byte, _merkleSumRoot [32]byte) (*types.Transaction, error) {
return _Witness.Contract.SubmitMerkleRoot(&_Witness.TransactOpts, _date, _merkleRoot, _merkleSumRoot)
}
// SubmitMerkleRoot is a paid mutator transaction binding the contract method 0xb51d7c96.
//
// Solidity: function submitMerkleRoot(string _date, bytes32 _merkleRoot, bytes32 _merkleSumRoot) returns()
func (_Witness *WitnessTransactorSession) SubmitMerkleRoot(_date string, _merkleRoot [32]byte, _merkleSumRoot [32]byte) (*types.Transaction, error) {
return _Witness.Contract.SubmitMerkleRoot(&_Witness.TransactOpts, _date, _merkleRoot, _merkleSumRoot)
}
// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b.
//
// Solidity: function transferOwnership(address newOwner) returns()
func (_Witness *WitnessTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) {
return _Witness.contract.Transact(opts, "transferOwnership", newOwner)
}
// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b.
//
// Solidity: function transferOwnership(address newOwner) returns()
func (_Witness *WitnessSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) {
return _Witness.Contract.TransferOwnership(&_Witness.TransactOpts, newOwner)
}
// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b.
//
// Solidity: function transferOwnership(address newOwner) returns()
func (_Witness *WitnessTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) {
return _Witness.Contract.TransferOwnership(&_Witness.TransactOpts, newOwner)
}
// WitnessDailyDistributionChangedIterator is returned from FilterDailyDistributionChanged and is used to iterate over the raw logs and unpacked data for DailyDistributionChanged events raised by the Witness contract.
type WitnessDailyDistributionChangedIterator struct {
Event *WitnessDailyDistributionChanged // 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 *WitnessDailyDistributionChangedIterator) 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(WitnessDailyDistributionChanged)
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(WitnessDailyDistributionChanged)
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 returns any retrieval or parsing error occurred during filtering.
func (it *WitnessDailyDistributionChangedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *WitnessDailyDistributionChangedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// WitnessDailyDistributionChanged represents a DailyDistributionChanged event raised by the Witness contract.
type WitnessDailyDistributionChanged struct {
DailyDistribution *big.Int
Raw types.Log // Blockchain specific contextual infos
}
// FilterDailyDistributionChanged is a free log retrieval operation binding the contract event 0xb3ae8e2fdcbd3e5bc919976d8ad797511092f7b991c4a29813a72b0b09e79458.
//
// Solidity: event DailyDistributionChanged(uint256 dailyDistribution)
func (_Witness *WitnessFilterer) FilterDailyDistributionChanged(opts *bind.FilterOpts) (*WitnessDailyDistributionChangedIterator, error) {
logs, sub, err := _Witness.contract.FilterLogs(opts, "DailyDistributionChanged")
if err != nil {
return nil, err
}
return &WitnessDailyDistributionChangedIterator{contract: _Witness.contract, event: "DailyDistributionChanged", logs: logs, sub: sub}, nil
}
// WatchDailyDistributionChanged is a free log subscription operation binding the contract event 0xb3ae8e2fdcbd3e5bc919976d8ad797511092f7b991c4a29813a72b0b09e79458.
//
// Solidity: event DailyDistributionChanged(uint256 dailyDistribution)
func (_Witness *WitnessFilterer) WatchDailyDistributionChanged(opts *bind.WatchOpts, sink chan<- *WitnessDailyDistributionChanged) (event.Subscription, error) {
logs, sub, err := _Witness.contract.WatchLogs(opts, "DailyDistributionChanged")
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(WitnessDailyDistributionChanged)
if err := _Witness.contract.UnpackLog(event, "DailyDistributionChanged", 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
}
// ParseDailyDistributionChanged is a log parse operation binding the contract event 0xb3ae8e2fdcbd3e5bc919976d8ad797511092f7b991c4a29813a72b0b09e79458.
//
// Solidity: event DailyDistributionChanged(uint256 dailyDistribution)
func (_Witness *WitnessFilterer) ParseDailyDistributionChanged(log types.Log) (*WitnessDailyDistributionChanged, error) {
event := new(WitnessDailyDistributionChanged)
if err := _Witness.contract.UnpackLog(event, "DailyDistributionChanged", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// WitnessMerkleRootChangedIterator is returned from FilterMerkleRootChanged and is used to iterate over the raw logs and unpacked data for MerkleRootChanged events raised by the Witness contract.
type WitnessMerkleRootChangedIterator struct {
Event *WitnessMerkleRootChanged // 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 *WitnessMerkleRootChangedIterator) 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(WitnessMerkleRootChanged)
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(WitnessMerkleRootChanged)
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 returns any retrieval or parsing error occurred during filtering.
func (it *WitnessMerkleRootChangedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *WitnessMerkleRootChangedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// WitnessMerkleRootChanged represents a MerkleRootChanged event raised by the Witness contract.
type WitnessMerkleRootChanged struct {
Date string
MerkleRoot [32]byte
MerkleSumRoot [32]byte
Raw types.Log // Blockchain specific contextual infos
}
// FilterMerkleRootChanged is a free log retrieval operation binding the contract event 0x03802ed049c84cd4e511bf3c40208130b1c5d73897142ecfb572a739c9e9f06d.
//
// Solidity: event MerkleRootChanged(string date, bytes32 merkleRoot, bytes32 merkleSumRoot)
func (_Witness *WitnessFilterer) FilterMerkleRootChanged(opts *bind.FilterOpts) (*WitnessMerkleRootChangedIterator, error) {
logs, sub, err := _Witness.contract.FilterLogs(opts, "MerkleRootChanged")
if err != nil {
return nil, err
}
return &WitnessMerkleRootChangedIterator{contract: _Witness.contract, event: "MerkleRootChanged", logs: logs, sub: sub}, nil
}
// WatchMerkleRootChanged is a free log subscription operation binding the contract event 0x03802ed049c84cd4e511bf3c40208130b1c5d73897142ecfb572a739c9e9f06d.
//
// Solidity: event MerkleRootChanged(string date, bytes32 merkleRoot, bytes32 merkleSumRoot)
func (_Witness *WitnessFilterer) WatchMerkleRootChanged(opts *bind.WatchOpts, sink chan<- *WitnessMerkleRootChanged) (event.Subscription, error) {
logs, sub, err := _Witness.contract.WatchLogs(opts, "MerkleRootChanged")
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(WitnessMerkleRootChanged)
if err := _Witness.contract.UnpackLog(event, "MerkleRootChanged", 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
}
// ParseMerkleRootChanged is a log parse operation binding the contract event 0x03802ed049c84cd4e511bf3c40208130b1c5d73897142ecfb572a739c9e9f06d.
//
// Solidity: event MerkleRootChanged(string date, bytes32 merkleRoot, bytes32 merkleSumRoot)
func (_Witness *WitnessFilterer) ParseMerkleRootChanged(log types.Log) (*WitnessMerkleRootChanged, error) {
event := new(WitnessMerkleRootChanged)
if err := _Witness.contract.UnpackLog(event, "MerkleRootChanged", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// WitnessMerkleRootSubmittedIterator is returned from FilterMerkleRootSubmitted and is used to iterate over the raw logs and unpacked data for MerkleRootSubmitted events raised by the Witness contract.
type WitnessMerkleRootSubmittedIterator struct {
Event *WitnessMerkleRootSubmitted // 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 *WitnessMerkleRootSubmittedIterator) 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(WitnessMerkleRootSubmitted)
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(WitnessMerkleRootSubmitted)
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 returns any retrieval or parsing error occurred during filtering.
func (it *WitnessMerkleRootSubmittedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *WitnessMerkleRootSubmittedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// WitnessMerkleRootSubmitted represents a MerkleRootSubmitted event raised by the Witness contract.
type WitnessMerkleRootSubmitted struct {
Addr common.Address
MerkleRoot [32]byte
MerkleSumRoot [32]byte
Count *big.Int
DailySubmitCount *big.Int
Raw types.Log // Blockchain specific contextual infos
}
// FilterMerkleRootSubmitted is a free log retrieval operation binding the contract event 0x7c0db56049d8c21ac04eb9f10f3a12460a3cd42c97482ed65838b868f685a34d.
//
// Solidity: event MerkleRootSubmitted(address indexed addr, bytes32 merkleRoot, bytes32 merkleSumRoot, uint256 indexed count, uint256 indexed dailySubmitCount)
func (_Witness *WitnessFilterer) FilterMerkleRootSubmitted(opts *bind.FilterOpts, addr []common.Address, count []*big.Int, dailySubmitCount []*big.Int) (*WitnessMerkleRootSubmittedIterator, error) {
var addrRule []interface{}
for _, addrItem := range addr {
addrRule = append(addrRule, addrItem)
}
var countRule []interface{}
for _, countItem := range count {
countRule = append(countRule, countItem)
}
var dailySubmitCountRule []interface{}
for _, dailySubmitCountItem := range dailySubmitCount {
dailySubmitCountRule = append(dailySubmitCountRule, dailySubmitCountItem)
}
logs, sub, err := _Witness.contract.FilterLogs(opts, "MerkleRootSubmitted", addrRule, countRule, dailySubmitCountRule)
if err != nil {
return nil, err
}
return &WitnessMerkleRootSubmittedIterator{contract: _Witness.contract, event: "MerkleRootSubmitted", logs: logs, sub: sub}, nil
}
// WatchMerkleRootSubmitted is a free log subscription operation binding the contract event 0x7c0db56049d8c21ac04eb9f10f3a12460a3cd42c97482ed65838b868f685a34d.
//
// Solidity: event MerkleRootSubmitted(address indexed addr, bytes32 merkleRoot, bytes32 merkleSumRoot, uint256 indexed count, uint256 indexed dailySubmitCount)
func (_Witness *WitnessFilterer) WatchMerkleRootSubmitted(opts *bind.WatchOpts, sink chan<- *WitnessMerkleRootSubmitted, addr []common.Address, count []*big.Int, dailySubmitCount []*big.Int) (event.Subscription, error) {
var addrRule []interface{}
for _, addrItem := range addr {
addrRule = append(addrRule, addrItem)
}
var countRule []interface{}
for _, countItem := range count {
countRule = append(countRule, countItem)
}
var dailySubmitCountRule []interface{}
for _, dailySubmitCountItem := range dailySubmitCount {
dailySubmitCountRule = append(dailySubmitCountRule, dailySubmitCountItem)
}
logs, sub, err := _Witness.contract.WatchLogs(opts, "MerkleRootSubmitted", addrRule, countRule, dailySubmitCountRule)
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(WitnessMerkleRootSubmitted)
if err := _Witness.contract.UnpackLog(event, "MerkleRootSubmitted", 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
}
// ParseMerkleRootSubmitted is a log parse operation binding the contract event 0x7c0db56049d8c21ac04eb9f10f3a12460a3cd42c97482ed65838b868f685a34d.
//
// Solidity: event MerkleRootSubmitted(address indexed addr, bytes32 merkleRoot, bytes32 merkleSumRoot, uint256 indexed count, uint256 indexed dailySubmitCount)
func (_Witness *WitnessFilterer) ParseMerkleRootSubmitted(log types.Log) (*WitnessMerkleRootSubmitted, error) {
event := new(WitnessMerkleRootSubmitted)
if err := _Witness.contract.UnpackLog(event, "MerkleRootSubmitted", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// WitnessMerkleRootThresholdChangedIterator is returned from FilterMerkleRootThresholdChanged and is used to iterate over the raw logs and unpacked data for MerkleRootThresholdChanged events raised by the Witness contract.
type WitnessMerkleRootThresholdChangedIterator struct {
Event *WitnessMerkleRootThresholdChanged // 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 *WitnessMerkleRootThresholdChangedIterator) 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(WitnessMerkleRootThresholdChanged)
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(WitnessMerkleRootThresholdChanged)
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 returns any retrieval or parsing error occurred during filtering.
func (it *WitnessMerkleRootThresholdChangedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *WitnessMerkleRootThresholdChangedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// WitnessMerkleRootThresholdChanged represents a MerkleRootThresholdChanged event raised by the Witness contract.
type WitnessMerkleRootThresholdChanged struct {
MerkleRootThreshold *big.Int
Raw types.Log // Blockchain specific contextual infos
}
// FilterMerkleRootThresholdChanged is a free log retrieval operation binding the contract event 0xd43620d8f66512fa8246fc8c49d14f776a9938857d9e877639cc92a2955d5a4c.
//
// Solidity: event MerkleRootThresholdChanged(uint256 merkleRootThreshold)
func (_Witness *WitnessFilterer) FilterMerkleRootThresholdChanged(opts *bind.FilterOpts) (*WitnessMerkleRootThresholdChangedIterator, error) {
logs, sub, err := _Witness.contract.FilterLogs(opts, "MerkleRootThresholdChanged")
if err != nil {
return nil, err
}
return &WitnessMerkleRootThresholdChangedIterator{contract: _Witness.contract, event: "MerkleRootThresholdChanged", logs: logs, sub: sub}, nil
}
// WatchMerkleRootThresholdChanged is a free log subscription operation binding the contract event 0xd43620d8f66512fa8246fc8c49d14f776a9938857d9e877639cc92a2955d5a4c.
//
// Solidity: event MerkleRootThresholdChanged(uint256 merkleRootThreshold)
func (_Witness *WitnessFilterer) WatchMerkleRootThresholdChanged(opts *bind.WatchOpts, sink chan<- *WitnessMerkleRootThresholdChanged) (event.Subscription, error) {
logs, sub, err := _Witness.contract.WatchLogs(opts, "MerkleRootThresholdChanged")
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(WitnessMerkleRootThresholdChanged)
if err := _Witness.contract.UnpackLog(event, "MerkleRootThresholdChanged", 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
}
// ParseMerkleRootThresholdChanged is a log parse operation binding the contract event 0xd43620d8f66512fa8246fc8c49d14f776a9938857d9e877639cc92a2955d5a4c.
//
// Solidity: event MerkleRootThresholdChanged(uint256 merkleRootThreshold)
func (_Witness *WitnessFilterer) ParseMerkleRootThresholdChanged(log types.Log) (*WitnessMerkleRootThresholdChanged, error) {
event := new(WitnessMerkleRootThresholdChanged)
if err := _Witness.contract.UnpackLog(event, "MerkleRootThresholdChanged", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// WitnessOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the Witness contract.
type WitnessOwnershipTransferredIterator struct {
Event *WitnessOwnershipTransferred // 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 *WitnessOwnershipTransferredIterator) 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(WitnessOwnershipTransferred)
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(WitnessOwnershipTransferred)
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 returns any retrieval or parsing error occurred during filtering.
func (it *WitnessOwnershipTransferredIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *WitnessOwnershipTransferredIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// WitnessOwnershipTransferred represents a OwnershipTransferred event raised by the Witness contract.
type WitnessOwnershipTransferred struct {
PreviousOwner common.Address
NewOwner common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
//
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_Witness *WitnessFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*WitnessOwnershipTransferredIterator, error) {
var previousOwnerRule []interface{}
for _, previousOwnerItem := range previousOwner {
previousOwnerRule = append(previousOwnerRule, previousOwnerItem)
}
var newOwnerRule []interface{}
for _, newOwnerItem := range newOwner {
newOwnerRule = append(newOwnerRule, newOwnerItem)
}
logs, sub, err := _Witness.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule)
if err != nil {
return nil, err
}
return &WitnessOwnershipTransferredIterator{contract: _Witness.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil
}
// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
//
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_Witness *WitnessFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *WitnessOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) {
var previousOwnerRule []interface{}
for _, previousOwnerItem := range previousOwner {
previousOwnerRule = append(previousOwnerRule, previousOwnerItem)
}
var newOwnerRule []interface{}
for _, newOwnerItem := range newOwner {
newOwnerRule = append(newOwnerRule, newOwnerItem)
}
logs, sub, err := _Witness.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule)
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(WitnessOwnershipTransferred)
if err := _Witness.contract.UnpackLog(event, "OwnershipTransferred", 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
}
// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0.
//
// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
func (_Witness *WitnessFilterer) ParseOwnershipTransferred(log types.Log) (*WitnessOwnershipTransferred, error) {
event := new(WitnessOwnershipTransferred)
if err := _Witness.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// WitnessWitnessChangedIterator is returned from FilterWitnessChanged and is used to iterate over the raw logs and unpacked data for WitnessChanged events raised by the Witness contract.
type WitnessWitnessChangedIterator struct {
Event *WitnessWitnessChanged // 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 *WitnessWitnessChangedIterator) 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(WitnessWitnessChanged)
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(WitnessWitnessChanged)
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 returns any retrieval or parsing error occurred during filtering.
func (it *WitnessWitnessChangedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *WitnessWitnessChangedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// WitnessWitnessChanged represents a WitnessChanged event raised by the Witness contract.
type WitnessWitnessChanged struct {
Addr common.Address
Ok bool
Count *big.Int
Raw types.Log // Blockchain specific contextual infos
}
// FilterWitnessChanged is a free log retrieval operation binding the contract event 0xfae38e0b0395412c5ac55a5b9231b2950defd7f1a4ba46b9a5317971e1aacab9.
//
// Solidity: event WitnessChanged(address indexed addr, bool indexed ok, uint256 indexed count)
func (_Witness *WitnessFilterer) FilterWitnessChanged(opts *bind.FilterOpts, addr []common.Address, ok []bool, count []*big.Int) (*WitnessWitnessChangedIterator, error) {
var addrRule []interface{}
for _, addrItem := range addr {
addrRule = append(addrRule, addrItem)
}
var okRule []interface{}
for _, okItem := range ok {
okRule = append(okRule, okItem)
}
var countRule []interface{}
for _, countItem := range count {
countRule = append(countRule, countItem)
}
logs, sub, err := _Witness.contract.FilterLogs(opts, "WitnessChanged", addrRule, okRule, countRule)
if err != nil {
return nil, err
}
return &WitnessWitnessChangedIterator{contract: _Witness.contract, event: "WitnessChanged", logs: logs, sub: sub}, nil
}
// WatchWitnessChanged is a free log subscription operation binding the contract event 0xfae38e0b0395412c5ac55a5b9231b2950defd7f1a4ba46b9a5317971e1aacab9.
//
// Solidity: event WitnessChanged(address indexed addr, bool indexed ok, uint256 indexed count)
func (_Witness *WitnessFilterer) WatchWitnessChanged(opts *bind.WatchOpts, sink chan<- *WitnessWitnessChanged, addr []common.Address, ok []bool, count []*big.Int) (event.Subscription, error) {
var addrRule []interface{}
for _, addrItem := range addr {
addrRule = append(addrRule, addrItem)
}
var okRule []interface{}
for _, okItem := range ok {
okRule = append(okRule, okItem)
}
var countRule []interface{}
for _, countItem := range count {
countRule = append(countRule, countItem)
}
logs, sub, err := _Witness.contract.WatchLogs(opts, "WitnessChanged", addrRule, okRule, countRule)
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(WitnessWitnessChanged)
if err := _Witness.contract.UnpackLog(event, "WitnessChanged", 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
}
// ParseWitnessChanged is a log parse operation binding the contract event 0xfae38e0b0395412c5ac55a5b9231b2950defd7f1a4ba46b9a5317971e1aacab9.
//
// Solidity: event WitnessChanged(address indexed addr, bool indexed ok, uint256 indexed count)
func (_Witness *WitnessFilterer) ParseWitnessChanged(log types.Log) (*WitnessWitnessChanged, error) {
event := new(WitnessWitnessChanged)
if err := _Witness.contract.UnpackLog(event, "WitnessChanged", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
package core
import (
"context"
"crypto/ecdsa"
"fmt"
"math/big"
"time"
"witness/contract"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
log "github.com/sirupsen/logrus"
)
type ChainRPC struct {
rpc *ethclient.Client
chainID *big.Int
privateKey *ecdsa.PrivateKey
storageContract *contract.AddressStorage
witnessContract *contract.Witness
}
func newChain(rpc, privateKey, storageCa, witnessCa string) *ChainRPC {
ethRpc, err := ethclient.Dial(rpc)
if err != nil {
panic(err)
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
chainID, err := ethRpc.ChainID(ctx)
if err != nil {
panic(err)
}
log.WithField("chain_id", chainID.String()).Info("rpc get chain id")
storage, err := contract.NewAddressStorage(common.HexToAddress(storageCa), ethRpc)
if err != nil {
panic(err)
}
witness, err := contract.NewWitness(common.HexToAddress(witnessCa), ethRpc)
if err != nil {
panic(err)
}
binPrivateKey, err := hexutil.Decode(privateKey)
if err == hexutil.ErrMissingPrefix {
binPrivateKey, err = hexutil.Decode("0x" + privateKey)
if err != nil {
panic(err)
}
}
if err != nil && err != hexutil.ErrMissingPrefix {
panic(err)
}
k, _ := btcec.PrivKeyFromBytes(binPrivateKey)
return &ChainRPC{rpc: ethRpc, storageContract: storage, witnessContract: witness, chainID: chainID, privateKey: k.ToECDSA()}
}
func (r *ChainRPC) GetContainerAddresses() (addrs []common.Address, err error) {
return r.storageContract.GetContainerAddresses(nil)
}
func (r *ChainRPC) GetNMAddresses() (addrs []common.Address, err error) {
return r.storageContract.GetNmAddresses(nil)
}
func (r *ChainRPC) SubmitProofs(date string, merkleSumTreeRoot, merkleTreeRoot common.Hash) (txHash common.Hash, err error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
opts, err := bind.NewKeyedTransactorWithChainID(r.privateKey, r.chainID)
if err != nil {
return
}
opts.Context = ctx
signedTx, err := r.witnessContract.SubmitMerkleRoot(opts, date, merkleSumTreeRoot, merkleTreeRoot)
if err != nil {
return
}
receipt, err := r.WaitForReceipt(ctx, signedTx.Hash())
if err != nil {
return
}
if receipt.Status != types.ReceiptStatusSuccessful {
return common.Hash{}, fmt.Errorf("tx %s failed", signedTx.Hash().Hex())
}
return signedTx.Hash(), nil
}
func (r *ChainRPC) WaitForReceipt(ctx context.Context, txHash common.Hash) (receipt *types.Receipt, err error) {
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
receipt, err = r.rpc.TransactionReceipt(ctx, txHash)
if err == nil {
return receipt, nil
}
if err == ethereum.NotFound {
time.Sleep(time.Second * 2)
continue
}
return nil, err
}
}
}
package core
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/trie"
"github.com/gogo/protobuf/proto"
witnessv1 "github.com/odysseus/odysseus-protocol/gen/proto/go/witness/v1"
log "github.com/sirupsen/logrus"
)
type StateDB struct {
db *trie.Database
trie *trie.Trie
}
func NewStateDB(db *trie.Database, root common.Hash) (statedb *StateDB, err error) {
t, err := trie.New(common.Hash{}, root, db)
if err != nil {
return nil, err
}
return &StateDB{
db: db,
trie: t,
}, nil
}
func (s *StateDB) GetMinerObject(miner common.Address) (object *witnessv1.MinerObject) {
object = &witnessv1.MinerObject{}
k := crypto.Keccak256(miner.Bytes())
v, err := s.trie.TryGet(k)
if err != nil {
return nil
}
err = proto.Unmarshal(v, object)
if err != nil {
return nil
}
return
}
func (s *StateDB) UpdateMinerObject(miner common.Address, object *witnessv1.MinerObject) (err error) {
k := crypto.Keccak256(miner.Bytes())
v, err := proto.Marshal(object)
if err != nil {
return
}
err = s.trie.TryUpdate(k, v)
return
}
func (s *StateDB) Commit() (root common.Hash, err error) {
root, nodes, err := s.trie.Commit(false)
if err != nil {
return
}
nodesSet := trie.NewMergedNodeSet()
if nodes != nil {
err = nodesSet.Merge(nodes)
if err != nil {
return
}
}
err = s.db.Update(nodesSet)
if err != nil {
return
}
err = s.db.Commit(root, true, nil)
return root, err
}
func (s *StateDB) IterAllObject() (objects []*witnessv1.MinerObject) {
iter := s.trie.NodeIterator(nil)
for iter.Next(true) {
if !iter.Leaf() {
continue
}
v := iter.LeafBlob()
object := &witnessv1.MinerObject{}
err := proto.Unmarshal(v, object)
if err != nil {
continue
}
log.WithField("workload", object.Workload).Debug("miner object")
objects = append(objects, object)
}
return
}
package core
import (
"fmt"
"math/big"
"math/rand"
"sort"
"sync"
"time"
"witness/conf"
"witness/tree"
"witness/util"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb/leveldb"
"github.com/ethereum/go-ethereum/trie"
witnessv1 "github.com/odysseus/odysseus-protocol/gen/proto/go/witness/v1"
log "github.com/sirupsen/logrus"
)
type Witness struct {
db *trie.Database
state *StateDB
pendingProof map[common.Address]*witnessv1.ValidatedProof
mtTreeCache map[string]*tree.MerkleTree
date string
rpc *ChainRPC
containerAddresses []common.Address
nmAddresses []common.Address
sync.Mutex
}
func NewWitness(cfg *conf.Config) *Witness {
log.Infoln("######", cfg.PrivateKey)
_rpc := newChain(cfg.ChainRPC, cfg.PrivateKey, cfg.StoreContract, cfg.WitnessContract)
diskDB, err := leveldb.New(cfg.DataDir, 128, 1024, "", false)
if err != nil {
panic(err)
}
var lastDay string
ok, err := diskDB.Has([]byte("lastday"))
if err != nil {
panic(err)
}
var stateRoot common.Hash
if ok {
val, _ := diskDB.Get([]byte("lastday"))
log.WithField("last day", string(val)).Info("diskdb get last day")
lastDay = string(val)
root, _ := diskDB.Get([]byte(fmt.Sprintf("sroot:%s", string(val))))
stateRoot = common.BytesToHash(root)
}
trieDB := trie.NewDatabase(diskDB)
log.WithField("root", stateRoot).Info("new witness open trie")
stateDB, err := NewStateDB(trieDB, stateRoot)
if err != nil {
panic(err)
}
w := &Witness{
db: trieDB,
state: stateDB,
pendingProof: make(map[common.Address]*witnessv1.ValidatedProof),
mtTreeCache: make(map[string]*tree.MerkleTree),
rpc: _rpc,
date: lastDay,
}
w.LoadMerkleProof(lastDay)
go w.UpdateAddress()
<-time.After(time.Second * 3)
go w.Ticker()
// go w.Mock()
return w
}
func (w *Witness) AddPendingProof(miner common.Address, proofs []*witnessv1.ValidatedProof) {
w.Lock()
defer w.Unlock()
var workload uint64
var pendingWorkload uint64
currentPendingProof, ok := w.pendingProof[miner]
if ok {
workload = currentPendingProof.Workload
pendingWorkload = currentPendingProof.Workload
}
for _, proof := range proofs {
workload += proof.Workload
}
w.pendingProof[miner] = &witnessv1.ValidatedProof{Workload: workload}
log.WithFields(log.Fields{
"miner": miner.Hex(),
"proof_count": len(proofs),
"current_workload": workload,
"pending_workload": pendingWorkload,
"workload_diff": workload - pendingWorkload,
}).Debug("add validated proof")
}
func (w *Witness) ProcessDay() {
w.date = time.Now().UTC().AddDate(0, 0, -1).Format("2006-01-02")
dayProof := w.Commit()
mstRoot, _, err := w.CommitMST(dayProof)
if err != nil {
log.WithError(err).Error("failed to commit merkle sum tree")
return
}
objects := w.state.IterAllObject()
mtRoot, err := w.CommitMT(objects)
if err != nil {
log.WithError(err).Error("failed to commit merkle tree")
return
}
err = w.db.DiskDB().Put([]byte("lastday"), []byte(w.date))
if err != nil {
log.WithError(err).Error("failed to update last day")
return
}
txHash, err := w.rpc.SubmitProofs(w.date, mstRoot, mtRoot)
if err != nil {
log.WithError(err).Error("submit proofs")
return
}
log.WithField("tx_hash", txHash.Hex()).Info("submit proofs")
log.Info("process day done")
}
func (w *Witness) Commit() (dayProofs map[common.Address]*witnessv1.ValidatedProof) {
st := time.Now()
proof := w.RefreshPendingProof()
for miner, proof := range proof {
err := w.SealProof(miner, proof)
if err != nil {
return
}
}
root, err := w.state.Commit()
if err != nil {
return
}
log.WithFields(log.Fields{"root": root.Hex(), "cost": time.Since(st).String()}).Info("commit state root")
err = w.db.DiskDB().Put([]byte(fmt.Sprintf("sroot:%s", w.date)), root.Bytes())
if err != nil {
log.WithError(err).Error("failed to update state root")
return
}
return proof
}
func (w *Witness) SealProof(miner common.Address, proof *witnessv1.ValidatedProof) (err error) {
minerObject := w.state.GetMinerObject(miner)
minerObject.Workload += proof.Workload
minerObject.Balance += proof.Balance
err = w.state.UpdateMinerObject(miner, minerObject)
if err != nil {
return err
}
log.WithFields(log.Fields{
"miner": miner.Hex(),
"old_workload": minerObject.Workload - proof.Workload,
"new_workload": minerObject.Workload,
"old_balance": minerObject.Balance - proof.Balance,
"new_balance": minerObject.Balance,
}).Info("seal proof")
return err
}
func (w *Witness) RefreshPendingProof() (proof map[common.Address]*witnessv1.ValidatedProof) {
w.Lock()
defer w.Unlock()
proof = make(map[common.Address]*witnessv1.ValidatedProof)
for miner, pendingProof := range w.pendingProof {
proof[miner] = pendingProof
}
w.pendingProof = make(map[common.Address]*witnessv1.ValidatedProof)
return
}
// CommitMST commit workload of per day
func (w *Witness) CommitMST(proofMap map[common.Address]*witnessv1.ValidatedProof) (root common.Hash, sum *big.Int, err error) {
if len(proofMap) == 0 {
return common.Hash{}, big.NewInt(0), nil
}
rawKeys := make([]common.Address, 0)
keys := make([][32]byte, len(proofMap))
dbKey := make([]byte, 0)
dbVal := make([]byte, 0)
vals := make([]*big.Int, len(proofMap))
for key := range proofMap {
rawKeys = append(rawKeys, key)
}
sort.Sort(util.AddressSlice(rawKeys))
for i, key := range rawKeys {
keys[i] = crypto.Keccak256Hash(key.Bytes())
dbKey = append(dbKey, keys[i][:]...)
vals[i] = new(big.Int).SetUint64(proofMap[key].Workload)
dbVal = append(append(dbVal, vals[i].Bytes()...), []byte(":")...)
}
st := time.Now()
nodes, sums := tree.ComputeMST(keys, vals)
err = w.db.DiskDB().Put([]byte(fmt.Sprintf("mstroot:%s", w.date)), nodes[0][:])
if err != nil {
log.Error(err)
return
}
err = w.db.DiskDB().Put([]byte(fmt.Sprintf("mstsum:%s", w.date)), sums[0].Bytes())
if err != nil {
log.Error(err)
return
}
err = w.db.DiskDB().Put([]byte(fmt.Sprintf("mstk:%s", w.date)), dbKey)
if err != nil {
return
}
err = w.db.DiskDB().Put([]byte(fmt.Sprintf("mstv:%s", w.date)), dbVal)
if err != nil {
return
}
log.WithFields(log.Fields{
"root": common.Hash(nodes[0]).Hex(),
"sum": sums[0].String(),
"cost": time.Since(st).String(),
}).Info("commit MST root")
return nodes[0], sums[0], nil
}
// CommitMT commit all workload
func (w *Witness) CommitMT(objects []*witnessv1.MinerObject) (root common.Hash, err error) {
merkleProofs := make(tree.Proofs, 0)
dbProofs := make([]byte, 0)
for _, object := range objects {
payload := append(common.HexToAddress(object.Miner).Bytes(), big.NewInt(0).SetUint64(object.Workload).Bytes()...)
_proof := crypto.Keccak256Hash(payload)
merkleProofs = append(merkleProofs, _proof)
dbProofs = append(dbProofs, _proof[:]...)
}
mtTree, err := tree.NewMerkleTree(merkleProofs)
if err != nil {
return
}
root = mtTree.GetRoot()
st := time.Now()
err = w.db.DiskDB().Put([]byte(fmt.Sprintf("mtroot:%s", w.date)), root.Bytes())
if err != nil {
return
}
log.WithFields(log.Fields{
"k": fmt.Sprintf("mtroot:%s", w.date),
"v": root.String(),
}).Debug()
err = w.db.DiskDB().Put([]byte(fmt.Sprintf("mtk:%s", w.date)), dbProofs)
if err != nil {
return
}
log.WithFields(log.Fields{
"k": fmt.Sprintf("mtk:%s", w.date),
"v_length": len(dbProofs),
}).Debug()
w.mtTreeCache[w.date] = mtTree
log.WithFields(log.Fields{
"root": root.Hex(),
"cost": time.Since(st).String(),
}).Info("commit MT root")
return
}
func (w *Witness) Ticker() {
duration := time.Duration(24) * time.Hour
executionTime := time.Date(time.Now().Year(), time.Now().Month(), time.Now().Day(), 0, 0, 0, 0, time.UTC).Add(duration)
// executionTime := time.Now().Add(time.Second * 30)
waitTime := executionTime.Sub(time.Now())
timer := time.NewTimer(waitTime)
log.WithField("wait_time", waitTime.String()).Info("prepare commit task")
for {
<-timer.C
w.ProcessDay()
executionTime = executionTime.Add(duration)
waitTime = executionTime.Sub(time.Now())
timer.Reset(waitTime)
log.WithField("wait time", waitTime.String()).Info("prepare commit task")
}
}
func (w *Witness) Mock() {
addresses := make([]common.Address, 10)
rand.Seed(time.Now().Unix())
for i := 0; i < 10; i++ {
b20 := make([]byte, 20)
rand.Read(b20)
addresses[i] = common.BytesToAddress(b20)
}
for {
time.Sleep(time.Second)
w.AddPendingProof(addresses[rand.Intn(10)], []*witnessv1.ValidatedProof{
{
Workload: uint64((rand.Int63n(9) + 1) * 100),
},
})
}
}
func (w *Witness) UpdateAddress() {
ticker := time.NewTicker(time.Minute * 10)
defer ticker.Stop()
log.Info("start update address task")
for {
addrs, err := w.rpc.GetContainerAddresses()
if err != nil {
log.WithError(err).Error("failed to get container addresses")
} else {
w.containerAddresses = addrs
}
addrs, err = w.rpc.GetNMAddresses()
if err != nil {
log.WithError(err).Error("failed to get NM addresses")
} else {
w.nmAddresses = addrs
}
log.WithFields(log.Fields{
"container_count": len(w.containerAddresses),
"nm_count": len(w.nmAddresses),
}).Info("store contract update address")
<-ticker.C
}
}
func (w *Witness) IsContainerAddress(address common.Address) bool {
for _, addr := range w.containerAddresses {
if addr.Hex() == address.Hex() {
return true
}
}
return false
}
func (w *Witness) IsNMAddress(address common.Address) bool {
for _, addr := range w.nmAddresses {
if addr.Hex() == address.Hex() {
return true
}
}
return false
}
func (w *Witness) GetMerkleProof(address common.Address) (workload uint64, proofs []common.Hash) {
w.Lock()
cacheTree, ok := w.mtTreeCache[w.date]
w.Unlock()
if !ok {
// todo
}
object := w.state.GetMinerObject(address)
if object == nil {
return 0, nil
}
payload := append(address.Bytes(), big.NewInt(0).SetUint64(object.Workload).Bytes()...)
leaf := crypto.Keccak256Hash(payload)
proofs, err := cacheTree.GetProof(leaf)
if err != nil {
log.WithError(err).Error("failed to get merkle proof")
return 0, make([]common.Hash, 0)
}
return object.Workload, proofs
}
func (w *Witness) GetPendingWorkload(address common.Address) (workload uint64) {
w.Lock()
proof, ok := w.pendingProof[address]
w.Unlock()
if !ok {
return 0
}
return proof.Workload
}
func (w *Witness) LoadMerkleProof(date string) {
merkleTreeKey := fmt.Sprintf("mtk:%s", date)
data, err := w.db.DiskDB().Get([]byte(merkleTreeKey))
if err != nil {
log.WithError(err).Error("failed to load merkle proof")
return
}
proofs := make([]common.Hash, len(data)/32)
for i := 0; i < len(data)/32; i++ {
copy(proofs[i][:], data[i*32:(i+1)*32])
}
mTree, err := tree.NewMerkleTree(proofs)
if err != nil {
log.WithError(err).Error("failed to load merkle proof")
return
}
w.Lock()
w.mtTreeCache[date] = mTree
w.Unlock()
log.WithFields(log.Fields{"date": date, "root": mTree.GetRoot().Hex()}).Info("load merkle tree")
return
}
......@@ -3,24 +3,157 @@ module witness
go 1.19
require (
github.com/btcsuite/btcd/btcec/v2 v2.3.2
github.com/ethereum/go-ethereum v1.10.26
github.com/gogo/protobuf v1.3.2
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/libp2p/go-libp2p v0.26.0
github.com/libp2p/go-libp2p-pubsub v0.9.1
github.com/multiformats/go-multiaddr v0.12.1
github.com/odysseus/odysseus-protocol v0.0.0-00010101000000-000000000000
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.18.0
github.com/prysmaticlabs/prysm/v3 v3.2.2-rc.0
github.com/sirupsen/logrus v1.9.3
github.com/urfave/cli/v2 v2.27.1
google.golang.org/grpc v1.60.1
)
require (
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/VictoriaMetrics/fastcache v1.10.0 // indirect
github.com/aristanetworks/goarista v0.0.0-20200805130819-fd197cf57d96 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
github.com/flynn/noise v1.0.0 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 // indirect
github.com/hashicorp/go-bexpr v0.1.10 // indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/holiman/uint256 v1.2.4 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/ipfs/go-cid v0.4.1 // indirect
github.com/ipfs/go-log/v2 v2.5.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/klauspost/compress v1.17.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/libp2p/go-flow-metrics v0.1.0 // indirect
github.com/libp2p/go-libp2p-asn-util v0.3.0 // indirect
github.com/libp2p/go-msgio v0.3.0 // indirect
github.com/libp2p/go-nat v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect
github.com/libp2p/go-reuseport v0.4.0 // indirect
github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/miekg/dns v1.1.56 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/highwayhash v1.0.1 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/mitchellh/pointerstructure v1.2.0 // indirect
github.com/mr-tron/base58 v1.2.0 // indirect
github.com/multiformats/go-base32 v0.1.0 // indirect
github.com/multiformats/go-base36 v0.2.0 // indirect
github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/onsi/ginkgo/v2 v2.13.0 // indirect
github.com/opencontainers/runtime-spec v1.1.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/prometheus/tsdb v0.10.0 // indirect
github.com/prysmaticlabs/fastssz v0.0.0-20220628121656-93dfe28febab // indirect
github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 // indirect
github.com/prysmaticlabs/gohashtree v0.0.2-alpha // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
github.com/quic-go/quic-go v0.39.4 // indirect
github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rivo/uniseg v0.3.4 // indirect
github.com/rjeczalik/notify v0.9.1 // indirect
github.com/rs/cors v1.7.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/status-im/keycard-go v0.2.0 // indirect
github.com/stretchr/testify v1.8.2 // indirect
github.com/supranational/blst v0.3.11 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect
github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tyler-smith/go-bip39 v1.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20231213231151-1d8dd44e695e // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/dig v1.17.1 // indirect
go.uber.org/fx v1.20.1 // indirect
go.uber.org/mock v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.org/x/tools v0.16.0 // indirect
google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
nhooyr.io/websocket v1.8.7 // indirect
)
replace github.com/odysseus/odysseus-protocol => ../odysseus-protocol
replace github.com/MariusVanDerWijden/tx-fuzz => github.com/MariusVanDerWijden/tx-fuzz v1.3.2
This source diff could not be displayed because it is too large. You can view the blob instead.
package p2p
import (
"encoding/json"
"io"
"os"
)
const bootnodefile = ".bootnodes.json"
var bootnodes []string
func loadBootnodesFile() {
file, err := os.Open(bootnodefile)
if err != nil {
return
}
defer file.Close()
b, err := io.ReadAll(file)
if err != nil {
return
}
_ = json.Unmarshal(b, &bootnodes)
return
}
func attachBootnodeToFile(bootnode string) error {
for _, node := range bootnodes {
if node == bootnode {
return nil
}
}
bootnodes = append(bootnodes, bootnode)
b, err := json.Marshal(bootnodes)
if err != nil {
return err
}
file, err := os.OpenFile(bootnodefile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer file.Close()
_, err = file.Write(b)
return err
}
package p2p
import (
"context"
"github.com/gogo/protobuf/proto"
"github.com/pkg/errors"
)
// Broadcast a message to the p2p network, the message is assumed to be
// broadcasted to the current fork.
func (s *Service) Broadcast(ctx context.Context, msg proto.Message, topic string) error {
msgBytes, err := proto.Marshal(msg)
if err != nil {
return err
}
return s.broadcastObject(ctx, msgBytes, topic)
}
// method to broadcast messages to other peers in our gossip mesh.
func (s *Service) broadcastObject(ctx context.Context, obj []byte, topic string) error {
if err := s.PublishToTopic(ctx, topic, obj); err != nil {
err := errors.Wrap(err, "could not publish message")
return err
}
return nil
}
package p2p
// Config for the p2p service. These parameters are set from application level flags
// to initialize the p2p service.
type Config struct {
UseDiscovery bool
StaticPeers []string
BootstrapNodeAddr []string
Discv5BootStrapAddr []string
LocalIP string
HostAddress string
PrivateKeyPath string
TCPPort uint
UDPPort uint
MaxPeers uint
MaxInboundPeers uint
MaxOutboundPeers uint
IgnoreLocalIP bool
SingleNode bool
EnableProm bool
NebulaGrpcAddress string
}
package p2p
import (
"runtime"
"github.com/libp2p/go-libp2p/core/control"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/sirupsen/logrus"
)
// InterceptPeerDial tests whether we're permitted to Dial the specified peer.
func (_ *Service) InterceptPeerDial(_ peer.ID) (allow bool) {
return true
}
// InterceptAddrDial tests whether we're permitted to dial the specified
// multiaddr for the given peer.
func (s *Service) InterceptAddrDial(pid peer.ID, m multiaddr.Multiaddr) (allow bool) {
// Disallow bad peers from dialing in.
return !s.peers.IsBad(pid)
}
// InterceptAccept checks whether the incidental inbound connection is allowed.
func (s *Service) InterceptAccept(n network.ConnMultiaddrs) (allow bool) {
// Deny all incoming connections before we are ready
if !s.started {
return false
}
if !s.validateDial(n.RemoteMultiaddr()) {
// Allow other go-routines to run in the event
// we receive a large amount of junk connections.
runtime.Gosched()
log.WithFields(logrus.Fields{"peer": n.RemoteMultiaddr(),
"reason": "exceeded dial limit"}).Trace("Not accepting inbound dial from ip address")
return false
}
if s.isPeerAtLimit(true /* inbound */) {
log.WithFields(logrus.Fields{"peer": n.RemoteMultiaddr(),
"reason": "at peer limit"}).Trace("Not accepting inbound dial")
return false
}
return true
}
// InterceptSecured tests whether a given connection, now authenticated,
// is allowed.
func (_ *Service) InterceptSecured(_ network.Direction, _ peer.ID, _ network.ConnMultiaddrs) (allow bool) {
return true
}
// InterceptUpgraded tests whether a fully capable connection is allowed.
func (_ *Service) InterceptUpgraded(_ network.Conn) (allow bool, reason control.DisconnectReason) {
return true, 0
}
func (s *Service) validateDial(addr multiaddr.Multiaddr) bool {
_, err := manet.ToIP(addr)
return err == nil
}
package p2p
import (
"context"
"crypto/ecdsa"
"net"
"strings"
"time"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
ma "github.com/multiformats/go-multiaddr"
"github.com/pkg/errors"
ecdsaprysm "github.com/prysmaticlabs/prysm/v3/crypto/ecdsa"
)
// Listener defines the discovery V5 network interface that is used
// to communicate with other peers.
type Listener interface {
Self() *enode.Node
Close()
Lookup(enode.ID) []*enode.Node
Resolve(*enode.Node) *enode.Node
RandomNodes() enode.Iterator
Ping(*enode.Node) error
RequestENR(*enode.Node) (*enode.Node, error)
LocalNode() *enode.LocalNode
}
// listen for new nodes watches for new nodes in the network and adds them to the peerstore.
func (s *Service) listenForNewNodes() {
iterator := s.dv5Listener.RandomNodes()
iterator = enode.Filter(iterator, s.filterPeer)
defer iterator.Close()
for {
// Exit if service's context is canceled
if s.ctx.Err() != nil {
break
}
if s.isPeerAtLimit(false) {
// Pause the main loop for a period to stop looking
// for new peers.
log.Trace("Not looking for peers, at peer limit")
time.Sleep(pollingPeriod)
continue
}
exists := iterator.Next()
if !exists {
break
}
node := iterator.Node()
peerInfo, _, err := convertToAddrInfo(node)
if err != nil {
log.WithError(err).Error("Could not convert to peer info")
continue
}
// Make sure that peer is not dialed too often, for each connection attempt there's a backoff period.
s.peers.RandomizeBackOff(peerInfo.ID)
go func(info *peer.AddrInfo) {
if err := s.connectWithPeer(s.ctx, *info); err != nil {
log.WithError(err).Tracef("Could not connect with peer %s", info.String())
}
}(peerInfo)
}
}
func (s *Service) createListener(
ipAddr net.IP,
privKey *ecdsa.PrivateKey,
) (*discover.UDPv5, error) {
// BindIP is used to specify the ip
// on which we will bind our listener on
// by default we will listen to all interfaces.
var bindIP net.IP
switch udpVersionFromIP(ipAddr) {
case "udp4":
bindIP = net.IPv4zero
case "udp6":
bindIP = net.IPv6zero
default:
return nil, errors.New("invalid ip provided")
}
// If local ip is specified then use that instead.
if s.cfg.LocalIP != "" {
ipAddr = net.ParseIP(s.cfg.LocalIP)
if ipAddr == nil {
return nil, errors.New("invalid local ip provided")
}
bindIP = ipAddr
}
udpAddr := &net.UDPAddr{
IP: bindIP,
Port: int(s.cfg.UDPPort),
}
// Listen to all network interfaces
// for both ip protocols.
networkVersion := "udp"
conn, err := net.ListenUDP(networkVersion, udpAddr)
if err != nil {
return nil, errors.Wrap(err, "could not listen to UDP")
}
localNode, err := s.createLocalNode(
privKey,
ipAddr,
int(s.cfg.UDPPort),
int(s.cfg.TCPPort),
)
if err != nil {
return nil, errors.Wrap(err, "could not create local node")
}
if s.cfg.HostAddress != "" {
hostIP := net.ParseIP(s.cfg.HostAddress)
if hostIP.To4() == nil && hostIP.To16() == nil {
log.Errorf("Invalid host address given: %s", hostIP.String())
} else {
localNode.SetFallbackIP(hostIP)
localNode.SetStaticIP(hostIP)
}
}
dv5Cfg := discover.Config{
PrivateKey: privKey,
}
dv5Cfg.Bootnodes = []*enode.Node{}
for _, addr := range s.cfg.Discv5BootStrapAddr {
bootNode, err := enode.Parse(enode.ValidSchemes, addr)
if err != nil {
return nil, errors.Wrap(err, "could not bootstrap addr")
}
if s.cfg.IgnoreLocalIP && s.isLocalIP(bootNode.IP().String()) {
continue
}
dv5Cfg.Bootnodes = append(dv5Cfg.Bootnodes, bootNode)
}
listener, err := discover.ListenV5(conn, localNode, dv5Cfg)
if err != nil {
return nil, errors.Wrap(err, "could not listen to discV5")
}
return listener, nil
}
func (s *Service) createLocalNode(
privKey *ecdsa.PrivateKey,
ipAddr net.IP,
udpPort, tcpPort int,
) (*enode.LocalNode, error) {
db, err := enode.OpenDB("")
if err != nil {
return nil, errors.Wrap(err, "could not open node's peer database")
}
localNode := enode.NewLocalNode(db, privKey)
ipEntry := enr.IP(ipAddr)
udpEntry := enr.UDP(udpPort)
tcpEntry := enr.TCP(tcpPort)
localNode.Set(ipEntry)
localNode.Set(udpEntry)
localNode.Set(tcpEntry)
localNode.SetFallbackIP(ipAddr)
localNode.SetFallbackUDP(udpPort)
return localNode, nil
}
func (s *Service) startDiscoveryV5(
addr net.IP,
privKey *ecdsa.PrivateKey,
) (*discover.UDPv5, error) {
listener, err := s.createListener(addr, privKey)
if err != nil {
return nil, errors.Wrap(err, "could not create listener")
}
record := listener.Self()
log.WithField("ENR", record.String()).Info("Started discovery v5")
enrRecordToFile(record.String())
return listener, nil
}
// filterPeer validates each node that we retrieve from our dht. We
// try to ascertain that the peer can be a valid protocol peer.
// Validity Conditions:
// 1. The local node is still actively looking for peers to
// connect to.
// 2. Peer has a valid IP and TCP port set in their enr.
// 3. Peer hasn't been marked as 'bad'
// 4. Peer is not currently active or connected.
// 5. Peer is ready to receive incoming connections.
// 6. Peer's fork digest in their ENR matches that of
// our localnodes.
func (s *Service) filterPeer(node *enode.Node) bool {
// Ignore nil node entries passed in.
if node == nil {
return false
}
// ignore nodes with no ip address stored.
if node.IP() == nil {
return false
}
// do not dial nodes with their tcp ports not set
if err := node.Record().Load(enr.WithEntry("tcp", new(enr.TCP))); err != nil {
if !enr.IsNotFound(err) {
log.WithError(err).Debug("Could not retrieve tcp port")
}
return false
}
peerData, multiAddr, err := convertToAddrInfo(node)
if err != nil {
log.WithError(err).Debug("Could not convert to peer data")
return false
}
if s.peers.IsBad(peerData.ID) {
return false
}
if s.peers.IsActive(peerData.ID) {
// save cpu cycles by not dialing peers that are already connected.
return false
}
if s.host.Network().Connectedness(peerData.ID) == network.Connected {
return false
}
if !s.peers.IsReadyToDial(peerData.ID) {
return false
}
s.peers.Add(node.Record(), peerData.ID, multiAddr, network.DirUnknown)
return true
}
// PeersFromStringAddrs convers peer raw ENRs into multiaddrs for p2p.
func PeersFromStringAddrs(addrs []string) ([]ma.Multiaddr, error) {
var allAddrs []ma.Multiaddr
enodeString, _, multiAddrString := parseGenericAddrs(addrs)
for _, stringAddr := range multiAddrString {
addr, err := multiAddrFromString(stringAddr)
if err != nil {
return nil, errors.Wrapf(err, "Could not get multiaddr from string")
}
allAddrs = append(allAddrs, addr)
}
for _, stringAddr := range enodeString {
enodeAddr, err := enode.Parse(enode.ValidSchemes, stringAddr)
if err != nil {
return nil, errors.Wrapf(err, "Could not get enode from string")
}
addr, err := convertToSingleMultiAddr(enodeAddr)
if err != nil {
return nil, errors.Wrapf(err, "Could not get multiaddr")
}
allAddrs = append(allAddrs, addr)
}
return allAddrs, nil
}
func parseBootStrapAddrs(addrs []string) (discv5Nodes []string, nodeIPs []string) {
enrAddrs, domainAddrs := splitAddrs(addrs)
enrAddrs = append(enrAddrs, parseDNSAddrs(domainAddrs)...)
discv5Nodes, nodeIPs, _ = parseGenericAddrs(enrAddrs)
if len(discv5Nodes) == 0 {
log.Warn("No bootstrap addresses supplied")
}
return discv5Nodes, nodeIPs
}
// splitAddrs splits a list of addresses into two lists, one enr addresses and one domain addresses.
func splitAddrs(addrs []string) (enrAddrs, domainAddrs []string) {
for _, addr := range addrs {
if isDomain(addr) {
domainAddrs = append(domainAddrs, addr)
continue
}
enrAddrs = append(enrAddrs, addr)
}
return enrAddrs, domainAddrs
}
func parseGenericAddrs(addrs []string) (enodeString, ipString, multiAddrString []string) {
for _, addr := range addrs {
if addr == "" {
// Ignore empty entries
continue
}
eNode, err := enode.Parse(enode.ValidSchemes, addr)
if err == nil {
enodeString = append(enodeString, addr)
ipString = append(ipString, eNode.IP().String())
continue
}
_, err = multiAddrFromString(addr)
if err == nil {
multiAddrString = append(multiAddrString, addr)
ipAddr := strings.Split(addr, "/")[2]
ipString = append(ipString, ipAddr)
continue
}
log.WithError(err).Errorf("Invalid address of %s provided", addr)
}
return enodeString, ipString, multiAddrString
}
func isDomain(addr string) bool {
return strings.Contains(addr, ".")
}
// parseDNSAddrs parses a list of domain addresses and returns a list of ENR addresses.
func parseDNSAddrs(domains []string) (bootstrapNodes []string) {
for _, domain := range domains {
nodes := lookupDNS(domain)
bootstrapNodes = append(bootstrapNodes, nodes...)
}
return
}
func lookupDNS(domain string) (nodes []string) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
records, err := net.DefaultResolver.LookupTXT(ctx, domain)
if err != nil {
log.WithField("domain", domain).WithError(err).Error("Could not lookup TXT record")
return nil
}
for _, record := range records {
if strings.HasPrefix(record, "enr:") {
nodes = append(nodes, record)
}
}
return
}
func convertToMultiAddr(nodes []*enode.Node) []ma.Multiaddr {
var multiAddrs []ma.Multiaddr
for _, node := range nodes {
// ignore nodes with no ip address stored
if node.IP() == nil {
continue
}
multiAddr, err := convertToSingleMultiAddr(node)
if err != nil {
log.WithError(err).Error("Could not convert to multiAddr")
continue
}
multiAddrs = append(multiAddrs, multiAddr)
}
return multiAddrs
}
func convertToAddrInfo(node *enode.Node) (*peer.AddrInfo, ma.Multiaddr, error) {
multiAddr, err := convertToSingleMultiAddr(node)
if err != nil {
return nil, nil, err
}
info, err := peer.AddrInfoFromP2pAddr(multiAddr)
if err != nil {
return nil, nil, err
}
return info, multiAddr, nil
}
func convertToSingleMultiAddr(node *enode.Node) (ma.Multiaddr, error) {
pubkey := node.Pubkey()
assertedKey, err := ecdsaprysm.ConvertToInterfacePubkey(pubkey)
if err != nil {
return nil, errors.Wrap(err, "could not get pubkey")
}
id, err := peer.IDFromPublicKey(assertedKey)
if err != nil {
return nil, errors.Wrap(err, "could not get peer id")
}
return multiAddressBuilderWithID(node.IP().String(), "tcp", uint(node.TCP()), id)
}
func multiAddrFromString(address string) (ma.Multiaddr, error) {
return ma.NewMultiaddr(address)
}
func udpVersionFromIP(ipAddr net.IP) string {
if ipAddr.To4() != nil {
return "udp4"
}
return "udp6"
}
func (s *Service) isPeerAtLimit(inbound bool) bool {
currentConns := len(s.host.Network().Peers())
if inbound {
currentInboundConns := len(s.peers.InboundConnected())
if currentInboundConns >= int(s.cfg.MaxInboundPeers) {
return true
}
} else {
currentOutboundConns := len(s.peers.OutboundConnected())
if currentOutboundConns >= int(s.cfg.MaxOutboundPeers) {
return true
}
}
activePeers := len(s.peers.Active())
maxPeers := int(s.cfg.MaxPeers)
return currentConns >= maxPeers || activePeers >= maxPeers
}
package p2p
import (
"testing"
"github.com/ethereum/go-ethereum/p2p/enode"
)
func TestDecodeV5(t *testing.T) {
nodes := []string{
"enr:-JG4QL9QdmQjI-AOv-zFL1oaUAcWP6dPXBBOUAEXE_z4KZNfNTYDfmtAvxq-E0Xl1cqWGO_WmPldHoZIaVKzA0moWQ-GAYupV_MKgmlkgnY0gmlwhMCoAdOJc2VjcDI1NmsxoQLvx1jTRx75jpj8jD3KJ3FCZ_6UiICRIQJ_1MWmVx0IbYN0Y3CCdn6DdWRwgnZ-",
"enr:-JG4QPGTzcn6tp8UqoSmEBBj5f0_42wonWmoedFgvncdZL3Qf0DCEQVzDSHGi9jM35qdD76rvpWFuGpQ_rmoX14ZnACGAYupV_plgmlkgnY0gmlwhMCoAdOJc2VjcDI1NmsxoQLvx1jTRx75jpj8jD3KJ3FCZ_6UiICRIQJ_1MWmVx0IbYN0Y3CCdn6DdWRwgnZ-",
"enr:-JG4QP1aYRCaCknvIa3hSqE1zAUrm203DNFcvS8E1lQkqHq-PR0sQhIkzK7L4ZLLLPOijD9BTeCLWi8-0LVORt63dimGAYutv-WkgmlkgnY0gmlwhMCoAdyJc2VjcDI1NmsxoQJ81pyuyqa2QoPztOPsCqpkcW1gJwUxOcSJuWr9VUNavIN0Y3CCdn2DdWRwgnZ-",
}
r1, r2, r3 := parseGenericAddrs(nodes)
t.Log(r1)
t.Log(r2)
t.Log(r3)
for _, addr := range r1 {
bootnode, err := enode.Parse(enode.ValidSchemes, addr)
if err != nil {
t.Fatal(err)
}
t.Log(bootnode.String())
maddr, _ := convertToSingleMultiAddr(bootnode)
t.Log(maddr.String())
}
}
package p2p
import (
"context"
"fmt"
"io"
"sync"
"time"
"witness/p2p/peers"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/sirupsen/logrus"
)
const (
// The time to wait for a status request.
timeForStatus = 10 * time.Second
)
func peerMultiaddrString(conn network.Conn) string {
return fmt.Sprintf("%s/p2p/%s", conn.RemoteMultiaddr().String(), conn.RemotePeer().String())
}
// AddConnectionHandler adds a callback function which handles the connection with a
// newly added peer. It performs a handshake with that peer by sending a hello request
// and validating the response from the peer.
func (s *Service) AddConnectionHandler(reqFunc, goodByeFunc func(ctx context.Context, id peer.ID) error) {
// Peer map and lock to keep track of current connection attempts.
peerMap := make(map[peer.ID]bool)
peerLock := new(sync.Mutex)
// This is run at the start of each connection attempt, to ensure
// that there aren't multiple inflight connection requests for the
// same peer at once.
peerHandshaking := func(id peer.ID) bool {
peerLock.Lock()
defer peerLock.Unlock()
if peerMap[id] {
return true
}
peerMap[id] = true
return false
}
peerFinished := func(id peer.ID) {
peerLock.Lock()
defer peerLock.Unlock()
delete(peerMap, id)
}
s.host.Network().Notify(&network.NotifyBundle{
ConnectedF: func(net network.Network, conn network.Conn) {
remotePeer := conn.RemotePeer()
disconnectFromPeer := func() {
s.peers.SetConnectionState(remotePeer, peers.PeerDisconnecting)
// Only attempt a goodbye if we are still connected to the peer.
if s.host.Network().Connectedness(remotePeer) == network.Connected {
if err := goodByeFunc(context.TODO(), remotePeer); err != nil {
log.WithError(err).Error("Unable to disconnect from peer")
}
}
s.peers.SetConnectionState(remotePeer, peers.PeerDisconnected)
}
// Connection handler must be non-blocking as part of libp2p design.
go func() {
if peerHandshaking(remotePeer) {
// Exit this if there is already another connection
// request in flight.
return
}
defer peerFinished(remotePeer)
// Handle the various pre-existing conditions that will result in us not handshaking.
peerConnectionState, err := s.peers.ConnectionState(remotePeer)
if err == nil && (peerConnectionState == peers.PeerConnected || peerConnectionState == peers.PeerConnecting) {
log.WithField("currentState", peerConnectionState).WithField("reason", "already active").Trace("Ignoring connection request")
return
}
s.peers.Add(nil /* ENR */, remotePeer, conn.RemoteMultiaddr(), conn.Stat().Direction)
// Defensive check in the event we still get a bad peer.
if s.peers.IsBad(remotePeer) {
log.WithField("reason", "bad peer").Trace("Ignoring connection request")
disconnectFromPeer()
return
}
validPeerConnection := func() {
s.peers.SetConnectionState(conn.RemotePeer(), peers.PeerConnected)
// Go through the handshake process.
log.WithFields(logrus.Fields{
"direction": conn.Stat().Direction,
"multiAddr": peerMultiaddrString(conn),
"activePeers": len(s.peers.Active()),
}).Info("Peer connected")
}
// Do not perform handshake on inbound dials.
if conn.Stat().Direction == network.DirInbound {
// Wait for peer to initiate handshake
time.Sleep(timeForStatus)
// Exit if we are disconnected with the peer.
if s.host.Network().Connectedness(remotePeer) != network.Connected {
return
}
validPeerConnection()
return
}
s.peers.SetConnectionState(conn.RemotePeer(), peers.PeerConnecting)
if err := reqFunc(context.TODO(), conn.RemotePeer()); err != nil && err != io.EOF {
log.WithError(err).Trace("Handshake failed")
disconnectFromPeer()
return
}
validPeerConnection()
}()
},
})
}
// AddDisconnectionHandler disconnects from peers. It handles updating the peer status.
// This also calls the handler responsible for maintaining other parts of the sync or p2p system.
func (s *Service) AddDisconnectionHandler(handler func(ctx context.Context, id peer.ID) error) {
s.host.Network().Notify(&network.NotifyBundle{
DisconnectedF: func(net network.Network, conn network.Conn) {
log := log.WithField("multiAddr", peerMultiaddrString(conn))
// Must be handled in a goroutine as this callback cannot be blocking.
go func() {
// Exit early if we are still connected to the peer.
if net.Connectedness(conn.RemotePeer()) == network.Connected {
return
}
priorState, err := s.peers.ConnectionState(conn.RemotePeer())
if err != nil {
// Can happen if the peer has already disconnected, so...
priorState = peers.PeerDisconnected
}
s.peers.SetConnectionState(conn.RemotePeer(), peers.PeerDisconnecting)
if err := handler(context.TODO(), conn.RemotePeer()); err != nil {
log.WithError(err).Error("Disconnect handler failed")
}
s.peers.SetConnectionState(conn.RemotePeer(), peers.PeerDisconnected)
// Only log disconnections if we were fully connected.
if priorState == peers.PeerConnected {
log.WithField("activePeers", len(s.peers.Active())).Info("Peer disconnected")
}
}()
},
})
}
package p2p
import (
"strings"
"github.com/libp2p/go-libp2p/core/peer"
ma "github.com/multiformats/go-multiaddr"
"github.com/sirupsen/logrus"
)
var log = logrus.WithField("module", "p2p")
func logIPAddr(id peer.ID, addrs ...ma.Multiaddr) {
var correctAddr ma.Multiaddr
for _, addr := range addrs {
if strings.Contains(addr.String(), "/ip4/") || strings.Contains(addr.String(), "/ip6/") {
correctAddr = addr
break
}
}
if correctAddr != nil {
log.WithField(
"multiAddr",
correctAddr.String()+"/p2p/"+id.String(),
).Info("Node started p2p server")
}
}
func logExternalIPAddr(id peer.ID, addr string, port uint) {
if addr != "" {
multiAddr, err := MultiAddressBuilder(addr, port)
if err != nil {
log.WithError(err).Error("Could not create multiaddress")
return
}
log.WithField(
"multiAddr",
multiAddr.String()+"/p2p/"+id.String(),
).Info("Node started external p2p server")
}
}
package p2p
import (
"fmt"
pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb"
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
)
func msgID(pmsg *pubsubpb.Message) string {
h := hash.Hash(pmsg.Data)
return fmt.Sprintf("%x", h[:20])
}
package p2p
import (
"testing"
pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb"
)
func TestMessageID(t *testing.T) {
tt := []pubsubpb.Message{
{
Data: []byte("hello"),
},
{
Data: []byte("world"),
},
}
wants := []string{
"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c",
"486ea46224d1bb4fb680f34f7c9ad96a8f24ec88",
}
for i := range tt {
t.Run(string(tt[i].Data), func(t *testing.T) {
if msgID(&tt[i]) != wants[i] {
t.Errorf("Wanted %s, got %s", wants[i], msgID(&tt[i]))
}
})
}
}
package p2p
import (
"crypto/ecdsa"
"fmt"
"net"
"witness/version"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/p2p/muxer/yamux"
"github.com/libp2p/go-libp2p/p2p/security/noise"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
ma "github.com/multiformats/go-multiaddr"
"github.com/pkg/errors"
ecdsaprysm "github.com/prysmaticlabs/prysm/v3/crypto/ecdsa"
)
// MultiAddressBuilder takes in an ip address string and port to produce a go multiaddr format.
func MultiAddressBuilder(ipAddr string, port uint) (ma.Multiaddr, error) {
parsedIP := net.ParseIP(ipAddr)
if parsedIP.To4() == nil && parsedIP.To16() == nil {
return nil, errors.Errorf("invalid ip address provided: %s", ipAddr)
}
if parsedIP.To4() != nil {
return ma.NewMultiaddr(fmt.Sprintf("/ip4/%s/tcp/%d", ipAddr, port))
}
return ma.NewMultiaddr(fmt.Sprintf("/ip6/%s/tcp/%d", ipAddr, port))
}
// buildOptions for the libp2p host.
func (s *Service) buildOptions(ip net.IP, priKey *ecdsa.PrivateKey) []libp2p.Option {
cfg := s.cfg
listen, err := MultiAddressBuilder(ip.String(), cfg.TCPPort)
if err != nil {
log.WithError(err).Fatal("Failed to p2p listen")
}
if cfg.LocalIP != "" {
if net.ParseIP(cfg.LocalIP) == nil {
log.Fatalf("Invalid local ip provided: %s", cfg.LocalIP)
}
listen, err = MultiAddressBuilder(cfg.LocalIP, cfg.TCPPort)
if err != nil {
log.WithError(err).Fatal("Failed to p2p listen")
}
}
ifaceKey, err := ecdsaprysm.ConvertToInterfacePrivkey(priKey)
if err != nil {
log.WithError(err).Fatal("Failed to retrieve private key")
}
id, err := peer.IDFromPublicKey(ifaceKey.GetPublic())
if err != nil {
log.WithError(err).Fatal("Failed to retrieve peer id")
}
log.Infof("Running node with peer id of %s ", id.String())
myPeerIDToFile(id.String())
log.Debugf("listen %s", listen.String())
options := []libp2p.Option{
privKeyOption(priKey),
libp2p.ListenAddrs(listen),
libp2p.UserAgent(version.Version),
libp2p.ConnectionGater(s),
libp2p.Transport(tcp.NewTCPTransport),
libp2p.Muxer("/yamux/6.7.0", yamux.DefaultTransport),
libp2p.DefaultMuxers,
}
options = append(options, libp2p.Security(noise.ID, noise.New))
options = append(options, libp2p.DisableRelay())
if cfg.HostAddress != "" {
options = append(options, libp2p.AddrsFactory(func(addrs []ma.Multiaddr) []ma.Multiaddr {
external, err := MultiAddressBuilder(cfg.HostAddress, cfg.TCPPort)
if err != nil {
log.WithError(err).Error("Unable to create external multiaddress")
} else {
addrs = append(addrs, external)
}
return addrs
}))
}
return options
}
func multiAddressBuilderWithID(ipAddr, protocol string, port uint, id peer.ID) (ma.Multiaddr, error) {
parsedIP := net.ParseIP(ipAddr)
if parsedIP.To4() == nil && parsedIP.To16() == nil {
return nil, errors.Errorf("invalid ip address provided: %s", ipAddr)
}
if id.String() == "" {
return nil, errors.New("empty peer id given")
}
if parsedIP.To4() != nil {
return ma.NewMultiaddr(fmt.Sprintf("/ip4/%s/%s/%d/p2p/%s", ipAddr, protocol, port, id.String()))
}
return ma.NewMultiaddr(fmt.Sprintf("/ip6/%s/%s/%d/p2p/%s", ipAddr, protocol, port, id.String()))
}
// Adds a private key to the libp2p option if the option was provided.
// If the private key file is missing or cannot be read, or if the
// private key contents cannot be marshaled, an exception is thrown.
func privKeyOption(privkey *ecdsa.PrivateKey) libp2p.Option {
return func(cfg *libp2p.Config) error {
ifaceKey, err := ecdsaprysm.ConvertToInterfacePrivkey(privkey)
if err != nil {
return err
}
log.Debug("ECDSA private key generated")
return cfg.Apply(libp2p.Identity(ifaceKey))
}
}
package p2p
import (
"crypto/rand"
"encoding/hex"
"net"
"os"
"reflect"
"testing"
gethCrypto "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/crypto"
ecdsaprysm "github.com/prysmaticlabs/prysm/v3/crypto/ecdsa"
"github.com/prysmaticlabs/prysm/v3/network"
)
func TestPrivateKeyLoading(t *testing.T) {
file, err := os.CreateTemp(t.TempDir(), "key")
if err != nil {
t.Fatal(err)
}
key, _, err := crypto.GenerateSecp256k1Key(rand.Reader)
if err != nil {
t.Fatal(err, "Could not generate key")
}
raw, err := key.Raw()
if err != nil {
panic(err)
}
out := hex.EncodeToString(raw)
err = os.WriteFile(file.Name(), []byte(out), 0666)
if err != nil {
t.Fatal(err, "Could not write key to file")
}
log.WithField("file", file.Name()).WithField("key", out).Info("Wrote key to file")
cfg := &Config{
PrivateKeyPath: file.Name(),
}
pKey, err := privKey(cfg)
if err != nil {
t.Fatal(err, "Could not apply option")
}
newPkey, err := ecdsaprysm.ConvertToInterfacePrivkey(pKey)
if err != nil {
panic(err)
}
rawBytes, err := key.Raw()
if err != nil {
panic(err)
}
newRaw, err := newPkey.Raw()
if err != nil {
panic(err)
}
if !reflect.DeepEqual(rawBytes, newRaw) {
t.Fatal("Private keys do not match")
}
}
func TestIPV6Support(t *testing.T) {
key, err := gethCrypto.GenerateKey()
if err != nil {
t.Fatal(err)
}
db, err := enode.OpenDB("")
if err != nil {
log.Error("could not open node's peer database")
}
lNode := enode.NewLocalNode(db, key)
mockIPV6 := net.IP{0xff, 0x02, 0xAA, 0, 0x1F, 0, 0x2E, 0, 0, 0x36, 0x45, 0, 0, 0, 0, 0x02}
lNode.Set(enr.IP(mockIPV6))
ma, err := convertToSingleMultiAddr(lNode.Node())
if err != nil {
t.Fatal(err)
}
ipv6Exists := false
for _, p := range ma.Protocols() {
if p.Name == "ip4" {
t.Error("Got ip4 address instead of ip6")
}
if p.Name == "ip6" {
ipv6Exists = true
}
}
if !ipv6Exists {
t.Error("Multiaddress did not have ipv6 protocol")
}
}
func TestDefaultMultiplexers(t *testing.T) {
var cfg libp2p.Config
_ = cfg
p2pCfg := &Config{
TCPPort: 2000,
UDPPort: 2000,
}
svc := &Service{cfg: p2pCfg}
var err error
svc.privKey, err = privKey(svc.cfg)
if err != nil {
t.Fatal(err)
}
ipAddr := network.IPAddr()
opts := svc.buildOptions(ipAddr, svc.privKey)
err = cfg.Apply(append(opts, libp2p.FallbackDefaults)...)
if err != nil {
t.Fatal(err)
}
if "/mplex/6.7.0" != cfg.Muxers[0].ID {
t.Fatal("Mplex not set as default")
}
if "/yamux/1.0.0" != cfg.Muxers[1].ID {
t.Fatal("Yamux not set as default")
}
}
package peers
import (
"context"
"math"
"math/rand"
"time"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
ma "github.com/multiformats/go-multiaddr"
manet "github.com/multiformats/go-multiaddr/net"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/p2p/peers/peerdata"
)
const (
// MinBackOffDuration minimum amount (in milliseconds) to wait before peer is re-dialed.
// When node and peer are dialing each other simultaneously connection may fail. In order, to break
// of constant dialing, peer is assigned some backoff period, and only dialed again once that backoff is up.
MinBackOffDuration = 100
// MaxBackOffDuration maximum amount (in milliseconds) to wait before peer is re-dialed.
MaxBackOffDuration = 5000
DefaultBadNodeReleaseDuration = time.Minute
)
type Status struct {
ctx context.Context
store *Store
ipTracker map[string]uint64
rand *rand.Rand
config *StatusConfig
}
type StatusConfig struct {
MaxInboundPeers int
MaxOutboundPeers int
MaxPeers int
MaxBadResponses int
BadNodeReleaseDuration time.Duration
}
func NewStatus(ctx context.Context, cfg *StatusConfig) *Status {
store := NewStore(ctx, &storeConfig{
MaxInboundPeers: cfg.MaxInboundPeers,
MaxOutboundPeers: cfg.MaxOutboundPeers,
MaxPeers: cfg.MaxPeers,
MaxBadResponses: cfg.MaxBadResponses,
})
// fallback set
if cfg.BadNodeReleaseDuration == 0 {
cfg.BadNodeReleaseDuration = DefaultBadNodeReleaseDuration
}
return &Status{
ctx: ctx,
store: store,
ipTracker: make(map[string]uint64),
rand: rand.New(rand.NewSource(rand.Int63())),
config: cfg,
}
}
// MaxPeerLimit returns the max peer limit stored in the current peer store.
func (p *Status) MaxPeerLimit() int {
return p.store.Config().MaxPeers
}
// MaxInboundPeerLimit returns the max inbound peer limit stored in the current peer store.
func (p *Status) MaxInboundPeerLimit() int {
return p.store.Config().MaxInboundPeers
}
// MaxOutboundPeerLimit returns the max inbound peer limit stored in the current peer store.
func (p *Status) MaxOutboundPeerLimit() int {
return p.store.Config().MaxOutboundPeers
}
// MaxBadResponses returns the max bad responses stored in the current peer store.
func (p *Status) MaxBadResponses() int {
return p.store.Config().MaxBadResponses
}
// Add adds a peer.
// If a peer already exists with this ID its address and direction are updated with the supplied data.
func (p *Status) Add(record *enr.Record, pid peer.ID, address ma.Multiaddr, direction network.Direction) {
p.store.Lock()
defer p.store.Unlock()
if peerData, ok := p.store.PeerData(pid); ok {
// Peer already exists, just update its address info.
prevAddress := peerData.Address
peerData.Address = address
peerData.Direction = direction
if record != nil {
peerData.Enr = record
}
if !sameIP(prevAddress, address) {
p.addIpToTracker(pid)
}
return
}
peerData := &PeerData{
Address: address,
Direction: direction,
// Peers start disconnected; state will be updated when the handshake process begins.
ConnState: PeerDisconnected,
}
if record != nil {
peerData.Enr = record
}
p.store.SetPeerData(pid, peerData)
p.addIpToTracker(pid)
}
// SetConnectionState sets the connection state of the given remote peer.
func (p *Status) SetConnectionState(pid peer.ID, state PeerConnectionState) {
p.store.Lock()
defer p.store.Unlock()
peerData := p.store.PeerDataGetOrCreate(pid)
peerData.ConnState = state
}
// ConnectionState gets the connection state of the given remote peer.
// This will error if the peer does not exist.
func (p *Status) ConnectionState(pid peer.ID) (PeerConnectionState, error) {
p.store.RLock()
defer p.store.RUnlock()
if peerData, ok := p.store.PeerData(pid); ok {
return peerData.ConnState, nil
}
return PeerDisconnected, peerdata.ErrPeerUnknown
}
// InboundConnected returns the current batch of inbound peers that are connected.
func (p *Status) InboundConnected() []peer.ID {
p.store.RLock()
defer p.store.RUnlock()
peers := make([]peer.ID, 0)
for pid, peerData := range p.store.Peers() {
if peerData.ConnState == PeerConnected && peerData.Direction == network.DirInbound {
peers = append(peers, pid)
}
}
return peers
}
// OutboundConnected returns the current batch of outbound peers that are connected.
func (p *Status) OutboundConnected() []peer.ID {
p.store.RLock()
defer p.store.RUnlock()
peers := make([]peer.ID, 0)
for pid, peerData := range p.store.Peers() {
if peerData.ConnState == PeerConnected && peerData.Direction == network.DirOutbound {
peers = append(peers, pid)
}
}
return peers
}
// Active returns the peers that are connecting or connected.
func (p *Status) Active() []peer.ID {
p.store.RLock()
defer p.store.RUnlock()
peers := make([]peer.ID, 0)
for pid, peerData := range p.store.Peers() {
if peerData.ConnState == PeerConnecting || peerData.ConnState == PeerConnected {
peers = append(peers, pid)
}
}
return peers
}
// RandomizeBackOff adds extra backoff period during which peer will not be dialed.
func (p *Status) RandomizeBackOff(pid peer.ID) {
p.store.Lock()
defer p.store.Unlock()
peerData := p.store.PeerDataGetOrCreate(pid)
// No need to add backoff period, if the previous one hasn't expired yet.
if !time.Now().After(peerData.NextValidTime) {
return
}
duration := time.Duration(math.Max(MinBackOffDuration, float64(p.rand.Intn(MaxBackOffDuration)))) * time.Millisecond
peerData.NextValidTime = time.Now().Add(duration)
}
// IsReadyToDial checks where the given peer is ready to be
// dialed again.
func (p *Status) IsReadyToDial(pid peer.ID) bool {
p.store.RLock()
defer p.store.RUnlock()
if peerData, ok := p.store.PeerData(pid); ok {
timeIsZero := peerData.NextValidTime.IsZero()
isInvalidTime := peerData.NextValidTime.After(time.Now())
return timeIsZero || !isInvalidTime
}
// If no record exists, we don't restrict dials to the
// peer.
return true
}
// IsActive checks if a peers is active and returns the result appropriately.
func (p *Status) IsActive(pid peer.ID) bool {
p.store.RLock()
defer p.store.RUnlock()
peerData, ok := p.store.PeerData(pid)
return ok && (peerData.ConnState == PeerConnected || peerData.ConnState == PeerConnecting)
}
// IncBadResponses increments the number of bad responses received from the given peer.
func (p *Status) IncBadResponses(pid peer.ID) {
p.store.Lock()
defer p.store.Unlock()
peerData, ok := p.store.PeerData(pid)
if !ok {
p.store.SetPeerData(pid, &PeerData{
BadResponses: 1,
})
return
}
if time.Now().Before(peerData.NextBadNodeReleaseTime) {
return
}
peerData.BadResponses++
if peerData.BadResponses >= p.MaxBadResponses() {
// freeze for a while
peerData.NextBadNodeReleaseTime = time.Now().Add(p.config.BadNodeReleaseDuration)
}
}
// IsBad states if the peer is to be considered bad (by *any* of the registered scorers).
// If the peer is unknown this will return `false`, which makes using this function easier than returning an error.
func (p *Status) IsBad(pid peer.ID) bool {
p.store.RLock()
defer p.store.RUnlock()
return p.isBad(pid)
}
// isBad is the lock-free version of IsBad.
func (p *Status) isBad(pid peer.ID) bool {
return p.isFromBadIP(pid) || p.isFromBadResponses(pid)
}
// this method assumes the store lock is acquired before
// executing the method.
func (p *Status) isFromBadIP(pid peer.ID) bool {
peerData, ok := p.store.PeerData(pid)
if !ok {
return false
}
if peerData.Address == nil {
return false
}
_, err := manet.ToIP(peerData.Address)
if err != nil {
return true
}
return false
}
// isFromBadResponses
func (p *Status) isFromBadResponses(pid peer.ID) bool {
peerData, ok := p.store.PeerData(pid)
if !ok {
return false
}
// release bad node
if !peerData.NextBadNodeReleaseTime.IsZero() && time.Now().After(peerData.NextBadNodeReleaseTime) {
peerData.BadResponses = 0
peerData.NextBadNodeReleaseTime = time.Time{}
}
return peerData.BadResponses >= p.MaxBadResponses()
}
func (p *Status) addIpToTracker(pid peer.ID) {
data, ok := p.store.PeerData(pid)
if !ok {
return
}
if data.Address == nil {
return
}
ip, err := manet.ToIP(data.Address)
if err != nil {
// Should never happen, it is
// assumed every IP coming in
// is a valid ip.
return
}
// Ignore loopback addresses.
if ip.IsLoopback() {
return
}
stringIP := ip.String()
p.ipTracker[stringIP] += 1
}
func (p *Status) tallyIPTracker() {
tracker := map[string]uint64{}
// Iterate through all peers.
for _, peerData := range p.store.Peers() {
if peerData.Address == nil {
continue
}
ip, err := manet.ToIP(peerData.Address)
if err != nil {
// Should never happen, it is
// assumed every IP coming in
// is a valid ip.
continue
}
stringIP := ip.String()
tracker[stringIP] += 1
}
p.ipTracker = tracker
}
func sameIP(firstAddr, secondAddr ma.Multiaddr) bool {
// Exit early if we do get nil multiaddresses
if firstAddr == nil || secondAddr == nil {
return false
}
firstIP, err := manet.ToIP(firstAddr)
if err != nil {
return false
}
secondIP, err := manet.ToIP(secondAddr)
if err != nil {
return false
}
return firstIP.Equal(secondIP)
}
package peers
import (
"context"
"sync"
"time"
"github.com/ethereum/go-ethereum/p2p/enr"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
ma "github.com/multiformats/go-multiaddr"
)
type PeerConnectionState int
const (
// PeerDisconnected means there is no connection to the peer.
PeerDisconnected PeerConnectionState = iota
// PeerDisconnecting means there is an on-going attempt to disconnect from the peer.
PeerDisconnecting
// PeerConnected means the peer has an active connection.
PeerConnected
// PeerConnecting means there is an on-going attempt to connect to the peer.
PeerConnecting
)
type PeerData struct {
Address ma.Multiaddr
Direction network.Direction
ConnState PeerConnectionState
Enr *enr.Record
NextValidTime time.Time
BadResponses int
NextBadNodeReleaseTime time.Time
}
type Store struct {
ctx context.Context
peers map[peer.ID]*PeerData
config *storeConfig
sync.RWMutex
}
type storeConfig struct {
MaxInboundPeers int
MaxOutboundPeers int
MaxPeers int
MaxBadResponses int
}
func NewStore(ctx context.Context, cfg *storeConfig) *Store {
return &Store{
ctx: ctx,
peers: make(map[peer.ID]*PeerData),
config: cfg,
}
}
// PeerData returns data associated with a given peer, if any.
// Important: it is assumed that store mutex is locked when calling this method.
func (s *Store) PeerData(pid peer.ID) (*PeerData, bool) {
peerData, ok := s.peers[pid]
return peerData, ok
}
// PeerDataGetOrCreate returns data associated with a given peer.
// If no data has been associated yet, newly created and associated data object is returned.
// Important: it is assumed that store mutex is locked when calling this method.
func (s *Store) PeerDataGetOrCreate(pid peer.ID) *PeerData {
if peerData, ok := s.peers[pid]; ok {
return peerData
}
s.peers[pid] = &PeerData{}
return s.peers[pid]
}
// SetPeerData updates data associated with a given peer.
// Important: it is assumed that store mutex is locked when calling this method.
func (s *Store) SetPeerData(pid peer.ID, data *PeerData) {
s.peers[pid] = data
}
// DeletePeerData removes data associated with a given peer.
// Important: it is assumed that store mutex is locked when calling this method.
func (s *Store) DeletePeerData(pid peer.ID) {
delete(s.peers, pid)
}
// Peers returns map of peer data objects.
// Important: it is assumed that store mutex is locked when calling this method.
func (s *Store) Peers() map[peer.ID]*PeerData {
return s.peers
}
// Config return store config
func (s *Store) Config() *storeConfig {
return s.config
}
package p2p
import (
"context"
"time"
pubsub "github.com/libp2p/go-libp2p-pubsub"
pubsubpb "github.com/libp2p/go-libp2p-pubsub/pb"
"github.com/pkg/errors"
)
const (
// overlay parameters
gossipSubD = 8 // topic stable mesh target count
gossipSubDlo = 6 // topic stable mesh low watermark
gossipSubDhi = 12 // topic stable mesh high watermark
// gossip parameters
gossipSubMcacheLen = 6 // number of windows to retain full messages in cache for `IWANT` responses
gossipSubMcacheGossip = 3 // number of windows to gossip about
gossipSubSeenTTL = 60 // number of heartbeat intervals to retain message IDs
// heartbeat interval
gossipSubHeartbeatInterval = 700 * time.Millisecond // frequency of heartbeat, milliseconds
)
// JoinTopic will join PubSub topic, if not already joined.
func (s *Service) JoinTopic(topic string, opts ...pubsub.TopicOpt) (*pubsub.Topic, error) {
s.joinedTopicsLock.Lock()
defer s.joinedTopicsLock.Unlock()
if _, ok := s.joinedTopics[topic]; !ok {
topicHandle, err := s.pubsub.Join(topic, opts...)
if err != nil {
return nil, err
}
s.joinedTopics[topic] = topicHandle
}
return s.joinedTopics[topic], nil
}
// LeaveTopic closes topic and removes corresponding handler from list of joined topics.
// This method will return error if there are outstanding event handlers or subscriptions.
func (s *Service) LeaveTopic(topic string) error {
s.joinedTopicsLock.Lock()
defer s.joinedTopicsLock.Unlock()
if t, ok := s.joinedTopics[topic]; ok {
if err := t.Close(); err != nil {
return err
}
delete(s.joinedTopics, topic)
}
return nil
}
// PublishToTopic joins (if necessary) and publishes a message to a PubSub topic.
func (s *Service) PublishToTopic(ctx context.Context, topic string, data []byte, opts ...pubsub.PubOpt) error {
topicHandle, err := s.JoinTopic(topic)
if err != nil {
return err
}
if s.cfg.SingleNode {
return topicHandle.Publish(ctx, data, opts...)
}
// Wait for at least 1 peer to be available to receive the published message.
for {
if len(topicHandle.ListPeers()) > 0 {
return topicHandle.Publish(ctx, data, opts...)
}
select {
case <-ctx.Done():
return errors.Wrapf(ctx.Err(), "unable to find requisite number of peers for topic %s, 0 peers found to publish to", topic)
default:
time.Sleep(100 * time.Millisecond)
}
}
}
// SubscribeToTopic joins (if necessary) and subscribes to PubSub topic.
func (s *Service) SubscribeToTopic(topic string, opts ...pubsub.SubOpt) (*pubsub.Subscription, error) {
topicHandle, err := s.JoinTopic(topic)
if err != nil {
return nil, err
}
return topicHandle.Subscribe(opts...)
}
// Creates a list of pubsub options to configure out router with.
func (s *Service) pubsubOptions() []pubsub.Option {
psOpts := []pubsub.Option{
pubsub.WithMessageSignaturePolicy(pubsub.StrictNoSign),
pubsub.WithNoAuthor(),
pubsub.WithMessageIdFn(func(pmsg *pubsubpb.Message) string {
return msgID(pmsg)
}),
pubsub.WithPeerOutboundQueueSize(pubsubQueueSize),
pubsub.WithMaxMessageSize(GossipMaxSize),
pubsub.WithValidateQueueSize(pubsubQueueSize),
pubsub.WithGossipSubParams(pubsubGossipParam()),
}
return psOpts
}
// creates a custom gossipsub parameter set.
func pubsubGossipParam() pubsub.GossipSubParams {
gParams := pubsub.DefaultGossipSubParams()
gParams.Dlo = gossipSubDlo
gParams.D = gossipSubD
gParams.HeartbeatInterval = gossipSubHeartbeatInterval
gParams.HistoryLength = gossipSubMcacheLen
gParams.HistoryGossip = gossipSubMcacheGossip
return gParams
}
// We have to unfortunately set this globally in order
// to configure our message id time-cache rather than instantiating
// it with a router instance.
func setPubSubParameters() {
pubsub.TimeCacheDuration = gossipSubSeenTTL * gossipSubHeartbeatInterval
}
package p2p
import (
"context"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol"
"github.com/sirupsen/logrus"
)
// Send a message to a specific peer. The returned stream may be used for reading, but has been
// closed for writing.
//
// When done, the caller must Close or Reset on the stream.
func (s *Service) Send(ctx context.Context, message []byte, baseTopic string, pid peer.ID) (network.Stream, error) {
topic := baseTopic
log.WithFields(logrus.Fields{
"topic": topic,
"request length": len(message),
}).Tracef("Sending RPC request to peer %s", pid.String())
// Apply max dial timeout when opening a new stream.
ctx, cancel := context.WithTimeout(ctx, maxDialTimeout)
defer cancel()
stream, err := s.host.NewStream(ctx, pid, protocol.ID(topic))
if err != nil {
return nil, err
}
_, err = stream.Write(message)
if err != nil {
return stream, err
}
// Close stream for writing.
if err := stream.CloseWrite(); err != nil {
_err := stream.Reset()
_ = _err
return nil, err
}
return stream, nil
}
// Package p2p including peer discovery using discv5, gossip-sub
// using libp2p, and handing peer lifecycles + handshakes.
package p2p
import (
"context"
"crypto/ecdsa"
"fmt"
"net"
"strings"
"sync"
"time"
"witness/p2p/peers"
"github.com/libp2p/go-libp2p"
"github.com/multiformats/go-multiaddr"
"github.com/prysmaticlabs/prysm/v3/async/event"
"github.com/ethereum/go-ethereum/p2p/enode"
"github.com/ethereum/go-ethereum/p2p/enr"
pubsub "github.com/libp2p/go-libp2p-pubsub"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/protocol"
"github.com/pkg/errors"
prysmnetwork "github.com/prysmaticlabs/prysm/v3/network"
)
// In the event that we are at our peer limit, we
// stop looking for new peers and instead poll
// for the current peer limit status for the time period
// defined below.
var pollingPeriod = time.Second * 12
// maxDialTimeout is the timeout for a single peer dial.
var maxDialTimeout = time.Second * 10
// pubsubQueueSize is the size that we assign to our validation queue and outbound message queue for
// gossipsub.
const pubsubQueueSize = 80
const GossipMaxSize = 100 * 1 << 20 // 10MB
const MaxChunkSize = 10 * 1 << 20 // 1MB
type subSession struct {
sub event.Subscription
listeners int
}
// Service for managing peer to peer (p2p) networking.
type Service struct {
started bool
cancel context.CancelFunc
cfg *Config
privKey *ecdsa.PrivateKey
pubsub *pubsub.PubSub
joinedTopics map[string]*pubsub.Topic
joinedTopicsLock sync.Mutex
dv5Listener Listener
startupErr error
ctx context.Context
host host.Host
peers *peers.Status
subManage map[string]*subSession
subManageLock sync.Mutex
}
// NewService initializes a new p2p service compatible with shared.Service interface. No
// connections are made until the Start function is called during the service registry startup.
func NewService(ctx context.Context, cfg *Config) (*Service, error) {
var err error
ctx, cancel := context.WithCancel(ctx)
_ = cancel // govet fix for lost cancel. Cancel is handled in service.Stop().
s := &Service{
ctx: ctx,
cancel: cancel,
cfg: cfg,
subManage: make(map[string]*subSession),
joinedTopics: make(map[string]*pubsub.Topic),
}
dv5Nodes, _ := parseBootStrapAddrs(s.cfg.BootstrapNodeAddr)
cfg.Discv5BootStrapAddr = dv5Nodes
s.privKey, err = privKey(s.cfg)
if err != nil {
log.WithError(err).Error("Failed to generate p2p private key")
return nil, err
}
// get external ip address
ipAddr := prysmnetwork.IPAddr()
if cfg.HostAddress != "" {
ipAddr = net.ParseIP("0.0.0.0")
if ipAddr.To4() == nil && ipAddr.To16() == nil {
log.Errorf("Invalid host address given: %s", ipAddr.String())
return nil, fmt.Errorf("invalid host address given: %s", ipAddr.String())
}
}
opts := s.buildOptions(ipAddr, s.privKey)
h, err := libp2p.New(opts...)
if err != nil {
log.WithError(err).Error("Failed to create p2p host")
return nil, err
}
s.host = h
// Gossipsub registration is done before we add in any new peers
// due to libp2p's gossipsub implementation not taking into
// account previously added peers when creating the gossipsub
// object.
psOpts := s.pubsubOptions()
// Set the pubsub global parameters that we require.
setPubSubParameters()
// Reinitialize them in the event we are running a custom config.
gs, err := pubsub.NewGossipSub(s.ctx, s.host, psOpts...)
if err != nil {
log.WithError(err).Error("Failed to start pubsub")
return nil, err
}
s.pubsub = gs
s.peers = peers.NewStatus(s.ctx, &peers.StatusConfig{
MaxInboundPeers: int(cfg.MaxInboundPeers),
MaxOutboundPeers: int(cfg.MaxOutboundPeers),
MaxPeers: int(cfg.MaxPeers),
MaxBadResponses: 3,
})
return s, nil
}
// Start the p2p service.
func (s *Service) Start() {
if s.started {
log.Error("Attempted to start p2p service when it was already started")
return
}
if s.cfg.UseDiscovery {
ipAddr := prysmnetwork.IPAddr()
listener, err := s.startDiscoveryV5(
ipAddr,
s.privKey,
)
if err != nil {
log.WithError(err).Fatal("Failed to start discovery")
s.startupErr = err
return
}
log.Debug("debug: connecting to bootnode ", len(s.cfg.Discv5BootStrapAddr))
err = s.connectToBootnodes()
if err != nil {
log.WithError(err).Error("Could not add bootnode to the exclusion list")
s.startupErr = err
return
}
s.dv5Listener = listener
go s.listenForNewNodes()
}
s.started = true
if len(s.cfg.StaticPeers) > 0 {
addrs, err := PeersFromStringAddrs(s.cfg.StaticPeers)
if err != nil {
log.WithError(err).Error("Could not connect to static peer")
}
s.connectWithAllPeers(addrs, false)
}
multiAddrs := s.host.Network().ListenAddresses()
logIPAddr(s.host.ID(), multiAddrs...)
p2pHostAddress := s.cfg.HostAddress
p2pTCPPort := s.cfg.TCPPort
if p2pHostAddress != "" {
logExternalIPAddr(s.host.ID(), p2pHostAddress, p2pTCPPort)
verifyConnectivity(p2pHostAddress, p2pTCPPort, "tcp")
}
}
// Stop the p2p service and terminate all peer connections.
func (s *Service) Stop() error {
defer s.cancel()
s.started = false
if s.dv5Listener != nil {
s.dv5Listener.Close()
}
return nil
}
// Status of the p2p service. Will return an error if the service is considered unhealthy to
// indicate that this node should not serve traffic until the issue has been resolved.
func (s *Service) Status() error {
if !s.started {
return errors.New("not running")
}
if s.startupErr != nil {
return s.startupErr
}
return nil
}
// Started returns true if the p2p service has successfully started.
func (s *Service) Started() bool {
return s.started
}
// PubSub returns the p2p pubsub framework.
func (s *Service) PubSub() *pubsub.PubSub {
return s.pubsub
}
// Host returns the currently running libp2p
// host of the service.
func (s *Service) Host() host.Host {
return s.host
}
// SetStreamHandler sets the protocol handler on the p2p host multiplexer.
// This method is a pass through to libp2pcore.Host.SetStreamHandler.
func (s *Service) SetStreamHandler(topic string, handler network.StreamHandler) {
s.host.SetStreamHandler(protocol.ID(topic), handler)
}
// PeerID returns the Peer ID of the local peer.
func (s *Service) PeerID() peer.ID {
return s.host.ID()
}
// Disconnect from a peer.
func (s *Service) Disconnect(pid peer.ID) error {
return s.host.Network().ClosePeer(pid)
}
// Connect to a specific peer.
func (s *Service) Connect(pi peer.AddrInfo) error {
return s.host.Connect(s.ctx, pi)
}
func (s *Service) connectWithAllPeers(multiAddrs []multiaddr.Multiaddr, isBootnode bool) {
addrInfos, err := peer.AddrInfosFromP2pAddrs(multiAddrs...)
if err != nil {
log.WithError(err).Error("Could not convert to peer address info's from multiaddresses")
return
}
for _, info := range addrInfos {
for _, addr := range info.Addrs {
ipAddr := strings.Split(addr.String(), "/")[2]
if s.cfg.IgnoreLocalIP && s.isLocalIP(ipAddr) {
continue
}
}
// make each dial non-blocking
go func(info peer.AddrInfo) {
log.Debugf("connecting to peer %s", info.String())
if err := s.connectWithPeer(s.ctx, info); err != nil {
log.WithError(err).Errorf("Could not connect with peer %s, err %s", info.String(), err.Error())
} else if isBootnode {
// save to file
}
}(info)
}
}
func (s *Service) connectWithPeer(ctx context.Context, info peer.AddrInfo) error {
if info.ID == s.host.ID() {
return nil
}
if s.peers.IsBad(info.ID) {
return errors.New("refused to connect to bad peer")
}
for _, addr := range info.Addrs {
ipAddr := strings.Split(addr.String(), "/")[2]
if s.cfg.IgnoreLocalIP && s.isLocalIP(ipAddr) {
return nil
}
}
ctx, cancel := context.WithTimeout(ctx, maxDialTimeout)
defer cancel()
if err := s.host.Connect(ctx, info); err != nil {
s.peers.IncBadResponses(info.ID)
return err
}
log.WithField("peer", info.ID).Debug("Connected to new peer")
return nil
}
func (s *Service) connectToBootnodes() error {
nodes := make([]*enode.Node, 0, len(s.cfg.Discv5BootStrapAddr))
for _, addr := range s.cfg.Discv5BootStrapAddr {
bootNode, err := enode.Parse(enode.ValidSchemes, addr)
if err != nil {
return err
}
log.Debug("Adding bootnode to the list", bootNode.String())
// do not dial bootnodes with their tcp ports not set
if err := bootNode.Record().Load(enr.WithEntry("tcp", new(enr.TCP))); err != nil {
if !enr.IsNotFound(err) {
log.WithError(err).Error("Could not retrieve tcp port")
}
continue
}
if s.cfg.IgnoreLocalIP && s.isLocalIP(bootNode.IP().String()) {
continue
}
nodes = append(nodes, bootNode)
}
multiAddresses := convertToMultiAddr(nodes)
s.connectWithAllPeers(multiAddresses, true)
return nil
}
func (s *Service) isLocalIP(ipAddr string) bool {
return ipAddr == s.cfg.LocalIP || ipAddr == s.cfg.HostAddress || ipAddr == "127.0.0.1"
}
package p2p
import (
"crypto/ecdsa"
"crypto/rand"
"encoding/hex"
"fmt"
"net"
"os"
"time"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/pkg/errors"
ecdsaprysm "github.com/prysmaticlabs/prysm/v3/crypto/ecdsa"
"github.com/sirupsen/logrus"
)
const dialTimeout = 1 * time.Second
const enrRecordFile = "discovery-enr"
const peerIDFile = "peer-id"
// Determines a private key for p2p networking from the p2p service's
// configuration struct. If no key is found, it generates a new one.
func privKey(cfg *Config) (*ecdsa.PrivateKey, error) {
privateKeyPath := cfg.PrivateKeyPath
_, err := os.Stat(privateKeyPath)
privateKeyExist := !os.IsNotExist(err)
if err != nil && privateKeyExist {
return nil, err
}
if privateKeyPath == "" || !privateKeyExist {
priv, _, err := crypto.GenerateSecp256k1Key(rand.Reader)
if err != nil {
return nil, err
}
return ecdsaprysm.ConvertFromInterfacePrivKey(priv)
}
return privKeyFromFile(privateKeyPath)
}
// Retrieves a p2p networking private key from a file path.
func privKeyFromFile(path string) (*ecdsa.PrivateKey, error) {
src, err := os.ReadFile(path) // #nosec G304
if err != nil {
log.WithError(err).Error("Error reading private key from file")
return nil, err
}
dst := make([]byte, hex.DecodedLen(len(src)))
_, err = hex.Decode(dst, src)
if err != nil {
return nil, errors.Wrap(err, "failed to decode hex string")
}
unmarshalledKey, err := crypto.UnmarshalSecp256k1PrivateKey(dst)
if err != nil {
return nil, err
}
return ecdsaprysm.ConvertFromInterfacePrivKey(unmarshalledKey)
}
// Attempt to dial an address to verify its connectivity
func verifyConnectivity(addr string, port uint, protocol string) {
if addr != "" {
a := net.JoinHostPort(addr, fmt.Sprintf("%d", port))
fields := logrus.Fields{
"protocol": protocol,
"address": a,
}
conn, err := net.DialTimeout(protocol, a, dialTimeout)
if err != nil {
log.WithError(err).WithFields(fields).Warn("IP address is not accessible")
return
}
if err := conn.Close(); err != nil {
log.WithError(err).Debug("Could not close connection")
}
}
}
func enrRecordToFile(enr string) {
// create or overwrite
f, err := os.Create(enrRecordFile)
if err != nil {
log.WithError(err).Warn("Error creating enrRecordFile")
return
}
defer f.Close()
_, err = f.WriteString(enr)
if err != nil {
log.WithError(err).Warn("Error writing enrRecordFile")
return
}
}
func myPeerIDToFile(peerID string) {
f, err := os.Create(peerIDFile)
if err != nil {
log.WithError(err).Warn("Error creating peerIDFile")
return
}
defer f.Close()
_, err = f.WriteString(peerID)
if err != nil {
log.WithError(err).Warn("Error writing peerIDFile")
return
}
}
# aigic witness
\ No newline at end of file
# witness
merkle sum tree:
mstroot:2020-01-01 -> root
mstsum:2020-01-01 -> sum
mstk:2020-01-01 -> key1(bytes32)key2(bytes32)
mstv:2020-01-01 -> val1:val2
merkle tree:
mtroot:2020-01-01 -> root
mtk:2020-01-01 -> key1(bytes32)key2(bytes32)
state:
lastday -> 2023-01-01
sroot:2020-01-01 -> root
package tree
import (
"bytes"
)
// Byte helpers.
// Sort2Bytes by contents.
func Sort2Bytes(i []byte, j []byte) ([]byte, []byte) {
if lessThanBytes(i, j) {
return i, j
} else {
return j, i
}
}
func lessThanBytes(i []byte, j []byte) bool {
switch bytes.Compare(i, j) {
case -1, 0:
return true
case 1:
return false
default:
return false
}
}
func safeCopyBytes(cp []byte) []byte {
if cp != nil {
copied := make([]byte, len(cp))
copy(copied, cp)
return copied
}
return nil
}
func copy2dBytes(ary [][]byte) [][]byte {
if ary != nil {
copied := make([][]byte, len(ary))
for i, a := range ary {
copied[i] = safeCopyBytes(a)
}
return copied
}
return nil
}
func padTo(b []byte, size int) []byte {
if len(b) > size {
return b
}
return append(b, make([]byte, size-len(b))...)
}
// Math helpers.
// Find the next power of 2 unless n is already a power of 2.
func nextPowerOf2(n uint64) uint64 {
var count uint64 = 0
if isPowerOfTwo(n) {
return n
}
for n != 0 {
n >>= 1
count += 1
}
return 1 << count
}
func isPowerOfTwo(n uint64) bool {
return (n & (n - 1)) == 0
}
package tree
import (
"bytes"
"encoding/hex"
"github.com/ethereum/go-ethereum/common"
)
type Proofs []common.Hash
func (x Proofs) Len() int { return len(x) }
func (x Proofs) Less(i, j int) bool { return bytes.Compare(x[i][:], x[j][:]) == -1 }
func (x Proofs) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x Proofs) Dedup() Proofs {
r := make(Proofs, 0, len(x))
for idx, el := range x {
if idx == 0 || !bytes.Equal(x[idx-1][:], el[:]) {
r = append(r, el)
}
}
return r
}
func (x Proofs) ToHexArray() []string {
r := make([]string, 0, len(x))
for _, el := range x {
r = append(r, hex.EncodeToString(el[:]))
}
return r
}
package tree
import (
"bytes"
"math/big"
"github.com/ethereum/go-ethereum/crypto"
)
var (
LeafPrefix = []byte{0x00}
NodePrefix = []byte{0x01}
)
type MerkleSumTree struct {
sideNodes [][32]byte
nodeSums []*big.Int
}
func leafDigest(data [32]byte, val *big.Int) (digest [32]byte) {
valBytes := make([]byte, 32)
copy(valBytes[32-len(val.Bytes()):], val.Bytes())
buf := bytes.NewBuffer(LeafPrefix)
buf.Write(valBytes)
buf.Write(data[:])
copy(digest[:], crypto.Keccak256Hash(buf.Bytes()).Bytes())
return
}
func nodeDigest(leftDigest, rightDigest [32]byte, leftVal, rightVal *big.Int) (digest [32]byte) {
leftValBytes := make([]byte, 32)
rightValBytes := make([]byte, 32)
copy(leftValBytes[32-len(leftVal.Bytes()):], leftVal.Bytes())
copy(rightValBytes[32-len(rightVal.Bytes()):], rightVal.Bytes())
buf := bytes.NewBuffer(NodePrefix)
buf.Write(leftValBytes)
buf.Write(leftDigest[:])
buf.Write(rightValBytes)
buf.Write(rightDigest[:])
copy(digest[:], crypto.Keccak256Hash(buf.Bytes()).Bytes())
return
}
func ComputeMST(dataList [][32]byte, values []*big.Int) (nodes [][32]byte, sums []*big.Int) {
nodeDigests := make([][32]byte, len(dataList))
nodeSums := make([]*big.Int, len(dataList))
for i := 0; i < len(dataList); i++ {
nodeDigests[i] = leafDigest(dataList[i], values[i])
nodeSums[i] = values[i]
}
odd := len(dataList) & 1
size := (len(dataList) + 1) >> 1
pNodeDigests := make([][32]byte, len(dataList))
pNodeSums := make([]*big.Int, len(dataList))
copy(pNodeDigests, nodeDigests)
copy(pNodeSums, nodeSums)
for {
i := 0
for i < size-odd {
j := i << 1
nodeDigests[i] = nodeDigest(pNodeDigests[j], pNodeDigests[j+1], pNodeSums[j], pNodeSums[j+1])
nodeSums[i] = new(big.Int).Add(pNodeSums[j], pNodeSums[j+1])
i++
}
if odd == 1 {
nodeDigests[i] = pNodeDigests[i<<1]
nodeSums[i] = pNodeSums[i<<1]
}
if size == 1 {
break
}
odd = size & 1
size = (size + 1) >> 1
copy(pNodeDigests, nodeDigests)
copy(pNodeSums, nodeSums)
}
return nodeDigests, nodeSums
}
package tree
import (
"crypto/sha256"
"fmt"
"math/big"
"testing"
)
func Test(t *testing.T) {
dataList := [][]byte{[]byte{0x01, 0x01}, []byte{0x02, 0x02}, {0x03, 0x03}, {0x04, 0x04}}
digestList := make([][32]byte, len(dataList))
for i := 0; i < len(dataList); i++ {
digestList[i] = sha256.Sum256(dataList[i])
}
fmt.Printf("%x\n", digestList)
valList := []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(4)}
roots, sums := ComputeMST(digestList, valList)
fmt.Printf("%x\n", roots[0])
fmt.Println(sums[0].String())
}
package tree
import (
"bytes"
"errors"
"math"
"sort"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
func combinedHash(first, second common.Hash) (hash common.Hash) {
var buffer [64]byte
if bytes.Compare(first[:], second[:]) <= 0 {
copy(buffer[:32], first[:])
copy(buffer[32:], second[:])
copy(hash[:], crypto.Keccak256(buffer[:]))
} else {
copy(buffer[:32], second[:])
copy(buffer[32:], first[:])
copy(hash[:], crypto.Keccak256(buffer[:]))
}
return hash
}
type MerkleTree struct {
layers [][]common.Hash
proofs Proofs
bufferElementPositionIndex map[common.Hash]int
}
func NewMerkleTree(proofs Proofs) (*MerkleTree, error) {
sort.Sort(proofs)
proofs = proofs.Dedup()
bufferElementPositionIndex := make(map[common.Hash]int)
for idx, el := range proofs {
bufferElementPositionIndex[el] = idx
}
var err error
tree := MerkleTree{
proofs: proofs,
bufferElementPositionIndex: bufferElementPositionIndex,
}
tree.layers, err = tree.GetLayers(proofs)
if err != nil {
return nil, err
}
return &tree, nil
}
func (m *MerkleTree) GetRoot() common.Hash {
return m.layers[len(m.layers)-1][0]
}
func (m *MerkleTree) GetProof(el common.Hash) ([]common.Hash, error) {
idx, ok := m.bufferElementPositionIndex[el]
if !ok {
return nil, errors.New("element does not exist in Merkle tree")
}
proof := make(Proofs, 0)
for _, layer := range m.layers {
pairElement, ok := m.getPairElement(idx, layer)
if ok {
proof = append(proof, pairElement)
}
idx = int(math.Floor(float64(idx) / 2))
}
return proof, nil
}
func (m *MerkleTree) GetLayers(proofs Proofs) ([][]common.Hash, error) {
if len(proofs) == 0 {
return nil, errors.New("empty tree")
}
layers := make([][]common.Hash, 0)
layers = append(layers, proofs)
for len(layers[len(layers)-1]) > 1 {
layers = append(layers, m.GetNextLayer(layers[len(layers)-1]))
}
return layers, nil
}
func (m *MerkleTree) GetNextLayer(proofs Proofs) Proofs {
layer := make(Proofs, 0)
for idx, el := range proofs {
if idx%2 == 0 {
if idx+1 >= len(proofs) {
layer = append(layer, el)
} else {
layer = append(layer, combinedHash(el, proofs[idx+1]))
}
}
}
return layer
}
func (m *MerkleTree) getPairElement(idx int, layer Proofs) (common.Hash, bool) {
pairIdx := idx - 1
if idx%2 == 0 {
pairIdx = idx + 1
}
if pairIdx >= len(layer) {
return common.Hash{}, false
}
return layer[pairIdx], true
}
package util
import (
"bytes"
"github.com/ethereum/go-ethereum/common"
)
type AddressSlice []common.Address
func (s AddressSlice) Len() int {
return len(s)
}
func (s AddressSlice) Less(i, j int) bool {
return bytes.Compare(s[i].Bytes(), s[j].Bytes()) < 0
}
func (s AddressSlice) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
package version
import (
"github.com/prometheus/client_golang/prometheus"
)
var (
GitHash, GitBranch, BuildTime, GOVersion, Version string
)
var mistGauge = prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "witness_version_gauge",
}, []string{"gitHash", "gitBranch", "buildTime", "goVersion", "version"})
func init() {
prometheus.MustRegister(mistGauge)
mistGauge.WithLabelValues(GitHash, GitBranch, BuildTime, GOVersion, Version).Set(1)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment