@@ -8,6 +8,7 @@ import (
 	"time"

 	"crypto/ecdsa"
+	"fmt"
 	"github.com/spiffe/spire/pkg/common/util"
 	"github.com/spiffe/spire/proto/api/node"
 	"github.com/spiffe/spire/proto/common"

package cache

import (
	"crypto/sha256"
	"hash"
	"sort"
	"sync"
	"time"

	"crypto/ecdsa"
	"github.com/spiffe/spire/pkg/common/util"
	"github.com/spiffe/spire/proto/api/node"
	"github.com/spiffe/spire/proto/common"
)

type selectors []*common.Selector

type CacheEntry struct {
	RegistrationEntry *common.RegistrationEntry
	SVID              *node.Svid
	PrivateKey        *ecdsa.PrivateKey
	Expiry            time.Time

	// Bundles stores the ID => Bundle map for
	// federated bundles. The registration entry
	// only stores references to the keys here.
	Bundles map[string][]byte
}

type Cache interface {
	Entry([]*common.Selector) (entry []CacheEntry)
	SetEntry(cacheEntry CacheEntry)
	DeleteEntry([]*common.Selector) (deleted bool)
}

type cacheImpl struct {
	cache map[string][]CacheEntry
	m     sync.Mutex
}

func NewCache() *cacheImpl {
	return &cacheImpl{cache: make(map[string][]CacheEntry)}
}

func (c *cacheImpl) Entry(selectors []*common.Selector) (entry []CacheEntry) {
	key := deriveCacheKey(selectors)
	c.m.Lock()
	defer c.m.Unlock()
	return c.cache[key]
}

func (c *cacheImpl) SetEntry(cacheEntry CacheEntry) {
	c.m.Lock()
	defer c.m.Unlock()
	key := deriveCacheKey(cacheEntry.RegistrationEntry.Selectors)
	c.cache[key] = append(c.cache[key], cacheEntry)
	return

}

func (c *cacheImpl) DeleteEntry(selectors []*common.Selector) (deleted bool) {
	c.m.Lock()
	defer c.m.Unlock()
	key := deriveCacheKey(selectors)
	if _, exists := c.cache[key]; exists == true {
		delete(c.cache, key)
		deleted = true
	}
	return
}

func deriveCacheKey(s selectors) (key string) {
	var concatSelectors string
	sort.Slice(s, util.SelectorsSortFunction(s))

	for _, selector := range s {
		concatSelectors = concatSelectors + "::" + selector.Type + ":" + selector.Value
	}
	hashedSelectors := hash.Hash.Sum(sha256.New(), []byte(concatSelectors))

	return string(hashedSelectors)
}


@@ -18,6 +18,8 @@ package deployment

 import (
 	"net/http"
+	"os/exec"
+	"path"
 	"time"

 	. "github.com/onsi/ginkgo"

/*
Copyright 2019 The KubeEdge Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package deployment

import (
	"net/http"
	"time"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	appsv1 "k8s.io/api/apps/v1"
	corev1 "k8s.io/api/core/v1"

	"github.com/kubeedge/kubeedge/tests/e2e/constants"
	. "github.com/kubeedge/kubeedge/tests/e2e/testsuite"
	"github.com/kubeedge/kubeedge/tests/e2e/utils"
)

var DeploymentTestTimerGroup *utils.TestTimerGroup = utils.NewTestTimerGroup()

//Run Test cases
var _ = Describe("Application deployment test in E2E scenario", func() {
	var UID string
	var testTimer *utils.TestTimer
	var testDescription GinkgoTestDescription
	Context("Test application deployment and delete deployment using deployment spec", func() {
		BeforeEach(func() {
			// Get current test description
			testDescription = CurrentGinkgoTestDescription()
			// Start test timer
			testTimer = DeploymentTestTimerGroup.NewTestTimer(testDescription.TestText)
		})
		AfterEach(func() {
			// End test timer
			testTimer.End()
			// Print result
			testTimer.PrintResult()
			var podlist corev1.PodList
			var deploymentList appsv1.DeploymentList
			err := utils.GetDeployments(&deploymentList, ctx.Cfg.K8SMasterForKubeEdge+constants.DeploymentHandler)
			Expect(err).To(BeNil())
			for _, deployment := range deploymentList.Items {
				if deployment.Name == UID {
					label := nodeName
					podlist, err = utils.GetPods(ctx.Cfg.K8SMasterForKubeEdge+constants.AppHandler, label)
					Expect(err).To(BeNil())
					StatusCode := utils.DeleteDeployment(ctx.Cfg.K8SMasterForKubeEdge+constants.DeploymentHandler, deployment.Name)
					Expect(StatusCode).Should(Equal(http.StatusOK))
				}
			}
			utils.CheckPodDeleteState(ctx.Cfg.K8SMasterForKubeEdge+constants.AppHandler, podlist)
			utils.PrintTestcaseNameandStatus()
		})

		It("E2E_APP_DEPLOYMENT_1: Create deployment and check the pods are coming up correctly", func() {
			replica := 1
			//Generate the random string and assign as a UID
			UID = "edgecore-depl-app-" + utils.GetRandomString(5)
			CreateDeploymentTest(replica, UID, nodeName, nodeSelector, ctx)
		})
		It("E2E_APP_DEPLOYMENT_2: Create deployment with replicas and check the pods are coming up correctly", func() {
			replica := 3
			//Generate the random string and assign as a UID
			UID = "edgecore-depl-app-" + utils.GetRandomString(5)
			CreateDeploymentTest(replica, UID, nodeName, nodeSelector, ctx)
		})

		It("E2E_APP_DEPLOYMENT_3: Create deployment and check deployment ctrler re-creating pods when user deletes the pods manually", func() {
			replica := 3
			//Generate the random string and assign as a UID
			UID = "edgecore-depl-app-" + utils.GetRandomString(5)
			podlist := CreateDeploymentTest(replica, UID, nodeName, nodeSelector, ctx)
			for _, pod := range podlist.Items {
				_, StatusCode := utils.DeletePods(ctx.Cfg.K8SMasterForKubeEdge + constants.AppHandler + "/" + pod.Name)
				Expect(StatusCode).Should(Equal(http.StatusOK))
			}
			utils.CheckPodDeleteState(ctx.Cfg.K8SMasterForKubeEdge+constants.AppHandler, podlist)
			label := nodeName
			podlist, err := utils.GetPods(ctx.Cfg.K8SMasterForKubeEdge+constants.AppHandler, label)
			Expect(err).To(BeNil())
			Expect(len(podlist.Items)).Should(Equal(replica))
			utils.WaitforPodsRunning(ctx.Cfg.KubeConfigPath, podlist, 240*time.Second)
		})

	})
	Context("Test application deployment using Pod spec", func() {
		BeforeEach(func() {
			// Get current test description
			testDescription = CurrentGinkgoTestDescription()
			// Start test timer
			testTimer = DeploymentTestTimerGroup.NewTestTimer(testDescription.TestText)
		})
		AfterEach(func() {
			// End test timer
			testTimer.End()
			// Print result
			testTimer.PrintResult()
			var podlist corev1.PodList
			label := nodeName
			podlist, err := utils.GetPods(ctx.Cfg.K8SMasterForKubeEdge+constants.AppHandler, label)
			Expect(err).To(BeNil())
			for _, pod := range podlist.Items {
				_, StatusCode := utils.DeletePods(ctx.Cfg.K8SMasterForKubeEdge + constants.AppHandler + "/" + pod.Name)
				Expect(StatusCode).Should(Equal(http.StatusOK))
			}
			utils.CheckPodDeleteState(ctx.Cfg.K8SMasterForKubeEdge+constants.AppHandler, podlist)
			utils.PrintTestcaseNameandStatus()
		})

		It("E2E_POD_DEPLOYMENT_1: Create a pod and check the pod is coming up correctly", func() {
			//Generate the random string and assign as podName
			podName := "pod-app-" + utils.GetRandomString(5)
			pod := utils.NewPodObj(podName, ctx.Cfg.AppImageURL[0], nodeSelector)

			CreatePodTest(nodeName, podName, ctx, pod)
		})

		It("E2E_POD_DEPLOYMENT_2: Create the pod and delete pod happening successfully", func() {
			//Generate the random string and assign as podName
			podName := "pod-app-" + utils.GetRandomString(5)
			pod := utils.NewPodObj(podName, ctx.Cfg.AppImageURL[0], nodeSelector)

			podlist := CreatePodTest(nodeName, podName, ctx, pod)
			for _, pod := range podlist.Items {
				_, StatusCode := utils.DeletePods(ctx.Cfg.K8SMasterForKubeEdge + constants.AppHandler + "/" + pod.Name)
				Expect(StatusCode).Should(Equal(http.StatusOK))
			}
			utils.CheckPodDeleteState(ctx.Cfg.K8SMasterForKubeEdge+constants.AppHandler, podlist)
		})
		It("E2E_POD_DEPLOYMENT_3: Create pod and delete the pod successfully, and delete already deleted pod and check the behaviour", func() {
			//Generate the random string and assign as podName
			podName := "pod-app-" + utils.GetRandomString(5)
			pod := utils.NewPodObj(podName, ctx.Cfg.AppImageURL[0], nodeSelector)

			podlist := CreatePodTest(nodeName, podName, ctx, pod)
			for _, pod := range podlist.Items {
				_, StatusCode := utils.DeletePods(ctx.Cfg.K8SMasterForKubeEdge + constants.AppHandler + "/" + pod.Name)
				Expect(StatusCode).Should(Equal(http.StatusOK))
			}
			utils.CheckPodDeleteState(ctx.Cfg.K8SMasterForKubeEdge+constants.AppHandler, podlist)
			_, StatusCode := utils.DeletePods(ctx.Cfg.K8SMasterForKubeEdge + constants.AppHandler + "/" + UID)
			Expect(StatusCode).Should(Equal(http.StatusNotFound))
		})
		It("E2E_POD_DEPLOYMENT_4: Create and delete pod multiple times and check all the Pod created and deleted successfully", func() {
			//Generate the random string and assign as a UID
			for i := 0; i < 10; i++ {
				//Generate the random string and assign as podName
				podName := "pod-app-" + utils.GetRandomString(5)
				pod := utils.NewPodObj(podName, ctx.Cfg.AppImageURL[0], nodeSelector)

				podlist := CreatePodTest(nodeName, podName, ctx, pod)
				for _, pod := range podlist.Items {
					_, StatusCode := utils.DeletePods(ctx.Cfg.K8SMasterForKubeEdge + constants.AppHandler + "/" + pod.Name)
					Expect(StatusCode).Should(Equal(http.StatusOK))
				}
				utils.CheckPodDeleteState(ctx.Cfg.K8SMasterForKubeEdge+constants.AppHandler, podlist)
			}
		})
		It("E2E_POD_DEPLOYMENT_5: Create pod with hostpath volume successfully", func() {
			//Generate the random string and assign as podName
			podName := "pod-app-" + utils.GetRandomString(5)
			pod := utils.NewPodObj(podName, ctx.Cfg.AppImageURL[0], nodeSelector)

			pod.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{{
				Name:      "hp",
				MountPath: "/hp",
			}}
			pod.Spec.Volumes = []corev1.Volume{{
				Name: "hp",
				VolumeSource: corev1.VolumeSource{
					HostPath: &corev1.HostPathVolumeSource{Path: "/tmp"},
				},
			}}

			podlist := CreatePodTest(nodeName, podName, ctx, pod)
			for _, pod := range podlist.Items {
				_, StatusCode := utils.DeletePods(ctx.Cfg.K8SMasterForKubeEdge + constants.AppHandler + "/" + pod.Name)
				Expect(StatusCode).Should(Equal(http.StatusOK))
			}
			utils.CheckPodDeleteState(ctx.Cfg.K8SMasterForKubeEdge+constants.AppHandler, podlist)
		})
	})
})


@@ -167,5 +167,5 @@ func setup(conf config) (_ *frontend, _ *processor, cleanup func(), err error) {
 		bucket:     bucket,
 		coll:       coll,
 	}
-	return f, p, nil, nil
+	return f, p, cleanup, nil
 }

// Copyright 2019 The Go Cloud Development Kit Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"context"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"gocloud.dev/blob"
	"gocloud.dev/docstore"
	"gocloud.dev/pubsub"
)

var (
	requestTopicURL  = flag.String("request-topic", "mem://requests", "gocloud.dev/pubsub URL for request topic")
	requestSubURL    = flag.String("request-sub", "mem://requests", "gocloud.dev/pubsub URL for request subscription")
	responseTopicURL = flag.String("response-topic", "mem://responses", "gocloud.dev/pubsub URL for response topic")
	responseSubURL   = flag.String("response-sub", "mem://responses", "gocloud.dev/pubsub URL for response subscription")
	bucketURL        = flag.String("bucket", "", "gocloud.dev/blob URL for image bucket")
	collectionURL    = flag.String("collection", "mem://orders/ID", "gocloud.dev/docstore URL for order collection")

	port         = flag.Int("port", 10538, "HTTP port for frontend")
	runFrontend  = flag.Bool("frontend", true, "run the frontend")
	runProcessor = flag.Bool("processor", true, "run the image processor")
)

func main() {
	flag.Parse()
	conf := config{
		requestTopicURL:  *requestTopicURL,
		requestSubURL:    *requestSubURL,
		responseTopicURL: *responseTopicURL,
		responseSubURL:   *responseSubURL,
		bucketURL:        *bucketURL,
		collectionURL:    *collectionURL,
	}
	frontend, processor, cleanup, err := setup(conf)
	if err != nil {
		log.Fatal(err)
	}
	defer cleanup()

	// Run the frontend, or the processor, or both.
	// When we want to run both, one of them has to run in a goroutine.
	// So it's easier to run both in goroutines, even if we only need
	// to run one.
	errc := make(chan error, 2)
	if *runFrontend {
		go func() { errc <- frontend.run(context.Background(), *port) }()
		fmt.Printf("listening on port %d\n", *port)
	} else {
		errc <- nil
	}
	if *runProcessor {
		go func() { errc <- processor.run(context.Background()) }()
	} else {
		errc <- nil
	}
	// Each of the goroutines will send once to errc, so receive two values.
	for i := 0; i < 2; i++ {
		if err := <-errc; err != nil {
			log.Fatal(err)
		}
	}
}

// config describes the URLs for the resources used by the order application.
type config struct {
	requestTopicURL  string
	requestSubURL    string
	responseTopicURL string
	responseSubURL   string
	bucketURL        string
	collectionURL    string
}

// setup opens all the necessary resources for the application.
func setup(conf config) (_ *frontend, _ *processor, cleanup func(), err error) {
	// TODO(jba): simplify cleanup logic
	var cleanups []func()
	defer func() {
		// Clean up on error; return cleanup func on success.
		f := func() {
			for _, c := range cleanups {
				c()
			}
		}
		if err != nil {
			f()
			cleanup = nil
		} else {
			cleanup = f
		}
	}()

	ctx := context.Background()
	// TODO(jba): This application assumes at-least-once processing. Enforce that here if possible.
	reqTopic, err := pubsub.OpenTopic(ctx, conf.requestTopicURL)
	if err != nil {
		return nil, nil, nil, err
	}
	cleanups = append(cleanups, func() { reqTopic.Shutdown(ctx) })

	reqSub, err := pubsub.OpenSubscription(ctx, conf.requestSubURL)
	if err != nil {
		return nil, nil, nil, err
	}
	cleanups = append(cleanups, func() { reqSub.Shutdown(ctx) })

	resTopic, err := pubsub.OpenTopic(ctx, conf.responseTopicURL)
	if err != nil {
		return nil, nil, nil, err
	}
	cleanups = append(cleanups, func() { resTopic.Shutdown(ctx) })

	resSub, err := pubsub.OpenSubscription(ctx, conf.responseSubURL)
	if err != nil {
		return nil, nil, nil, err
	}
	cleanups = append(cleanups, func() { resSub.Shutdown(ctx) })

	burl := conf.bucketURL
	if burl == "" {
		dir, err := ioutil.TempDir("", "gocdk-order")
		if err != nil {
			return nil, nil, nil, err
		}
		burl = "file://" + filepath.ToSlash(dir)
		cleanups = append(cleanups, func() { os.Remove(dir) })
	}
	bucket, err := blob.OpenBucket(ctx, burl)
	if err != nil {
		return nil, nil, nil, err
	}
	cleanups = append(cleanups, func() { bucket.Close() })

	coll, err := docstore.OpenCollection(ctx, conf.collectionURL)
	if err != nil {
		return nil, nil, nil, err
	}
	cleanups = append(cleanups, func() { coll.Close() })

	f := &frontend{
		requestTopic: reqTopic,
		bucket:       bucket,
		coll:         coll,
	}
	p := &processor{
		requestSub: reqSub,
		bucket:     bucket,
		coll:       coll,
	}
	return f, p, nil, nil
}


@@ -66,6 +66,9 @@ func (j journalBlockServer) RemoveBlockReferences(
 	contexts map[BlockID][]BlockContext) (
 	liveCounts map[BlockID]int, err error) {
 	if tlfJournal, ok := j.jServer.getTLFJournal(tlfID); ok {
+		defer func() {
+			err = translateToBlockServerError(err)
+		}()
 		// TODO: Get server counts without making a
 		// RemoveBlockReferences call and merge it.
 		return tlfJournal.removeBlockReferences(ctx, contexts)

// Copyright 2016 Keybase Inc. All rights reserved.
// Use of this source code is governed by a BSD
// license that can be found in the LICENSE file.

package libkbfs

import "golang.org/x/net/context"

type journalBlockServer struct {
	jServer *JournalServer
	BlockServer
	enableAddBlockReference bool
}

var _ BlockServer = journalBlockServer{}

func (j journalBlockServer) Get(
	ctx context.Context, tlfID TlfID, id BlockID, context BlockContext) (
	[]byte, BlockCryptKeyServerHalf, error) {
	if tlfJournal, ok := j.jServer.getTLFJournal(tlfID); ok {
		data, serverHalf, err := tlfJournal.getBlockDataWithContext(
			id, context)
		switch err.(type) {
		case nil:
			return data, serverHalf, nil
		case BServerErrorBlockNonExistent:
			return j.BlockServer.Get(ctx, tlfID, id, context)
		default:
			return nil, BlockCryptKeyServerHalf{}, err
		}
	}

	return j.BlockServer.Get(ctx, tlfID, id, context)
}

func (j journalBlockServer) Put(
	ctx context.Context, tlfID TlfID, id BlockID, context BlockContext,
	buf []byte, serverHalf BlockCryptKeyServerHalf) error {
	if tlfJournal, ok := j.jServer.getTLFJournal(tlfID); ok {
		return tlfJournal.putBlockData(ctx, id, context, buf, serverHalf)
	}

	return j.BlockServer.Put(ctx, tlfID, id, context, buf, serverHalf)
}

func (j journalBlockServer) AddBlockReference(
	ctx context.Context, tlfID TlfID, id BlockID,
	context BlockContext) error {
	if !j.enableAddBlockReference {
		// TODO: Temporarily return an error until KBFS-1149 is
		// fixed. This is needed despite
		// journalBlockCache.CheckForBlockPtr, since CheckForBlockPtr
		// may be called before journaling is turned on for a TLF.
		return BServerErrorBlockNonExistent{}
	}

	if tlfJournal, ok := j.jServer.getTLFJournal(tlfID); ok {
		return tlfJournal.addBlockReference(ctx, id, context)
	}

	return j.BlockServer.AddBlockReference(ctx, tlfID, id, context)
}

func (j journalBlockServer) RemoveBlockReferences(
	ctx context.Context, tlfID TlfID,
	contexts map[BlockID][]BlockContext) (
	liveCounts map[BlockID]int, err error) {
	if tlfJournal, ok := j.jServer.getTLFJournal(tlfID); ok {
		// TODO: Get server counts without making a
		// RemoveBlockReferences call and merge it.
		return tlfJournal.removeBlockReferences(ctx, contexts)
	}

	return j.BlockServer.RemoveBlockReferences(ctx, tlfID, contexts)
}

func (j journalBlockServer) ArchiveBlockReferences(
	ctx context.Context, tlfID TlfID,
	contexts map[BlockID][]BlockContext) error {
	if tlfJournal, ok := j.jServer.getTLFJournal(tlfID); ok {
		return tlfJournal.archiveBlockReferences(ctx, contexts)
	}

	return j.BlockServer.ArchiveBlockReferences(ctx, tlfID, contexts)
}

func (j journalBlockServer) Shutdown() {
	j.jServer.shutdown()
}


@@ -27,7 +27,11 @@ import (
 	"github.com/iotexproject/iotex-proto/golang/iotextypes"
 )

+var nativeStakingContractCreator = address.ZeroAddress
+var nativeStakingContractNonce = uint64(0)
+
 type stakingCommittee struct {
+	candidatesByHeight   CandidatesByHeight
 	getEpochHeight       GetEpochHeight
 	getEpochNum          GetEpochNum
 	electionCommittee    committee.Committee

// Copyright (c) 2019 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.

package poll

import (
	"context"
	"encoding/hex"
	"math/big"
	"time"

	"github.com/pkg/errors"
	"go.uber.org/zap"

	"github.com/iotexproject/iotex-core/action"
	"github.com/iotexproject/iotex-core/action/protocol"
	"github.com/iotexproject/iotex-core/action/protocol/rolldpos"
	"github.com/iotexproject/iotex-core/config"
	"github.com/iotexproject/iotex-core/pkg/log"
	"github.com/iotexproject/iotex-core/state"
	"github.com/iotexproject/iotex-election/committee"
	"github.com/iotexproject/iotex-election/types"
	"github.com/iotexproject/iotex-election/util"
	"github.com/iotexproject/iotex-proto/golang/iotextypes"
)

type stakingCommittee struct {
	getEpochHeight       GetEpochHeight
	getEpochNum          GetEpochNum
	electionCommittee    committee.Committee
	governanceStaking    Protocol
	nativeStaking        *NativeStaking
	rp                   *rolldpos.Protocol
	scoreThreshold       *big.Int
	currentNativeBuckets []*types.Bucket
}

// NewStakingCommittee creates a staking committee which fetch result from governance chain and native staking
func NewStakingCommittee(
	ec committee.Committee,
	gs Protocol,
	readContract ReadContract,
	getEpochHeight GetEpochHeight,
	getEpochNum GetEpochNum,
	nativeStakingContractAddress string,
	nativeStakingContractCode string,
	rp *rolldpos.Protocol,
	scoreThreshold *big.Int,
) (Protocol, error) {
	if getEpochHeight == nil {
		return nil, errors.New("failed to create native staking: empty getEpochHeight")
	}
	if getEpochNum == nil {
		return nil, errors.New("failed to create native staking: empty getEpochNum")
	}
	var ns *NativeStaking
	if nativeStakingContractAddress != "" || nativeStakingContractCode != "" {
		var err error
		if ns, err = NewNativeStaking(readContract); err != nil {
			return nil, errors.New("failed to create native staking")
		}
		if nativeStakingContractAddress != "" {
			ns.SetContract(nativeStakingContractAddress)
		}
	}
	return &stakingCommittee{
		electionCommittee: ec,
		governanceStaking: gs,
		nativeStaking:     ns,
		getEpochHeight:    getEpochHeight,
		getEpochNum:       getEpochNum,
		rp:                rp,
		scoreThreshold:    scoreThreshold,
	}, nil
}

func (sc *stakingCommittee) Initialize(ctx context.Context, sm protocol.StateManager) error {
	return sc.governanceStaking.Initialize(ctx, sm)
}

func (sc *stakingCommittee) Handle(ctx context.Context, act action.Action, sm protocol.StateManager) (*action.Receipt, error) {
	receipt, err := sc.governanceStaking.Handle(ctx, act, sm)
	if err := sc.persistNativeBuckets(ctx, receipt, err); err != nil {
		return nil, err
	}
	return receipt, err
}

func (sc *stakingCommittee) Validate(ctx context.Context, act action.Action) error {
	return validate(ctx, sc, act)
}

func (sc *stakingCommittee) DelegatesByHeight(ctx context.Context, height uint64) (state.CandidateList, error) {
	cand, err := sc.governanceStaking.DelegatesByHeight(ctx, height)
	if err != nil {
		return nil, err
	}
	vaCtx := protocol.MustGetValidateActionsCtx(ctx)
	hu := config.NewHeightUpgrade(&vaCtx.Genesis)
	// convert to epoch start height
	if hu.IsPre(config.Cook, sc.getEpochHeight(sc.getEpochNum(height))) {
		return sc.filterDelegates(cand), nil
	}
	// native staking starts from Cook
	if sc.nativeStaking == nil {
		return nil, errors.New("native staking was not set after cook height")
	}

	nativeVotes, err := sc.nativeStaking.Votes(vaCtx.Tip.Height, vaCtx.Tip.Timestamp)
	if err == ErrNoData {
		// no native staking data
		return sc.filterDelegates(cand), nil
	}
	if err != nil {
		return nil, errors.Wrap(err, "failed to get native chain candidates")
	}
	sc.currentNativeBuckets = nativeVotes.Buckets

	return sc.mergeDelegates(cand, nativeVotes, vaCtx.Tip.Timestamp), nil
}

func (sc *stakingCommittee) ReadState(ctx context.Context, sm protocol.StateManager, method []byte, args ...[]byte) ([]byte, error) {
	return sc.governanceStaking.ReadState(ctx, sm, method, args...)
}

// SetNativeStakingContract sets the address of native staking contract
func (sc *stakingCommittee) SetNativeStakingContract(contract string) {
	sc.nativeStaking.SetContract(contract)
}

// return candidates whose votes are above threshold
func (sc *stakingCommittee) filterDelegates(candidates state.CandidateList) state.CandidateList {
	var cand state.CandidateList
	for _, c := range candidates {
		if c.Votes.Cmp(sc.scoreThreshold) >= 0 {
			cand = append(cand, c)
		}
	}
	return cand
}

func (sc *stakingCommittee) mergeDelegates(list state.CandidateList, votes *VoteTally, ts time.Time) state.CandidateList {
	// as of now, native staking does not have register contract, only voting/staking contract
	// it is assumed that all votes done on native staking target for delegates registered on Ethereum
	// votes cast to all outside address will not be counted and simply ignored
	candidates := make(map[string]*state.Candidate)
	candidateScores := make(map[string]*big.Int)
	for _, cand := range list {
		clone := cand.Clone()
		name := to12Bytes(clone.CanName)
		if v, ok := votes.Candidates[name]; ok {
			clone.Votes.Add(clone.Votes, v.Votes)
		}
		if clone.Votes.Cmp(sc.scoreThreshold) >= 0 {
			candidates[hex.EncodeToString(name[:])] = clone
			candidateScores[hex.EncodeToString(name[:])] = clone.Votes
		}
	}
	sorted := util.Sort(candidateScores, uint64(ts.Unix()))
	var merged state.CandidateList
	for _, name := range sorted {
		merged = append(merged, candidates[name])
	}
	return merged
}

func (sc *stakingCommittee) persistNativeBuckets(ctx context.Context, receipt *action.Receipt, err error) error {
	// Start to write native buckets archive after cook and only when the action is executed successfully
	raCtx := protocol.MustGetRunActionsCtx(ctx)
	epochHeight := sc.getEpochHeight(sc.getEpochNum(raCtx.BlockHeight))
	hu := config.NewHeightUpgrade(&raCtx.Genesis)
	if hu.IsPre(config.Cook, epochHeight) {
		return nil
	}
	if err != nil {
		return nil
	}
	if receipt == nil || receipt.Status != uint64(iotextypes.ReceiptStatus_Success) {
		return nil
	}
	log.L().Info("Store native buckets to election db", zap.Int("size", len(sc.currentNativeBuckets)))
	if err := sc.electionCommittee.PutNativePollByEpoch(
		sc.rp.GetEpochNum(raCtx.BlockHeight)+1, // The native buckets recorded in this epoch will be used in next one
		raCtx.Tip.Timestamp,                    // The timestamp of last block is used to represent the current buckets timestamp
		sc.currentNativeBuckets,
	); err != nil {
		return err
	}
	sc.currentNativeBuckets = nil
	return nil
}


@@ -53,7 +53,8 @@ var telemetryStatusCmd = &cobra.Command{
 	Short: "Print the node's telemetry status",
 	Long:  `Print the node's telemetry status`,
 	Run: func(cmd *cobra.Command, args []string) {
-		cfg, err := logging.EnsureTelemetryConfig(nil, "")
+		maybeUpdateDataDirFromEnv()
+		cfg, err := logging.EnsureTelemetryConfig(&dataDir, "")

 		// If error loading config, can't disable / no need to disable
 		if err != nil {

// Copyright (C) 2019 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// go-algorand is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with go-algorand.  If not, see <https://www.gnu.org/licenses/>.

package main

import (
	"fmt"

	"github.com/spf13/cobra"

	"github.com/algorand/go-algorand/logging"
)

var (
	nodeName string
	uri      string
)

func init() {
	telemetryCmd.AddCommand(telemetryStatusCmd)
	telemetryCmd.AddCommand(telemetryEnableCmd)
	telemetryCmd.AddCommand(telemetryDisableCmd)
	telemetryCmd.AddCommand(telemetryNameCmd)
	telemetryCmd.AddCommand(telemetryEndpointCmd)

	// Enable Logging : node name
	telemetryNameCmd.Flags().StringVarP(&nodeName, "name", "n", "", "Friendly-name to use for node")
	telemetryEndpointCmd.Flags().StringVarP(&uri, "endpoint", "e", "", "Endpoint's URI")
}

var telemetryCmd = &cobra.Command{
	Use:   "telemetry",
	Short: "Control and manage Algorand logging",
	Long:  `Enable/disable and configure Algorand remote logging`,
	Run:   telemetryStatusCmd.Run,
}

var telemetryStatusCmd = &cobra.Command{
	Use:   "status",
	Short: "Print the node's telemetry status",
	Long:  `Print the node's telemetry status`,
	Run: func(cmd *cobra.Command, args []string) {
		cfg, err := logging.EnsureTelemetryConfig(nil, "")

		// If error loading config, can't disable / no need to disable
		if err != nil {
			fmt.Println(err)
			fmt.Println(loggingNotConfigured)
		} else if cfg.Enable == false {
			fmt.Println(loggingNotEnabled)
		} else {
			fmt.Printf(loggingEnabled, cfg.Name, cfg.GUID)
		}
	},
}

var telemetryEnableCmd = &cobra.Command{
	Use:   "enable",
	Short: "Enable Algorand remote logging",
	Long:  `Enable Algorand remote logging`,
	Run: func(cmd *cobra.Command, args []string) {
		cfg, err := logging.EnsureTelemetryConfig(nil, "")

		// If error loading config, can't disable / no need to disable
		if err != nil {
			return
		}

		cfg.Enable = true
		cfg.Save(cfg.FilePath)
		fmt.Printf("Telemetry logging enabled: Name = %s, Guid = %s\n", cfg.Name, cfg.GUID)
	},
}

var telemetryDisableCmd = &cobra.Command{
	Use:   "disable",
	Short: "Disable Algorand remote logging",
	Long:  `Disable Algorand remote logging`,
	Run: func(cmd *cobra.Command, args []string) {
		cfg, err := logging.EnsureTelemetryConfig(nil, "")

		// If error loading config, can't disable / no need to disable
		if err != nil {
			return
		}

		cfg.Enable = false
		cfg.Save(cfg.FilePath)
		fmt.Printf("Telemetry logging disabled: Name = %s, Guid = %s\n", cfg.Name, cfg.GUID)
	},
}

var telemetryNameCmd = &cobra.Command{
	Use:   "name -n nodeName",
	Short: "Enable Algorand remote logging",
	Long:  `Enable Algorand remote logging with specified node name`,
	Run: func(cmd *cobra.Command, args []string) {
		cfg, err := logging.EnsureTelemetryConfig(nil, "")
		if err != nil {
			fmt.Println(err)
			return
		}
		cfg.Enable = true
		if len(nodeName) > 0 {
			cfg.Name = nodeName
		}
		cfg.Save(cfg.FilePath)
		fmt.Printf("Telemetry logging: Name = %s, Guid = %s\n", cfg.Name, cfg.GUID)
	},
}

var telemetryEndpointCmd = &cobra.Command{
	Use:   "endpoint -e <url>",
	Short: "sets the \"URI\" property",
	Long:  `Sets the "URI" property in the telemetry configuration`,
	Run: func(cmd *cobra.Command, args []string) {
		cfg, err := logging.EnsureTelemetryConfig(nil, "")
		if err != nil {
			fmt.Println(err)
			return
		}
		cfg.URI = uri
		cfg.Save(cfg.FilePath)
		fmt.Printf("Telemetry logging: Name = %s, Guid = %s, URI = %s\n", cfg.Name, cfg.GUID, cfg.URI)
	},
}


@@ -84,7 +84,7 @@ func byteOrNil(data []byte) *[]byte {
 	return &data
 }

-func computeAssetIndexInPayset(tx node.TxnWithStatus, txnCounter uint64, payset []transactions.SignedTxnWithAD) (aidx *uint64) {
+func computeCreatableIndexInPayset(tx node.TxnWithStatus, txnCounter uint64, payset []transactions.SignedTxnWithAD) (cidx *uint64) {
 	// Compute transaction index in block
 	offset := -1
 	for idx, stxnib := range payset {

// Copyright (C) 2019-2020 Algorand, Inc.
// This file is part of go-algorand
//
// go-algorand is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// go-algorand is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with go-algorand.  If not, see <https://www.gnu.org/licenses/>.

package v2

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/algorand/go-codec/codec"
	"github.com/labstack/echo/v4"

	"github.com/algorand/go-algorand/daemon/algod/api/server/v2/generated"
	"github.com/algorand/go-algorand/data"
	"github.com/algorand/go-algorand/data/basics"
	"github.com/algorand/go-algorand/data/transactions"
	"github.com/algorand/go-algorand/logging"
	"github.com/algorand/go-algorand/node"
	"github.com/algorand/go-algorand/protocol"
)

// returnError logs an internal message while returning the encoded response.
func returnError(ctx echo.Context, code int, internal error, external string, logger logging.Logger) error {
	logger.Info(internal)
	return ctx.JSON(code, generated.ErrorResponse{Message: external})
}

func badRequest(ctx echo.Context, internal error, external string, log logging.Logger) error {
	return returnError(ctx, http.StatusBadRequest, internal, external, log)
}

func serviceUnavailable(ctx echo.Context, internal error, external string, log logging.Logger) error {
	return returnError(ctx, http.StatusServiceUnavailable, internal, external, log)
}

func internalError(ctx echo.Context, internal error, external string, log logging.Logger) error {
	return returnError(ctx, http.StatusInternalServerError, internal, external, log)
}

func notFound(ctx echo.Context, internal error, external string, log logging.Logger) error {
	return returnError(ctx, http.StatusNotFound, internal, external, log)
}

func addrOrNil(addr basics.Address) *string {
	if addr.IsZero() {
		return nil
	}
	ret := addr.String()
	return &ret
}

func strOrNil(str string) *string {
	if str == "" {
		return nil
	}
	return &str
}

func numOrNil(num uint64) *uint64 {
	if num == 0 {
		return nil
	}
	return &num
}

func byteOrNil(data []byte) *[]byte {
	if len(data) == 0 {
		return nil
	}
	return &data
}

func computeAssetIndexInPayset(tx node.TxnWithStatus, txnCounter uint64, payset []transactions.SignedTxnWithAD) (aidx *uint64) {
	// Compute transaction index in block
	offset := -1
	for idx, stxnib := range payset {
		if tx.Txn.Txn.ID() == stxnib.Txn.ID() {
			offset = idx
			break
		}
	}

	// Sanity check that txn was in fetched block
	if offset < 0 {
		return nil
	}

	// Count into block to get created asset index
	idx := txnCounter - uint64(len(payset)) + uint64(offset) + 1
	return &idx
}

// computeAssetIndexFromTxn returns the created asset index given a confirmed
// transaction whose confirmation block is available in the ledger. Note that
// 0 is an invalid asset index (they start at 1).
func computeAssetIndexFromTxn(tx node.TxnWithStatus, l *data.Ledger) (aidx *uint64) {
	// Must have ledger
	if l == nil {
		return nil
	}
	// Transaction must be confirmed
	if tx.ConfirmedRound == 0 {
		return nil
	}
	// Transaction must be AssetConfig transaction
	if tx.Txn.Txn.AssetConfigTxnFields == (transactions.AssetConfigTxnFields{}) {
		return nil
	}
	// Transaction must be creating an asset
	if tx.Txn.Txn.AssetConfigTxnFields.ConfigAsset != 0 {
		return nil
	}

	// Look up block where transaction was confirmed
	blk, err := l.Block(tx.ConfirmedRound)
	if err != nil {
		return nil
	}

	payset, err := blk.DecodePaysetFlat()
	if err != nil {
		return nil
	}

	return computeAssetIndexInPayset(tx, blk.BlockHeader.TxnCounter, payset)
}

// getCodecHandle converts a format string into the encoder + content type
func getCodecHandle(formatPtr *string) (codec.Handle, string, error) {
	format := "json"
	if formatPtr != nil {
		format = strings.ToLower(*formatPtr)
	}

	switch format {
	case "json":
		return protocol.JSONHandle, "application/json", nil
	case "msgpack":
		fallthrough
	case "msgp":
		return protocol.CodecHandle, "application/msgpack", nil
	default:
		return nil, "", fmt.Errorf("invalid format: %s", format)
	}
}

func encode(handle codec.Handle, obj interface{}) ([]byte, error) {
	var output []byte
	enc := codec.NewEncoderBytes(&output, handle)

	err := enc.Encode(obj)
	if err != nil {
		return nil, fmt.Errorf("failed to encode object: %v", err)
	}
	return output, nil
}

func decode(handle codec.Handle, data []byte, v interface{}) error {
	enc := codec.NewDecoderBytes(data, handle)

	err := enc.Decode(v)
	if err != nil {
		return fmt.Errorf("failed to decode object: %v", err)
	}
	return nil
}


@@ -107,8 +107,8 @@ var orderCreateCmd = &cobra.Command{
 }

 var orderCancelCmd = &cobra.Command{
-	Use:   "cancel <order_id>",
-	Short: "Cancel order on Marketplace",
+	Use:   "cancel <order_id>...",
+	Short: "Cancel given orders on Marketplace",
 	Args:  cobra.MinimumNArgs(1),
 	RunE: func(cmd *cobra.Command, args []string) error {
 		ctx, cancel := newTimeoutContext()

package commands

import (
	"fmt"

	"github.com/sonm-io/core/cmd/cli/task_config"
	pb "github.com/sonm-io/core/proto"
	"github.com/spf13/cobra"
)

var (
	ordersSearchLimit uint64 = 0
)

func init() {
	orderListCmd.PersistentFlags().Uint64Var(&ordersSearchLimit, "limit", 10, "Orders count to show")

	orderRootCmd.AddCommand(
		orderListCmd,
		orderStatusCmd,
		orderCreateCmd,
		orderCancelCmd,
		orderPurgeCmd,
	)
}

var orderRootCmd = &cobra.Command{
	Use:               "order",
	Short:             "Manage orders",
	PersistentPreRunE: loadKeyStoreWrapper,
}

var orderListCmd = &cobra.Command{
	Use:   "list",
	Short: "Show your active orders",
	RunE: func(cmd *cobra.Command, args []string) error {
		ctx, cancel := newTimeoutContext()
		defer cancel()

		market, err := newMarketClient(ctx)
		if err != nil {
			return fmt.Errorf("сannot create client connection: %v", err)
		}

		req := &pb.Count{Count: ordersSearchLimit}
		reply, err := market.GetOrders(ctx, req)
		if err != nil {
			return fmt.Errorf("cannot receive orders from marketplace: %v", err)
		}

		printOrdersList(cmd, reply.Orders)
		return nil
	},
}

var orderStatusCmd = &cobra.Command{
	Use:   "status <order_id>",
	Short: "Show order stats",
	Args:  cobra.MinimumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		ctx, cancel := newTimeoutContext()
		defer cancel()

		market, err := newMarketClient(ctx)
		if err != nil {
			return fmt.Errorf("cannot create client connection: %v", err)
		}

		orderID := args[0]
		order, err := market.GetOrderByID(ctx, &pb.ID{Id: orderID})
		if err != nil {
			return fmt.Errorf("cannot get order by ID: %v", err)
		}

		printOrderDetails(cmd, order)
		return nil
	},
}

var orderCreateCmd = &cobra.Command{
	Use:   "create <bid.yaml>",
	Short: "Place new Bid order on Marketplace",
	Args:  cobra.MinimumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		ctx, cancel := newTimeoutContext()
		defer cancel()

		market, err := newMarketClient(ctx)
		if err != nil {
			return fmt.Errorf("cannot create client connection: %v", err)
		}

		path := args[0]
		bid := &pb.BidOrder{}
		if err := task_config.LoadFromFile(path, bid); err != nil {
			return fmt.Errorf("cannot load order definition: %v", err)
		}

		created, err := market.CreateOrder(ctx, bid)
		if err != nil {
			return fmt.Errorf("cannot create order on marketplace: %v", err)
		}

		printID(cmd, created.GetId().Unwrap().String())
		return nil
	},
}

var orderCancelCmd = &cobra.Command{
	Use:   "cancel <order_id>",
	Short: "Cancel order on Marketplace",
	Args:  cobra.MinimumNArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		ctx, cancel := newTimeoutContext()
		defer cancel()

		market, err := newMarketClient(ctx)
		if err != nil {
			return fmt.Errorf("cannot create client connection: %v", err)
		}

		orderID := args[0]
		_, err = market.CancelOrder(ctx, &pb.ID{Id: orderID})
		if err != nil {
			return fmt.Errorf("cannot cancel order on Marketplace: %v", err)
		}

		showOk(cmd)
		return nil
	},
}

var orderPurgeCmd = &cobra.Command{
	Use:   "purge",
	Short: "Remove all your orders from Marketplace",
	RunE: func(cmd *cobra.Command, _ []string) error {
		ctx, cancel := newTimeoutContext()
		defer cancel()

		market, err := newMarketClient(ctx)
		if err != nil {
			return fmt.Errorf("cannot create client connection: %v", err)
		}

		if _, err := market.Purge(ctx, &pb.Empty{}); err != nil {
			return fmt.Errorf("cannot purge orders: %v", err)
		}

		showOk(cmd)
		return nil
	},
}


@@ -134,6 +134,10 @@ func (e *dErrImpl) Error() string {
 	return "Multiple errors:\n" + strings.Join(lines, "\n")
 }

+func (e *dErrImpl) AnonymizedErrs() []string {
+	return e.anonymizedErrs
+}
+
 func (e *dErrImpl) len() int {
 	return len(e.errs)
 }

//  Copyright 2017 Google Inc. All Rights Reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

package daisy

import (
	"fmt"
	"strings"
)

const (
	untypedError              = ""
	multiError                = "MultiError"
	fileIOError               = "FileIOError"
	resourceDNEError          = "ResourceDoesNotExist"
	imageObsoleteDeletedError = "ImageObsoleteOrDeleted"

	apiError    = "APIError"
	apiError404 = "APIError404"
)

// dErr is a Daisy internal error type.
// It has:
// - optional error typing
// - multiple error aggregation
//
// Default implementation:
// The default dErr implementation is flat, dErr.add(anotherDErr) will merge the two dErrs
// into a single, flat dErr instead of making anotherDErr a child to dErr.
type dErr interface {
	error

	// add shouldn't be called directly, instead call addErrs(dErr, error).
	// This assists with nil dErrs. addErrs(nil, e) will return a new dErr.
	add(error)
	Type() string
}

// addErrs adds an error to a dErr.
// The dErr can be nil. If both the dErr and errors are nil, a nil dErr is returned.
// If dErr is nil, but errors are not nil, a new dErr is instantiated, the errors are added,
// and the new dErr is returned.
// Any nil error in errs is disregarded. Therefore, `var e dErr; e = addErrs(e, nil)`
// preserves e's nil-ness.
func addErrs(e dErr, errs ...error) dErr {
	for _, err := range errs {
		if err != nil {
			if e == nil {
				e = &dErrImpl{}
			}
			e.add(err)
		}
	}
	return e
}

func errf(format string, a ...interface{}) dErr {
	return newErr(fmt.Errorf(format, a...))
}

// newErr returns a dErr. newErr is used to wrap another error as a dErr.
// If e is already a dErr, e is copied and returned.
// If e is nil, nil is returned.
func newErr(e error) dErr {
	if e == nil {
		return nil
	}
	if dE, ok := e.(*dErrImpl); ok {
		return dE
	}
	return &dErrImpl{errs: []error{e}}
}

func typedErr(errType string, e error) dErr {
	if e == nil {
		return nil
	}
	dE := newErr(e)
	dE.(*dErrImpl).errType = errType
	return dE
}

func typedErrf(errType, format string, a ...interface{}) dErr {
	return typedErr(errType, fmt.Errorf(format, a...))
}

type dErrImpl struct {
	errs    []error
	errType string
}

func (e *dErrImpl) add(err error) {
	if e2, ok := err.(*dErrImpl); ok {
		e.merge(e2)
	} else if !ok {
		// This is some other error type. Add it.
		e.errs = append(e.errs, err)
	}
	if e.len() > 1 {
		e.errType = multiError
	}
}

func (e *dErrImpl) Error() string {
	if e.len() == 0 {
		return ""
	}
	if e.len() == 1 {
		errStr := e.errs[0].Error()
		if e.errType != "" {
			return fmt.Sprintf("%s: %s", e.errType, errStr)
		}
		return errStr
	}

	// Multiple error handling.
	pre := "* "
	lines := make([]string, e.len())
	for i, err := range e.errs {
		lines[i] = pre + err.Error()
	}

	return "Multiple errors:\n" + strings.Join(lines, "\n")
}

func (e *dErrImpl) len() int {
	return len(e.errs)
}

func (e *dErrImpl) merge(e2 *dErrImpl) {
	if e2.len() > 0 {
		e.errs = append(e.errs, e2.errs...)
		// Take e2's type. This solves the situation of e having 0 errors, and e2 having 1.
		// Of course, there is a possibility of len(e) > 0 and len(e2) > 1, in which case,
		// the type should be a multiError.
		e.errType = e2.errType
		if e.len() > 1 {
			e.errType = multiError
		}
	}
}

func (e *dErrImpl) Type() string {
	return e.errType
}


@@ -2,7 +2,10 @@ package h2quic

 import (
 	"bytes"
+	"errors"
+	"fmt"
 	"net/http"
+	"net/url"
 	"strconv"
 	"strings"
 	"sync"

package h2quic

import (
	"bytes"
	"net/http"
	"strconv"
	"strings"
	"sync"

	quic "github.com/lucas-clemente/quic-go"
	"github.com/lucas-clemente/quic-go/internal/protocol"
	"github.com/lucas-clemente/quic-go/internal/utils"
	"golang.org/x/net/http2"
	"golang.org/x/net/http2/hpack"
)

type responseWriter struct {
	dataStreamID protocol.StreamID
	dataStream   quic.Stream

	headerStream      quic.Stream
	headerStreamMutex *sync.Mutex

	header        http.Header
	status        int // status code passed to WriteHeader
	headerWritten bool

	settings *sessionSettings
}

func newResponseWriter(headerStream quic.Stream, headerStreamMutex *sync.Mutex, dataStream quic.Stream, dataStreamID protocol.StreamID, settings *sessionSettings) *responseWriter {
	return &responseWriter{
		header:            http.Header{},
		headerStream:      headerStream,
		headerStreamMutex: headerStreamMutex,
		dataStream:        dataStream,
		dataStreamID:      dataStreamID,
		settings:          settings,
	}
}

func (w *responseWriter) Header() http.Header {
	return w.header
}

func (w *responseWriter) WriteHeader(status int) {
	if w.headerWritten {
		return
	}
	w.headerWritten = true
	w.status = status

	var headers bytes.Buffer
	enc := hpack.NewEncoder(&headers)
	enc.WriteField(hpack.HeaderField{Name: ":status", Value: strconv.Itoa(status)})

	for k, v := range w.header {
		for index := range v {
			enc.WriteField(hpack.HeaderField{Name: strings.ToLower(k), Value: v[index]})
		}
	}

	utils.Infof("Responding with %d", status)
	w.headerStreamMutex.Lock()
	defer w.headerStreamMutex.Unlock()
	h2framer := http2.NewFramer(w.headerStream, nil)
	err := h2framer.WriteHeaders(http2.HeadersFrameParam{
		StreamID:      uint32(w.dataStreamID),
		EndHeaders:    true,
		BlockFragment: headers.Bytes(),
	})
	if err != nil {
		utils.Errorf("could not write h2 header: %s", err.Error())
	}
}

func (w *responseWriter) Write(p []byte) (int, error) {
	if !w.headerWritten {
		w.WriteHeader(200)
	}
	if !bodyAllowedForStatus(w.status) {
		return 0, http.ErrBodyNotAllowed
	}
	return w.dataStream.Write(p)
}

func (w *responseWriter) Flush() {}

// This is a NOP. Use http.Request.Context
func (w *responseWriter) CloseNotify() <-chan bool { return make(<-chan bool) }

// test that we implement http.Flusher
var _ http.Flusher = &responseWriter{}

// test that we implement http.CloseNotifier
var _ http.CloseNotifier = &responseWriter{}

// copied from http2/http2.go
// bodyAllowedForStatus reports whether a given response status code
// permits a body. See RFC 2616, section 4.4.
func bodyAllowedForStatus(status int) bool {
	switch {
	case status >= 100 && status <= 199:
		return false
	case status == 204:
		return false
	case status == 304:
		return false
	}
	return true
}


@@ -129,7 +129,7 @@ func (pl *RoundRobin) Remove(pid transport.PeerIdentifier) error {
 	pl.lock.Lock()
 	defer pl.lock.Unlock()

-	if err := pl.pr.Remove(pid); err != nil {
+	if err := pl.removeByPeerIdentifier(pid); err != nil {
 		// The peer has already been removed
 		return err
 	}

// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package roundrobin

import (
	"context"
	"sync"

	yerrors "go.uber.org/yarpc/internal/errors"
	"go.uber.org/yarpc/transport"
	"go.uber.org/yarpc/transport/internal/errors"

	"go.uber.org/atomic"
)

// New creates a new round robin PeerList using
func New(peerIDs []transport.PeerIdentifier, agent transport.Agent) (*RoundRobin, error) {
	rr := &RoundRobin{
		pr:                 NewPeerRing(len(peerIDs)),
		agent:              agent,
		peerAvailableEvent: make(chan struct{}, 1),
	}

	err := rr.addAll(peerIDs)
	return rr, err
}

// RoundRobin is a PeerList which rotates which peers are to be selected in a circle
type RoundRobin struct {
	lock sync.Mutex

	pr                 *PeerRing
	peerAvailableEvent chan struct{}
	agent              transport.Agent
	started            atomic.Bool
}

func (pl *RoundRobin) addAll(peerIDs []transport.PeerIdentifier) error {
	pl.lock.Lock()
	defer pl.lock.Unlock()

	var errs []error

	for _, peerID := range peerIDs {
		if err := pl.addPeer(peerID); err != nil {
			errs = append(errs, err)
			continue
		}
	}

	return yerrors.MultiError(errs)
}

// Add a peer identifier to the round robin
func (pl *RoundRobin) Add(pid transport.PeerIdentifier) error {
	pl.lock.Lock()
	err := pl.addPeer(pid)
	pl.lock.Unlock()
	return err
}

// Must be run inside a mutex.Lock()
func (pl *RoundRobin) addPeer(pid transport.PeerIdentifier) error {
	p, err := pl.agent.RetainPeer(pid, pl)
	if err != nil {
		return err
	}

	if err = pl.pr.Add(p); err != nil {
		return err
	}

	pl.notifyPeerAvailable()
	return nil
}

// Start notifies the RoundRobin that requests will start coming
func (pl *RoundRobin) Start() error {
	if pl.started.Swap(true) {
		return errors.ErrPeerListAlreadyStarted("RoundRobinList")
	}
	return nil
}

// Stop notifies the RoundRobin that requests will stop coming
func (pl *RoundRobin) Stop() error {
	if !pl.started.Swap(false) {
		return errors.ErrPeerListNotStarted("RoundRobinList")
	}
	return pl.clearPeers()
}

func (pl *RoundRobin) clearPeers() error {
	pl.lock.Lock()
	defer pl.lock.Unlock()

	var errs []error

	peers := pl.pr.RemoveAll()
	for _, p := range peers {
		if err := pl.agent.ReleasePeer(p, pl); err != nil {
			errs = append(errs, err)
		}
	}

	return yerrors.MultiError(errs)
}

// Remove a peer identifier from the round robin
func (pl *RoundRobin) Remove(pid transport.PeerIdentifier) error {
	pl.lock.Lock()
	defer pl.lock.Unlock()

	if err := pl.pr.Remove(pid); err != nil {
		// The peer has already been removed
		return err
	}

	return pl.agent.ReleasePeer(pid, pl)
}

// ChoosePeer selects the next available peer in the round robin
func (pl *RoundRobin) ChoosePeer(ctx context.Context, req *transport.Request) (transport.Peer, error) {
	if !pl.started.Load() {
		return nil, errors.ErrPeerListNotStarted("RoundRobinList")
	}

	for {
		if nextPeer := pl.nextPeer(); nextPeer != nil {
			pl.notifyPeerAvailable()
			return nextPeer, nil
		}

		if err := pl.waitForPeerAddedEvent(ctx); err != nil {
			return nil, err
		}
	}
}

// nextPeer grabs the next available peer from the PeerRing and returns it,
// if there are no available peers it returns nil
func (pl *RoundRobin) nextPeer() transport.Peer {
	pl.lock.Lock()
	peer := pl.pr.Next()
	pl.lock.Unlock()
	return peer
}

// notifyPeerAvailable writes to a channel indicating that a Peer is currently
// available for requests
func (pl *RoundRobin) notifyPeerAvailable() {
	select {
	case pl.peerAvailableEvent <- struct{}{}:
	default:
	}
}

// waitForPeerAddedEvent waits until a peer is added to the peer list or the
// given context finishes.
// Must NOT be run in a mutex.Lock()
func (pl *RoundRobin) waitForPeerAddedEvent(ctx context.Context) error {
	if _, ok := ctx.Deadline(); !ok {
		return errors.ErrChooseContextHasNoDeadline("RoundRobinList")
	}

	select {
	case <-pl.peerAvailableEvent:
		return nil
	case <-ctx.Done():
		return ctx.Err()
	}
}

// NotifyStatusChanged when the peer's status changes
func (pl *RoundRobin) NotifyStatusChanged(transport.Peer) {}


@@ -17,9 +17,13 @@ limitations under the License.
 package cainjector

 import (
+	"context"
+	"fmt"
 	"io/ioutil"

 	logf "github.com/jetstack/cert-manager/pkg/logs"
+	"github.com/pkg/errors"
+	"golang.org/x/sync/errgroup"

 	admissionreg "k8s.io/api/admissionregistration/v1beta1"
 	apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"

/*
Copyright 2019 The Jetstack cert-manager contributors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package cainjector

import (
	"io/ioutil"

	logf "github.com/jetstack/cert-manager/pkg/logs"

	admissionreg "k8s.io/api/admissionregistration/v1beta1"
	apiext "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime"
	apireg "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
	ctrl "sigs.k8s.io/controller-runtime"
)

// injectorSet describes a particular setup of the injector controller
type injectorSetup struct {
	resourceName string
	injector     CertInjector
	listType     runtime.Object
}

var (
	MutatingWebhookSetup = injectorSetup{
		resourceName: "mutatingwebhookconfiguration",
		injector:     mutatingWebhookInjector{},
		listType:     &admissionreg.MutatingWebhookConfigurationList{},
	}

	ValidatingWebhookSetup = injectorSetup{
		resourceName: "validatingwebhookconfiguration",
		injector:     validatingWebhookInjector{},
		listType:     &admissionreg.ValidatingWebhookConfigurationList{},
	}

	APIServiceSetup = injectorSetup{
		resourceName: "apiservice",
		injector:     apiServiceInjector{},
		listType:     &apireg.APIServiceList{},
	}

	CRDSetup = injectorSetup{
		resourceName: "customresourcedefinition",
		injector:     crdConversionInjector{},
		listType:     &apiext.CustomResourceDefinitionList{},
	}

	injectorSetups  = []injectorSetup{MutatingWebhookSetup, ValidatingWebhookSetup, APIServiceSetup, CRDSetup}
	ControllerNames []string
)

// registerAllInjectors registers all injectors and based on the
// graduation state of the injector decides how to log no kind/resource match errors
func registerAllInjectors(mgr ctrl.Manager, sources ...caDataSource) error {
	for _, setup := range injectorSetups {
		if err := Register(mgr, setup, sources...); err != nil {
			if !meta.IsNoMatchError(err) || !setup.injector.IsAlpha() {
				return err
			}
			ctrl.Log.V(logf.WarnLevel).Info("unable to register injector which is still in an alpha phase."+
				" Enable the feature on the API server in order to use this injector",
				"injector", setup.resourceName)
		}
	}
	return nil
}

// Register registers an injection controller with the given manager, and adds relevant indicies.
func Register(mgr ctrl.Manager, setup injectorSetup, sources ...caDataSource) error {
	typ := setup.injector.NewTarget().AsObject()
	builder := ctrl.NewControllerManagedBy(mgr).For(typ)
	for _, s := range sources {
		if err := s.ApplyTo(mgr, setup, builder); err != nil {
			return err
		}
	}

	return builder.Complete(&genericInjectReconciler{
		Client:       mgr.GetClient(),
		sources:      sources,
		log:          ctrl.Log.WithName("inject-controller"),
		resourceName: setup.resourceName,
		injector:     setup.injector,
	})
}

// dataFromSliceOrFile returns data from the slice (if non-empty), or from the file,
// or an error if an error occurred reading the file
func dataFromSliceOrFile(data []byte, file string) ([]byte, error) {
	if len(data) > 0 {
		return data, nil
	}
	if len(file) > 0 {
		fileData, err := ioutil.ReadFile(file)
		if err != nil {
			return []byte{}, err
		}
		return fileData, nil
	}
	return nil, nil
}

// RegisterCertificateBased registers all known injection controllers that
// target Certificate resources with the  given manager, and adds relevant
// indices.
// The registered controllers require the cert-manager API to be available
// in order to run.
func RegisterCertificateBased(mgr ctrl.Manager) error {
	sources := []caDataSource{
		&certificateDataSource{client: mgr.GetClient()},
	}
	return registerAllInjectors(mgr, sources...)
}

// RegisterSecretBased registers all known injection controllers that
// target Secret resources with the  given manager, and adds relevant
// indices.
// The registered controllers only require the corev1 APi to be available in
// order to run.
func RegisterSecretBased(mgr ctrl.Manager) error {
	sources := []caDataSource{
		&secretDataSource{client: mgr.GetClient()},
		&kubeconfigDataSource{},
	}
	return registerAllInjectors(mgr, sources...)
}


@@ -8,7 +8,8 @@ var (
 	newlineTabRE           = regexp.MustCompile(`\n\t`)
 	certificateTimeErrorRE = regexp.MustCompile(`: current time \S+ is after \S+`)
 	// aws
-	awsRequestIDRE = regexp.MustCompile(`(, )*(?i)(request id: )(?:[-[:xdigit:]]+)`)
+	awsRequestIDRE   = regexp.MustCompile(`(, )*(?i)(request id: )(?:[-[:xdigit:]]+)`)
+	awsNotAuthorized = regexp.MustCompile(`(User: arn:aws:sts::)\S+(:assumed-role/[^/]+/)\S+( is not authorized to perform: \S+ on resource: arn:aws:iam::)[^:]+(:\S+)`)
 	// azure
 	azureErrorDescriptionRE = regexp.MustCompile(`\"error_description\":\"(.*?)\\r\\n`)
 )

package utils

import (
	"regexp"
)

var (
	newlineTabRE           = regexp.MustCompile(`\n\t`)
	certificateTimeErrorRE = regexp.MustCompile(`: current time \S+ is after \S+`)
	// aws
	awsRequestIDRE = regexp.MustCompile(`(, )*(?i)(request id: )(?:[-[:xdigit:]]+)`)
	// azure
	azureErrorDescriptionRE = regexp.MustCompile(`\"error_description\":\"(.*?)\\r\\n`)
)

// ErrorScrub scrubs cloud error messages destined for CRD status to remove things that
// change every attempt, such as request IDs, which subsequently cause an infinite update/reconcile loop.
func ErrorScrub(err error) string {
	if err == nil {
		return ""
	}
	s := newlineTabRE.ReplaceAllString(err.Error(), ", ")
	s = awsRequestIDRE.ReplaceAllString(s, "")
	s = certificateTimeErrorRE.ReplaceAllString(s, "")
	// if Azure error, return just the error description
	match := azureErrorDescriptionRE.FindStringSubmatch(s)
	if len(match) > 0 {
		return match[1]
	}
	return s
}


@@ -24,11 +24,14 @@ import (
 	intv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1"
 	bcreconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/brokercell"
 	"github.com/google/knative-gcp/pkg/reconciler"
+	"github.com/google/knative-gcp/pkg/reconciler/brokercell/testingdata"
 	. "github.com/google/knative-gcp/pkg/reconciler/testing"
+	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/client-go/kubernetes/scheme"
 	clientgotesting "k8s.io/client-go/testing"
+	fakekubeclient "knative.dev/pkg/client/injection/kube/client/fake"
 	"knative.dev/pkg/configmap"
 	"knative.dev/pkg/controller"
 	logtesting "knative.dev/pkg/logging/testing"

/*
Copyright 2020 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package brokercell

import (
	"context"
	"fmt"
	"testing"

	intv1alpha1 "github.com/google/knative-gcp/pkg/apis/intevents/v1alpha1"
	bcreconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/intevents/v1alpha1/brokercell"
	"github.com/google/knative-gcp/pkg/reconciler"
	. "github.com/google/knative-gcp/pkg/reconciler/testing"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/client-go/kubernetes/scheme"
	clientgotesting "k8s.io/client-go/testing"
	"knative.dev/pkg/configmap"
	"knative.dev/pkg/controller"
	logtesting "knative.dev/pkg/logging/testing"
	. "knative.dev/pkg/reconciler/testing"
)

const (
	testNS         = "testnamespace"
	brokerCellName = "test-brokercell"

	brokerCellFinalizerName = "brokercells.internal.events.cloud.google.com"
)

var (
	testKey = fmt.Sprintf("%s/%s", testNS, brokerCellName)

	brokerCellFinalizerUpdatedEvent = Eventf(corev1.EventTypeNormal, "FinalizerUpdate", `Updated "test-brokercell" finalizers`)
	brokerCellReconciledEvent       = Eventf(corev1.EventTypeNormal, "BrokerCellReconciled", `BrokerCell reconciled: "testnamespace/test-brokercell"`)
	brokerCellFinalizedEvent        = Eventf(corev1.EventTypeNormal, "BrokerCellFinalized", `BrokerCell finalized: "testnamespace/test-brokercell"`)
)

func init() {
	// Add types to scheme
	_ = intv1alpha1.AddToScheme(scheme.Scheme)
}

func TestAllCases(t *testing.T) {
	table := TableTest{{
		Name: "bad workqueue key",
		Key:  "too/many/parts",
	}, {
		Name: "key not found",
		Key:  testKey,
	}, {
		Name: "BrokerCell is being deleted",
		Key:  testKey,
		Objects: []runtime.Object{
			NewBrokerCell(brokerCellName, testNS,
				WithInitBrokerCellConditions,
				WithBrokerCellDeletionTimestamp),
		},
		WantEvents: []string{
			brokerCellFinalizedEvent,
		},
	}, {
		Name: "BrokerCell created",
		Key:  testKey,
		Objects: []runtime.Object{
			NewBrokerCell(brokerCellName, testNS),
		},
		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
			Object: NewBrokerCell(brokerCellName, testNS,
				WithInitBrokerCellConditions,
			),
		}},
		WantEvents: []string{
			brokerCellFinalizerUpdatedEvent,
			brokerCellReconciledEvent,
		},
		WantPatches: []clientgotesting.PatchActionImpl{
			patchFinalizers(testNS, brokerCellName, brokerCellFinalizerName),
		},
	}}

	defer logtesting.ClearAll()
	table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher, testData map[string]interface{}) controller.Reconciler {
		r := &Reconciler{
			Base: reconciler.NewBase(ctx, controllerAgentName, cmw),
		}
		return bcreconciler.NewReconciler(ctx, r.Logger, r.RunClientSet, listers.GetBrokerCellLister(), r.Recorder, r)
	}))
}

func patchFinalizers(namespace, name, finalizer string) clientgotesting.PatchActionImpl {
	action := clientgotesting.PatchActionImpl{}
	action.Name = name
	action.Namespace = namespace
	patch := `{"metadata":{"finalizers":["` + finalizer + `"],"resourceVersion":""}}`
	action.Patch = []byte(patch)
	return action
}

func patchRemoveFinalizers(namespace, name string) clientgotesting.PatchActionImpl {
	action := clientgotesting.PatchActionImpl{}
	action.Name = name
	action.Namespace = namespace
	patch := `{"metadata":{"finalizers":[],"resourceVersion":""}}`
	action.Patch = []byte(patch)
	return action
}


@@ -104,7 +104,7 @@ func EncodeSimulatedMessage(msg Message, timestamp, blockNumber *big.Int, execut
 	tx := ovmTransaction{
 		timestamp,
 		blockNumber,
-		uint8(msg.QueueOrigin().Uint64()),
+		uint8(msg.QueueOrigin()),
 		*msg.L1MessageSender(),
 		*to,
 		big.NewInt(int64(msg.Gas())),

package core

import (
	"fmt"
	"math/big"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/core/vm"
	"github.com/ethereum/go-ethereum/rollup/dump"
)

var ZeroAddress = common.HexToAddress("0x0000000000000000000000000000000000000000")

type ovmTransaction struct {
	Timestamp     *big.Int       `json:"timestamp"`
	BlockNumber   *big.Int       `json:"blockNumber"`
	L1QueueOrigin uint8          `json:"l1QueueOrigin"`
	L1TxOrigin    common.Address `json:"l1TxOrigin"`
	Entrypoint    common.Address `json:"entrypoint"`
	GasLimit      *big.Int       `json:"gasLimit"`
	Data          []uint8        `json:"data"`
}

func toExecutionManagerRun(evm *vm.EVM, msg Message) (Message, error) {
	tx := ovmTransaction{
		evm.Context.Time,
		msg.L1BlockNumber(),
		uint8(msg.QueueOrigin().Uint64()),
		*msg.L1MessageSender(),
		*msg.To(),
		big.NewInt(int64(msg.Gas())),
		msg.Data(),
	}

	var abi = evm.Context.OvmExecutionManager.ABI
	var args = []interface{}{
		tx,
		evm.Context.OvmStateManager.Address,
	}

	ret, err := abi.Pack("run", args...)
	if err != nil {
		return nil, err
	}

	outputmsg, err := modMessage(
		msg,
		msg.From(),
		&evm.Context.OvmExecutionManager.Address,
		ret,
		evm.Context.GasLimit,
	)
	if err != nil {
		return nil, err
	}

	return outputmsg, nil
}

func AsOvmMessage(tx *types.Transaction, signer types.Signer, decompressor common.Address, gasLimit uint64) (Message, error) {
	msg, err := tx.AsMessage(signer)
	if err != nil {
		// This should only be allowed to pass if the transaction is in the ctc
		// already. The presence of `Index` should specify this.
		index := tx.GetMeta().Index
		if index == nil {
			return msg, fmt.Errorf("Cannot convert tx to message in asOvmMessage: %w", err)
		}
	}

	// Queue origin L1ToL2 transactions do not go through the
	// sequencer entrypoint. The calldata is expected to be in the
	// correct format when deserialized from the EVM events, see
	// rollup/sync_service.go.
	qo := msg.QueueOrigin()
	if qo != nil && qo.Uint64() == uint64(types.QueueOriginL1ToL2) {
		return msg, nil
	}

	// Sequencer transactions get sent to the "sequencer entrypoint," a contract that decompresses
	// the incoming transaction data.
	outmsg, err := modMessage(
		msg,
		msg.From(),
		&decompressor,
		tx.GetMeta().RawTransaction,
		gasLimit,
	)

	if err != nil {
		return msg, fmt.Errorf("Cannot mod message: %w", err)
	}

	return outmsg, nil
}

func EncodeSimulatedMessage(msg Message, timestamp, blockNumber *big.Int, executionManager, stateManager dump.OvmDumpAccount) (Message, error) {
	to := msg.To()
	if to == nil {
		to = &common.Address{0}
	}

	tx := ovmTransaction{
		timestamp,
		blockNumber,
		uint8(msg.QueueOrigin().Uint64()),
		*msg.L1MessageSender(),
		*to,
		big.NewInt(int64(msg.Gas())),
		msg.Data(),
	}

	from := msg.From()
	var args = []interface{}{
		tx,
		from,
		stateManager.Address,
	}

	output, err := executionManager.ABI.Pack("simulateMessage", args...)
	if err != nil {
		return nil, fmt.Errorf("Cannot pack simulateMessage: %w", err)
	}

	return modMessage(
		msg,
		common.Address{},
		&executionManager.Address,
		output,
		msg.Gas(),
	)
}

func modMessage(
	msg Message,
	from common.Address,
	to *common.Address,
	data []byte,
	gasLimit uint64,
) (Message, error) {
	queueOrigin, err := getQueueOrigin(msg.QueueOrigin())
	if err != nil {
		return nil, err
	}

	outmsg := types.NewMessage(
		from,
		to,
		msg.Nonce(),
		common.Big0,
		gasLimit,
		msg.GasPrice(),
		data,
		false,
		msg.L1MessageSender(),
		msg.L1BlockNumber(),
		queueOrigin,
		msg.SignatureHashType(),
	)

	return outmsg, nil
}

func getQueueOrigin(
	queueOrigin *big.Int,
) (types.QueueOrigin, error) {
	if queueOrigin.Cmp(big.NewInt(0)) == 0 {
		return types.QueueOriginSequencer, nil
	} else if queueOrigin.Cmp(big.NewInt(1)) == 0 {
		return types.QueueOriginL1ToL2, nil
	} else if queueOrigin.Cmp(big.NewInt(2)) == 0 {
		return types.QueueOriginL1ToL2, nil
	} else {
		return types.QueueOriginSequencer, fmt.Errorf("invalid queue origin: %d", queueOrigin)
	}
}


@@ -97,7 +97,7 @@ func (a *GCPActuator) getZones(region string) ([]string, error) {
 	pageToken := ""

 	for {
-		zoneList, err := a.client.ListComputeZones(gcpclient.ListComputeZonesOptions{
+		zoneList, err := a.gcpClient.ListComputeZones(gcpclient.ListComputeZonesOptions{
 			Filter:    zoneFilter,
 			PageToken: pageToken,
 		})

package remotemachineset

import (
	"fmt"

	"github.com/pkg/errors"
	log "github.com/sirupsen/logrus"

	machineapi "github.com/openshift/cluster-api/pkg/apis/machine/v1beta1"
	corev1 "k8s.io/api/core/v1"

	installgcp "github.com/openshift/installer/pkg/asset/machines/gcp"
	installertypes "github.com/openshift/installer/pkg/types"
	installertypesgcp "github.com/openshift/installer/pkg/types/gcp"

	hivev1 "github.com/openshift/hive/pkg/apis/hive/v1"
	"github.com/openshift/hive/pkg/gcpclient"
)

// GCPActuator encapsulates the pieces necessary to be able to generate
// a list of MachineSets to sync to the remote cluster.
type GCPActuator struct {
	client gcpclient.Client
	logger log.FieldLogger
}

var _ Actuator = &GCPActuator{}

// NewGCPActuator is the constructor for building a GCPActuator
func NewGCPActuator(gcpCreds *corev1.Secret, logger log.FieldLogger) (*GCPActuator, error) {
	gcpClient, err := gcpclient.NewClientFromSecret(gcpCreds)
	if err != nil {
		logger.WithError(err).Warn("failed to create GCP client with creds in clusterDeployment's secret")
		return nil, err
	}
	actuator := &GCPActuator{
		client: gcpClient,
		logger: logger,
	}
	return actuator, nil
}

// GenerateMachineSets satisfies the Actuator interface and will take a clusterDeployment and return a list of MachineSets
// to sync to the remote cluster.
func (a *GCPActuator) GenerateMachineSets(cd *hivev1.ClusterDeployment, pool *hivev1.MachinePool, logger log.FieldLogger) ([]*machineapi.MachineSet, error) {
	if cd.Spec.ClusterMetadata == nil {
		return nil, errors.New("ClusterDeployment does not have cluster metadata")
	}
	if cd.Spec.Platform.GCP == nil {
		return nil, errors.New("ClusterDeployment is not for GCP")
	}
	if pool.Spec.Platform.GCP == nil {
		return nil, errors.New("MachinePool is not for GCP")
	}

	ic := &installertypes.InstallConfig{
		Platform: installertypes.Platform{
			GCP: &installertypesgcp.Platform{
				Region: cd.Spec.Platform.GCP.Region,
			},
		},
	}

	computePool := baseMachinePool(pool)
	computePool.Platform.GCP = &installertypesgcp.MachinePool{
		Zones:        pool.Spec.Platform.GCP.Zones,
		InstanceType: pool.Spec.Platform.GCP.InstanceType,
	}

	// get image ID for the generated machine sets
	imageID, err := a.getImageID(cd, logger)
	if err != nil {
		return nil, errors.Wrap(err, "failed to find image ID for the machine sets")
	}

	if len(computePool.Platform.GCP.Zones) == 0 {
		zones, err := a.getZones(cd.Spec.Platform.GCP.Region)
		if err != nil {
			return nil, errors.Wrap(err, "compute pool not providing list of zones and failed to fetch list of zones")
		}
		if len(zones) == 0 {
			return nil, fmt.Errorf("zero zones returned for region %s", cd.Spec.Platform.GCP.Region)
		}
		computePool.Platform.GCP.Zones = zones
	}

	installerMachineSets, err := installgcp.MachineSets(cd.Spec.ClusterMetadata.InfraID, ic, computePool, imageID, pool.Spec.Name, "worker-user-data")
	return installerMachineSets, errors.Wrap(err, "failed to generate machinesets")
}

func (a *GCPActuator) getZones(region string) ([]string, error) {
	zones := []string{}

	// Filter to regions matching '.*<region>.*' (where the zone is actually UP)
	zoneFilter := fmt.Sprintf("(region eq '.*%s.*') (status eq UP)", region)

	pageToken := ""

	for {
		zoneList, err := a.client.ListComputeZones(gcpclient.ListComputeZonesOptions{
			Filter:    zoneFilter,
			PageToken: pageToken,
		})
		if err != nil {
			return zones, err
		}

		for _, zone := range zoneList.Items {
			zones = append(zones, zone.Name)
		}

		if zoneList.NextPageToken == "" {
			break
		}
		pageToken = zoneList.NextPageToken
	}

	return zones, nil
}

func (a *GCPActuator) getImageID(cd *hivev1.ClusterDeployment, logger log.FieldLogger) (string, error) {
	infra := cd.Spec.ClusterMetadata.InfraID

	// find names of the form '<infra>-.*'
	filter := fmt.Sprintf("name eq \"%s-.*\"", infra)
	result, err := a.client.ListComputeImages(gcpclient.ListComputeImagesOptions{Filter: filter})
	if err != nil {
		logger.WithError(err).Warnf("failed to find a GCP image starting with name: %s", infra)
		return "", err
	}
	switch len(result.Items) {
	case 0:
		msg := fmt.Sprintf("found 0 results searching for GCP image starting with name: %s", infra)
		logger.Warnf(msg)
		return "", errors.New(msg)
	case 1:
		logger.Debugf("using image with name %s for machine sets", result.Items[0].Name)
		return result.Items[0].Name, nil
	default:
		msg := fmt.Sprintf("unexpected number of results when looking for GCP image with name starting with %s", infra)
		logger.Warnf(msg)
		return "", errors.New(msg)
	}
}


@@ -94,5 +94,5 @@ func (f *Factory) FromRole(roleARN string, region string) (*session.Session, err
 		return nil, err
 	}
 	sess.Handlers.Build.PushBackNamed(userAgentHandler())
-	return sess, err
+	return sess, nil
 }

// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

// Package session provides functions that return AWS sessions to use in the AWS SDK.
package session

import (
	"fmt"
	"runtime"

	"github.com/aws/amazon-ecs-cli-v2/internal/pkg/version"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
	"github.com/aws/aws-sdk-go/aws/request"
	"github.com/aws/aws-sdk-go/aws/session"
)

const userAgentHeader = "User-Agent"

// userAgentHandler returns a http request handler that sets a custom user agent to all aws requests.
func userAgentHandler() request.NamedHandler {
	return request.NamedHandler{
		Name: "UserAgentHandler",
		Fn: func(r *request.Request) {
			userAgent := r.HTTPRequest.Header.Get(userAgentHeader)
			r.HTTPRequest.Header.Set(userAgentHeader,
				fmt.Sprintf("aws-ecs-cli-v2/%s (%s) %s", version.Version, runtime.GOOS, userAgent))
		},
	}
}

// Factory holds methods to create sessions.
type Factory struct{}

// Default returns a session configured against the "default" AWS profile.
func (f *Factory) Default() (*session.Session, error) {
	sess, err := session.NewSessionWithOptions(session.Options{
		Config: aws.Config{
			CredentialsChainVerboseErrors: aws.Bool(true),
		},
		SharedConfigState: session.SharedConfigEnable,
	})
	if err != nil {
		return nil, err
	}
	sess.Handlers.Build.PushBackNamed(userAgentHandler())
	return sess, err
}

// DefaultWithRegion returns a session configured against the "default" AWS profile and the input region.
func (f *Factory) DefaultWithRegion(region string) (*session.Session, error) {
	sess, err := session.NewSession(&aws.Config{
		Region: aws.String(region),
	})
	if err != nil {
		return nil, err
	}
	sess.Handlers.Build.PushBackNamed(userAgentHandler())
	return sess, err
}

// FromProfile returns a session configured against the input profile name.
func (f *Factory) FromProfile(name string) (*session.Session, error) {
	sess, err := session.NewSessionWithOptions(session.Options{
		Config: aws.Config{
			CredentialsChainVerboseErrors: aws.Bool(true),
		},
		SharedConfigState: session.SharedConfigEnable,
		Profile:           name,
	})
	if err != nil {
		return nil, err
	}
	sess.Handlers.Build.PushBackNamed(userAgentHandler())
	return sess, err
}

// FromRole returns a session configured against the input role and region.
func (f *Factory) FromRole(roleARN string, region string) (*session.Session, error) {
	defaultSession, err := f.Default()

	if err != nil {
		return nil, fmt.Errorf("error creating default session: %w", err)
	}

	creds := stscreds.NewCredentials(defaultSession, roleARN)
	sess, err := session.NewSession(&aws.Config{
		CredentialsChainVerboseErrors: aws.Bool(true),
		Credentials:                   creds,
		Region:                        &region,
	})
	if err != nil {
		return nil, err
	}
	sess.Handlers.Build.PushBackNamed(userAgentHandler())
	return sess, err
}


@@ -45,6 +45,7 @@ import (
 	triggerinformer "github.com/google/knative-gcp/pkg/client/injection/informers/broker/v1beta1/trigger"
 	triggerreconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/broker/v1beta1/trigger"
 	"github.com/google/knative-gcp/pkg/reconciler"
+	reconcilerutils "github.com/google/knative-gcp/pkg/reconciler/utils"
 	"github.com/google/knative-gcp/pkg/utils"
 )

/*
Copyright 2020 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package trigger

import (
	"context"

	"github.com/google/knative-gcp/pkg/reconciler/celltenant"

	"cloud.google.com/go/pubsub"
	"go.uber.org/zap"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/client-go/tools/cache"

	"github.com/google/knative-gcp/pkg/logging"
	"knative.dev/eventing/pkg/apis/eventing"
	eventingv1beta1 "knative.dev/eventing/pkg/apis/eventing/v1beta1"
	"knative.dev/eventing/pkg/duck"
	"knative.dev/pkg/client/injection/ducks/duck/v1/addressable"
	"knative.dev/pkg/client/injection/ducks/duck/v1/source"
	"knative.dev/pkg/configmap"
	"knative.dev/pkg/controller"
	pkgcontroller "knative.dev/pkg/controller"
	"knative.dev/pkg/injection"
	pkgreconciler "knative.dev/pkg/reconciler"
	"knative.dev/pkg/resolver"

	brokerv1beta1 "github.com/google/knative-gcp/pkg/apis/broker/v1beta1"
	"github.com/google/knative-gcp/pkg/apis/configs/dataresidency"
	brokerinformer "github.com/google/knative-gcp/pkg/client/injection/informers/broker/v1beta1/broker"
	triggerinformer "github.com/google/knative-gcp/pkg/client/injection/informers/broker/v1beta1/trigger"
	triggerreconciler "github.com/google/knative-gcp/pkg/client/injection/reconciler/broker/v1beta1/trigger"
	"github.com/google/knative-gcp/pkg/reconciler"
	"github.com/google/knative-gcp/pkg/utils"
)

const (
	// controllerAgentName is the string used by this controller to identify
	// itself when creating events.
	controllerAgentName = "trigger-controller"
	// finalizerName is the name of the finalizer that this controller adds to the Triggers that it reconciles.
	finalizerName = "googlecloud"
)

// filterBroker is the function to filter brokers with proper brokerclass.
var filterBroker = pkgreconciler.AnnotationFilterFunc(eventingv1beta1.BrokerClassAnnotationKey, brokerv1beta1.BrokerClass, false /*allowUnset*/)

type Constructor injection.ControllerConstructor

// NewConstructor creates a constructor to make a Trigger controller.
func NewConstructor(dataresidencyss *dataresidency.StoreSingleton) Constructor {
	return func(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
		return newController(ctx, cmw, dataresidencyss.Store(ctx, cmw))
	}
}

func newController(ctx context.Context, cmw configmap.Watcher, drs *dataresidency.Store) *controller.Impl {
	triggerInformer := triggerinformer.Get(ctx)

	var client *pubsub.Client
	// If there is an error, the projectID will be empty. The reconciler will retry
	// to get the projectID during reconciliation.
	projectID, err := utils.ProjectIDOrDefault("")
	if err != nil {
		logging.FromContext(ctx).Error("Failed to get project ID", zap.Error(err))
	} else {
		// Attempt to create a pubsub client for all worker threads to use. If this
		// fails, pass a nil value to the Reconciler. They will attempt to
		// create a client on reconcile.
		if client, err = pubsub.NewClient(ctx, projectID); err != nil {
			client = nil
			logging.FromContext(ctx).Error("Failed to create controller-wide Pub/Sub client", zap.Error(err))
		}
	}

	if client != nil {
		go func() {
			<-ctx.Done()
			client.Close()
		}()
	}
	r := &Reconciler{
		Base:         reconciler.NewBase(ctx, controllerAgentName, cmw),
		brokerLister: brokerinformer.Get(ctx).Lister(),
		targetReconciler: &celltenant.TargetReconciler{
			ProjectID:          projectID,
			PubsubClient:       client,
			DataresidencyStore: drs,
		},
	}

	impl := triggerreconciler.NewImpl(ctx, r, withAgentAndFinalizer)
	r.sourceTracker = duck.NewListableTracker(ctx, source.Get, impl.EnqueueKey, controller.GetTrackerLease(ctx))
	r.addressableTracker = duck.NewListableTracker(ctx, addressable.Get, impl.EnqueueKey, controller.GetTrackerLease(ctx))
	r.uriResolver = resolver.NewURIResolver(ctx, impl.EnqueueKey)

	r.Logger.Info("Setting up event handlers")

	triggerInformer.Informer().AddEventHandlerWithResyncPeriod(controller.HandleAll(impl.Enqueue), reconciler.DefaultResyncPeriod)

	// Watch brokers.
	brokerinformer.Get(ctx).Informer().AddEventHandler(
		cache.FilteringResourceEventHandler{
			// Only care about brokers with the proper class annotation
			FilterFunc: filterBroker,
			Handler: controller.HandleAll(func(obj interface{}) {
				if b, ok := obj.(*brokerv1beta1.Broker); ok {
					triggers, err := triggerinformer.Get(ctx).Lister().Triggers(b.Namespace).List(labels.SelectorFromSet(map[string]string{eventing.BrokerLabelKey: b.Name}))
					if err != nil {
						r.Logger.Warn("Failed to list triggers", zap.String("Namespace", b.Namespace), zap.String("Broker", b.Name))
						return
					}
					for _, trigger := range triggers {
						impl.Enqueue(trigger)
					}
				}
			}),
		},
	)

	return impl
}

func withAgentAndFinalizer(_ *pkgcontroller.Impl) pkgcontroller.Options {
	return pkgcontroller.Options{
		FinalizerName: finalizerName,
		AgentName:     controllerAgentName,
	}
}


@@ -6,7 +6,8 @@ import (
 	"fmt"
 	"html"
 	"net/http"
-	"strings"
+	"net/url"
+	"regexp"

 	"github.com/mholt/caddy/middleware"
 )

// Package redirect is middleware for redirecting certain requests
// to other locations.
package redirect

import (
	"fmt"
	"html"
	"net/http"
	"strings"

	"github.com/mholt/caddy/middleware"
)

// Redirect is middleware to respond with HTTP redirects
type Redirect struct {
	Next  middleware.Handler
	Rules []Rule
}

// ServeHTTP implements the middleware.Handler interface.
func (rd Redirect) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
	for _, rule := range rd.Rules {
		if rule.From == "/" {
			// Catchall redirect preserves path (TODO: Standardize/formalize this behavior)
			newPath := strings.TrimSuffix(rule.To, "/") + r.URL.Path
			if rule.Meta {
				fmt.Fprintf(w, metaRedir, html.EscapeString(newPath))
			} else {
				http.Redirect(w, r, newPath, rule.Code)
			}
			return 0, nil
		}
		if r.URL.Path == rule.From {
			if rule.Meta {
				fmt.Fprintf(w, metaRedir, html.EscapeString(rule.To))
			} else {
				http.Redirect(w, r, rule.To, rule.Code)
			}
			return 0, nil
		}
	}
	return rd.Next.ServeHTTP(w, r)
}

// Rule describes an HTTP redirect rule.
type Rule struct {
	From, To string
	Code     int
	Meta     bool
}

var metaRedir = `<html>
<head>
  <meta http-equiv="refresh" content="0;URL='%s'">
</head>
<body>redirecting...</body>
</html>`


@@ -173,8 +173,3 @@ func (o *ocDistAggregator) Count() (uint64, error) {
 func (o *ocDistAggregator) Histogram() (aggregation.Buckets, error) {
 	return o.buckets, nil
 }
-
-// end returns the time the histogram was measured.
-func (o *ocDistAggregator) end() time.Time {
-	return o.endTime
-}

// Copyright The OpenTelemetry Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package opencensus // import "go.opentelemetry.io/otel/bridge/opencensus"

import (
	"errors"
	"fmt"
	"time"

	"go.opencensus.io/metric/metricdata"

	"go.opentelemetry.io/otel/metric/number"
	"go.opentelemetry.io/otel/sdk/export/metric/aggregation"
)

var (
	errIncompatibleType = errors.New("incompatible type for aggregation")
	errEmpty            = errors.New("points may not be empty")
	errBadPoint         = errors.New("point cannot be converted")
)

// aggregationWithEndTime is an aggregation that can also provide the timestamp
// of the last recorded point.
type aggregationWithEndTime interface {
	aggregation.Aggregation
	end() time.Time
}

// newAggregationFromPoints creates an OpenTelemetry aggregation from
// OpenCensus points.  Points may not be empty and must be either
// all (int|float)64 or all *metricdata.Distribution.
func newAggregationFromPoints(points []metricdata.Point) (aggregationWithEndTime, error) {
	if len(points) == 0 {
		return nil, errEmpty
	}
	switch t := points[0].Value.(type) {
	case int64:
		return newExactAggregator(points)
	case float64:
		return newExactAggregator(points)
	case *metricdata.Distribution:
		return newDistributionAggregator(points)
	default:
		// TODO add *metricdata.Summary support
		return nil, fmt.Errorf("%w: %v", errIncompatibleType, t)
	}
}

var _ aggregation.Aggregation = &ocExactAggregator{}
var _ aggregation.LastValue = &ocExactAggregator{}
var _ aggregation.Points = &ocExactAggregator{}

// newExactAggregator creates an OpenTelemetry aggreation from OpenCensus points.
// Points may not be empty, and must only contain integers or floats.
func newExactAggregator(pts []metricdata.Point) (aggregationWithEndTime, error) {
	points := make([]aggregation.Point, len(pts))
	for i, pt := range pts {
		switch t := pt.Value.(type) {
		case int64:
			points[i] = aggregation.Point{
				Number: number.NewInt64Number(pt.Value.(int64)),
				Time:   pt.Time,
			}
		case float64:
			points[i] = aggregation.Point{
				Number: number.NewFloat64Number(pt.Value.(float64)),
				Time:   pt.Time,
			}
		default:
			return nil, fmt.Errorf("%w: %v", errIncompatibleType, t)
		}
	}
	return &ocExactAggregator{
		points: points,
	}, nil
}

type ocExactAggregator struct {
	points []aggregation.Point
}

// Kind returns the kind of aggregation this is.
func (o *ocExactAggregator) Kind() aggregation.Kind {
	return aggregation.ExactKind
}

// Points returns access to the raw data set.
func (o *ocExactAggregator) Points() ([]aggregation.Point, error) {
	return o.points, nil
}

// LastValue returns the last point.
func (o *ocExactAggregator) LastValue() (number.Number, time.Time, error) {
	last := o.points[len(o.points)-1]
	return last.Number, last.Time, nil
}

// end returns the timestamp of the last point
func (o *ocExactAggregator) end() time.Time {
	_, t, _ := o.LastValue()
	return t
}

var _ aggregation.Aggregation = &ocDistAggregator{}
var _ aggregation.Histogram = &ocDistAggregator{}

// newDistributionAggregator creates an OpenTelemetry aggreation from
// OpenCensus points. Points may not be empty, and must only contain
// Distributions.  The most recent disribution will be used in the aggregation.
func newDistributionAggregator(pts []metricdata.Point) (aggregationWithEndTime, error) {
	// only use the most recent datapoint for now.
	pt := pts[len(pts)-1]
	val, ok := pt.Value.(*metricdata.Distribution)
	if !ok {
		return nil, fmt.Errorf("%w: %v", errBadPoint, pt.Value)
	}
	bucketCounts := make([]uint64, len(val.Buckets))
	for i, bucket := range val.Buckets {
		if bucket.Count < 0 {
			return nil, fmt.Errorf("%w: bucket count may not be negative", errBadPoint)
		}
		bucketCounts[i] = uint64(bucket.Count)
	}
	if val.Count < 0 {
		return nil, fmt.Errorf("%w: count may not be negative", errBadPoint)
	}
	return &ocDistAggregator{
		sum:   number.NewFloat64Number(val.Sum),
		count: uint64(val.Count),
		buckets: aggregation.Buckets{
			Boundaries: val.BucketOptions.Bounds,
			Counts:     bucketCounts,
		},
		endTime: pts[len(pts)-1].Time,
	}, nil
}

type ocDistAggregator struct {
	sum     number.Number
	count   uint64
	buckets aggregation.Buckets
	endTime time.Time
}

// Kind returns the kind of aggregation this is.
func (o *ocDistAggregator) Kind() aggregation.Kind {
	return aggregation.HistogramKind
}

// Sum returns the sum of values.
func (o *ocDistAggregator) Sum() (number.Number, error) {
	return o.sum, nil
}

// Count returns the number of values.
func (o *ocDistAggregator) Count() (uint64, error) {
	return o.count, nil
}

// Histogram returns the count of events in pre-determined buckets.
func (o *ocDistAggregator) Histogram() (aggregation.Buckets, error) {
	return o.buckets, nil
}

// end returns the time the histogram was measured.
func (o *ocDistAggregator) end() time.Time {
	return o.endTime
}


@@ -8,10 +8,12 @@ package staking

 import (
 	"context"
+	"math/big"

 	"github.com/gogo/protobuf/proto"
 	"github.com/pkg/errors"

+	"github.com/iotexproject/iotex-address/address"
 	"github.com/iotexproject/iotex-proto/golang/iotextypes"

 	"github.com/iotexproject/iotex-core/db"

// Copyright (c) 2020 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.

package staking

import (
	"context"

	"github.com/gogo/protobuf/proto"
	"github.com/pkg/errors"

	"github.com/iotexproject/iotex-proto/golang/iotextypes"

	"github.com/iotexproject/iotex-core/db"
	"github.com/iotexproject/iotex-core/pkg/util/byteutil"
)

const (
	// StakingCandidatesNamespace is a namespace to store candidates with epoch start height
	StakingCandidatesNamespace = "stakingCandidates"
	// StakingBucketsNamespace is a namespace to store vote buckets with epoch start height
	StakingBucketsNamespace = "stakingBuckets"
)

const indexerHeightKey = "latestHeight"

// CandidatesBucketsIndexer is an indexer to store candidates by given height
type CandidatesBucketsIndexer struct {
	latestCandidatesHeight uint64
	latestBucketsHeight    uint64
	kvStore                db.KVStore
}

// NewStakingCandidatesBucketsIndexer creates a new StakingCandidatesIndexer
func NewStakingCandidatesBucketsIndexer(kv db.KVStore) (*CandidatesBucketsIndexer, error) {
	if kv == nil {
		return nil, ErrMissingField
	}
	return &CandidatesBucketsIndexer{
		kvStore: kv,
	}, nil
}

// Start starts the indexer
func (cbi *CandidatesBucketsIndexer) Start(ctx context.Context) error {
	if err := cbi.kvStore.Start(ctx); err != nil {
		return err
	}
	ret, err := cbi.kvStore.Get(StakingCandidatesNamespace, []byte(indexerHeightKey))
	switch errors.Cause(err) {
	case nil:
		cbi.latestCandidatesHeight = byteutil.BytesToUint64BigEndian(ret)
	case db.ErrNotExist:
		cbi.latestCandidatesHeight = 0
	default:
		return err
	}

	ret, err = cbi.kvStore.Get(StakingBucketsNamespace, []byte(indexerHeightKey))
	switch errors.Cause(err) {
	case nil:
		cbi.latestBucketsHeight = byteutil.BytesToUint64BigEndian(ret)
	case db.ErrNotExist:
		cbi.latestBucketsHeight = 0
	default:
		return err
	}
	return nil
}

// Stop stops the indexer
func (cbi *CandidatesBucketsIndexer) Stop(ctx context.Context) error {
	return cbi.kvStore.Stop(ctx)
}

// PutCandidates puts candidates into indexer
func (cbi *CandidatesBucketsIndexer) PutCandidates(height uint64, candidates *iotextypes.CandidateListV2) error {
	candidatesBytes, err := proto.Marshal(candidates)
	if err != nil {
		return err
	}
	heightBytes := byteutil.Uint64ToBytesBigEndian(height)
	if err := cbi.kvStore.Put(StakingCandidatesNamespace, heightBytes, candidatesBytes); err != nil {
		return err
	}
	if err := cbi.kvStore.Put(StakingCandidatesNamespace, []byte(indexerHeightKey), heightBytes); err != nil {
		return err
	}
	cbi.latestCandidatesHeight = height
	return nil
}

// GetCandidates gets candidates from indexer given epoch start height
func (cbi *CandidatesBucketsIndexer) GetCandidates(height uint64, offset, limit uint32) ([]byte, uint64, error) {
	if height > cbi.latestCandidatesHeight {
		height = cbi.latestCandidatesHeight
	}
	candidateList := &iotextypes.CandidateListV2{}
	ret, err := cbi.kvStore.Get(StakingCandidatesNamespace, byteutil.Uint64ToBytesBigEndian(height))
	if errors.Cause(err) == db.ErrNotExist {
		d, err := proto.Marshal(candidateList)
		return d, height, err
	}
	if err != nil {
		return nil, height, err
	}
	if err := proto.Unmarshal(ret, candidateList); err != nil {
		return nil, height, err
	}
	length := uint32(len(candidateList.Candidates))
	if offset >= length {
		d, err := proto.Marshal(&iotextypes.CandidateListV2{})
		return d, height, err
	}
	end := offset + limit
	if end > uint32(len(candidateList.Candidates)) {
		end = uint32(len(candidateList.Candidates))
	}
	candidateList.Candidates = candidateList.Candidates[offset:end]
	d, err := proto.Marshal(candidateList)
	return d, height, err
}

// PutBuckets puts vote buckets into indexer
func (cbi *CandidatesBucketsIndexer) PutBuckets(height uint64, buckets *iotextypes.VoteBucketList) error {
	bucketsBytes, err := proto.Marshal(buckets)
	if err != nil {
		return err
	}
	heightBytes := byteutil.Uint64ToBytesBigEndian(height)
	if err := cbi.kvStore.Put(StakingBucketsNamespace, heightBytes, bucketsBytes); err != nil {
		return err
	}
	if err := cbi.kvStore.Put(StakingBucketsNamespace, []byte(indexerHeightKey), heightBytes); err != nil {
		return err
	}
	cbi.latestBucketsHeight = height
	return nil
}

// GetBuckets gets vote buckets from indexer given epoch start height
func (cbi *CandidatesBucketsIndexer) GetBuckets(height uint64, offset, limit uint32) ([]byte, uint64, error) {
	if height > cbi.latestBucketsHeight {
		height = cbi.latestBucketsHeight
	}
	buckets := &iotextypes.VoteBucketList{}
	ret, err := cbi.kvStore.Get(StakingBucketsNamespace, byteutil.Uint64ToBytesBigEndian(height))
	if errors.Cause(err) == db.ErrNotExist {
		d, err := proto.Marshal(buckets)
		return d, height, err
	}
	if err != nil {
		return nil, height, err
	}
	if err := proto.Unmarshal(ret, buckets); err != nil {
		return nil, height, err
	}
	length := uint32(len(buckets.Buckets))
	if offset >= length {
		d, err := proto.Marshal(&iotextypes.VoteBucketList{})
		return d, height, err
	}
	end := offset + limit
	if end > uint32(len(buckets.Buckets)) {
		end = uint32(len(buckets.Buckets))
	}
	buckets.Buckets = buckets.Buckets[offset:end]
	d, err := proto.Marshal(buckets)
	return d, height, err
}


@@ -1,8 +1,9 @@
 package structs

 import (
-	"fmt"
+	"strings"

+	"github.com/pborman/uuid"
 	"github.com/pkg/errors"
 	"github.com/sonm-io/core/proto"
 )

package structs

import (
	"fmt"

	"github.com/pkg/errors"
	"github.com/sonm-io/core/proto"
)

type Network interface {
	// ID returns a unique identifier that will be used as a new network name.
	ID() string
	// NetworkType returns a network driver name used to establish networking.
	NetworkType() string
	// NetworkOptions return configuration map, passed directly to network driver, this map should not be mutated.
	NetworkOptions() map[string]string
	// Returns network subnet in CIDR notation if applicable.
	NetworkCIDR() string
	// Returns specified addr to join the network.
	NetworkAddr() string
}

type NetworkSpec struct {
	*sonm.NetworkSpec
	Id string
}

func (n *NetworkSpec) ID() string {
	return n.Id
}

func (n *NetworkSpec) NetworkType() string {
	return n.GetType()
}

func (n *NetworkSpec) NetworkOptions() map[string]string {
	return n.GetOptions()
}

func (n *NetworkSpec) NetworkCIDR() string {
	return n.GetSubnet()
}

func (n *NetworkSpec) NetworkAddr() string {
	return n.GetAddr()
}

func validateNetworkSpec(id string, spec *sonm.NetworkSpec) error {
	if spec.Type == "tinc" {
		if len(spec.Addr) == 0 || len(spec.Subnet) == 0 {
			return errors.New("address and subnet are required for tinc driver")
		}
	}
	return nil
}

func NewNetworkSpec(id string, spec *sonm.NetworkSpec) (*NetworkSpec, error) {
	err := validateNetworkSpec(id, spec)
	if err != nil {
		return nil, err
	}
	return &NetworkSpec{spec, id}, nil
}

func NewNetworkSpecs(idPrefix string, specs []*sonm.NetworkSpec) ([]Network, error) {
	result := make([]Network, 0, len(specs))
	for i, s := range specs {
		spec, err := NewNetworkSpec(idPrefix+"__"+fmt.Sprint(i), s)
		if err != nil {
			return nil, err
		}
		result = append(result, spec)
	}
	return result, nil
}