cmd/devp2p: use AWS-SDK v2 (#22360)

This updates the DNS deployer to use AWS SDK v2. Migration is relatively
seamless, although there were two locations that required a slightly
different approach to achieve the same results. In particular, waiting for
DNS change propagation is very different with SDK v2. 

This change also optimizes DNS updates by publishing all changes before
waiting for propagation.
This commit is contained in:
Quest Henkart 2021-03-19 06:15:57 -06:00 committed by GitHub
parent d50e9d24be
commit e3a3f7cd64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 153 additions and 87 deletions

@ -17,16 +17,19 @@
package main package main
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go-v2/credentials"
"github.com/aws/aws-sdk-go/service/route53" "github.com/aws/aws-sdk-go-v2/service/route53"
"github.com/aws/aws-sdk-go-v2/service/route53/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/dnsdisc" "github.com/ethereum/go-ethereum/p2p/dnsdisc"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
@ -38,6 +41,7 @@ const (
// https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests-changeresourcerecordsets // https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/DNSLimitations.html#limits-api-requests-changeresourcerecordsets
route53ChangeSizeLimit = 32000 route53ChangeSizeLimit = 32000
route53ChangeCountLimit = 1000 route53ChangeCountLimit = 1000
maxRetryLimit = 60
) )
var ( var (
@ -58,7 +62,7 @@ var (
) )
type route53Client struct { type route53Client struct {
api *route53.Route53 api *route53.Client
zoneID string zoneID string
} }
@ -74,13 +78,13 @@ func newRoute53Client(ctx *cli.Context) *route53Client {
if akey == "" || asec == "" { if akey == "" || asec == "" {
exit(fmt.Errorf("need Route53 Access Key ID and secret proceed")) exit(fmt.Errorf("need Route53 Access Key ID and secret proceed"))
} }
config := &aws.Config{Credentials: credentials.NewStaticCredentials(akey, asec, "")} creds := aws.NewCredentialsCache(credentials.NewStaticCredentialsProvider(akey, asec, ""))
session, err := session.NewSession(config) cfg, err := config.LoadDefaultConfig(context.Background(), config.WithCredentialsProvider(creds))
if err != nil { if err != nil {
exit(fmt.Errorf("can't create AWS session: %v", err)) exit(fmt.Errorf("can't initialize AWS configuration: %v", err))
} }
return &route53Client{ return &route53Client{
api: route53.New(session), api: route53.NewFromConfig(cfg),
zoneID: ctx.String(route53ZoneIDFlag.Name), zoneID: ctx.String(route53ZoneIDFlag.Name),
} }
} }
@ -105,25 +109,43 @@ func (c *route53Client) deploy(name string, t *dnsdisc.Tree) error {
return nil return nil
} }
// Submit change batches. // Submit all change batches.
batches := splitChanges(changes, route53ChangeSizeLimit, route53ChangeCountLimit) batches := splitChanges(changes, route53ChangeSizeLimit, route53ChangeCountLimit)
changesToCheck := make([]*route53.ChangeResourceRecordSetsOutput, len(batches))
for i, changes := range batches { for i, changes := range batches {
log.Info(fmt.Sprintf("Submitting %d changes to Route53", len(changes))) log.Info(fmt.Sprintf("Submitting %d changes to Route53", len(changes)))
batch := new(route53.ChangeBatch) batch := &types.ChangeBatch{
batch.SetChanges(changes) Changes: changes,
batch.SetComment(fmt.Sprintf("enrtree update %d/%d of %s at seq %d", i+1, len(batches), name, t.Seq())) Comment: aws.String(fmt.Sprintf("enrtree update %d/%d of %s at seq %d", i+1, len(batches), name, t.Seq())),
}
req := &route53.ChangeResourceRecordSetsInput{HostedZoneId: &c.zoneID, ChangeBatch: batch} req := &route53.ChangeResourceRecordSetsInput{HostedZoneId: &c.zoneID, ChangeBatch: batch}
resp, err := c.api.ChangeResourceRecordSets(req) changesToCheck[i], err = c.api.ChangeResourceRecordSets(context.TODO(), req)
if err != nil { if err != nil {
return err return err
} }
}
log.Info(fmt.Sprintf("Waiting for change request %s", *resp.ChangeInfo.Id)) // wait for all change batches to propagate
wreq := &route53.GetChangeInput{Id: resp.ChangeInfo.Id} for _, change := range changesToCheck {
if err := c.api.WaitUntilResourceRecordSetsChanged(wreq); err != nil { log.Info(fmt.Sprintf("Waiting for change request %s", *change.ChangeInfo.Id))
return err wreq := &route53.GetChangeInput{Id: change.ChangeInfo.Id}
var count int
for {
wresp, err := c.api.GetChange(context.TODO(), wreq)
if err != nil {
return err
}
count++
if wresp.ChangeInfo.Status == types.ChangeStatusInsync || count >= maxRetryLimit {
break
}
time.Sleep(30 * time.Second)
} }
} }
return nil return nil
} }
@ -140,7 +162,7 @@ func (c *route53Client) findZoneID(name string) (string, error) {
log.Info(fmt.Sprintf("Finding Route53 Zone ID for %s", name)) log.Info(fmt.Sprintf("Finding Route53 Zone ID for %s", name))
var req route53.ListHostedZonesByNameInput var req route53.ListHostedZonesByNameInput
for { for {
resp, err := c.api.ListHostedZonesByName(&req) resp, err := c.api.ListHostedZonesByName(context.TODO(), &req)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -149,7 +171,7 @@ func (c *route53Client) findZoneID(name string) (string, error) {
return *zone.Id, nil return *zone.Id, nil
} }
} }
if !*resp.IsTruncated { if !resp.IsTruncated {
break break
} }
req.DNSName = resp.NextDNSName req.DNSName = resp.NextDNSName
@ -159,7 +181,7 @@ func (c *route53Client) findZoneID(name string) (string, error) {
} }
// computeChanges creates DNS changes for the given record. // computeChanges creates DNS changes for the given record.
func (c *route53Client) computeChanges(name string, records map[string]string, existing map[string]recordSet) []*route53.Change { func (c *route53Client) computeChanges(name string, records map[string]string, existing map[string]recordSet) []types.Change {
// Convert all names to lowercase. // Convert all names to lowercase.
lrecords := make(map[string]string, len(records)) lrecords := make(map[string]string, len(records))
for name, r := range records { for name, r := range records {
@ -167,7 +189,7 @@ func (c *route53Client) computeChanges(name string, records map[string]string, e
} }
records = lrecords records = lrecords
var changes []*route53.Change var changes []types.Change
for path, val := range records { for path, val := range records {
ttl := int64(rootTTL) ttl := int64(rootTTL)
if path != name { if path != name {
@ -204,21 +226,21 @@ func (c *route53Client) computeChanges(name string, records map[string]string, e
} }
// sortChanges ensures DNS changes are in leaf-added -> root-changed -> leaf-deleted order. // sortChanges ensures DNS changes are in leaf-added -> root-changed -> leaf-deleted order.
func sortChanges(changes []*route53.Change) { func sortChanges(changes []types.Change) {
score := map[string]int{"CREATE": 1, "UPSERT": 2, "DELETE": 3} score := map[string]int{"CREATE": 1, "UPSERT": 2, "DELETE": 3}
sort.Slice(changes, func(i, j int) bool { sort.Slice(changes, func(i, j int) bool {
if *changes[i].Action == *changes[j].Action { if changes[i].Action == changes[j].Action {
return *changes[i].ResourceRecordSet.Name < *changes[j].ResourceRecordSet.Name return *changes[i].ResourceRecordSet.Name < *changes[j].ResourceRecordSet.Name
} }
return score[*changes[i].Action] < score[*changes[j].Action] return score[string(changes[i].Action)] < score[string(changes[j].Action)]
}) })
} }
// splitChanges splits up DNS changes such that each change batch // splitChanges splits up DNS changes such that each change batch
// is smaller than the given RDATA limit. // is smaller than the given RDATA limit.
func splitChanges(changes []*route53.Change, sizeLimit, countLimit int) [][]*route53.Change { func splitChanges(changes []types.Change, sizeLimit, countLimit int) [][]types.Change {
var ( var (
batches [][]*route53.Change batches [][]types.Change
batchSize int batchSize int
batchCount int batchCount int
) )
@ -241,7 +263,7 @@ func splitChanges(changes []*route53.Change, sizeLimit, countLimit int) [][]*rou
} }
// changeSize returns the RDATA size of a DNS change. // changeSize returns the RDATA size of a DNS change.
func changeSize(ch *route53.Change) int { func changeSize(ch types.Change) int {
size := 0 size := 0
for _, rr := range ch.ResourceRecordSet.ResourceRecords { for _, rr := range ch.ResourceRecordSet.ResourceRecords {
if rr.Value != nil { if rr.Value != nil {
@ -251,8 +273,8 @@ func changeSize(ch *route53.Change) int {
return size return size
} }
func changeCount(ch *route53.Change) int { func changeCount(ch types.Change) int {
if *ch.Action == "UPSERT" { if ch.Action == types.ChangeActionUpsert {
return 2 return 2
} }
return 1 return 1
@ -262,13 +284,19 @@ func changeCount(ch *route53.Change) int {
func (c *route53Client) collectRecords(name string) (map[string]recordSet, error) { func (c *route53Client) collectRecords(name string) (map[string]recordSet, error) {
log.Info(fmt.Sprintf("Retrieving existing TXT records on %s (%s)", name, c.zoneID)) log.Info(fmt.Sprintf("Retrieving existing TXT records on %s (%s)", name, c.zoneID))
var req route53.ListResourceRecordSetsInput var req route53.ListResourceRecordSetsInput
req.SetHostedZoneId(c.zoneID) req.HostedZoneId = &c.zoneID
existing := make(map[string]recordSet) existing := make(map[string]recordSet)
err := c.api.ListResourceRecordSetsPages(&req, func(resp *route53.ListResourceRecordSetsOutput, last bool) bool { for {
resp, err := c.api.ListResourceRecordSets(context.TODO(), &req)
if err != nil {
return existing, err
}
for _, set := range resp.ResourceRecordSets { for _, set := range resp.ResourceRecordSets {
if !isSubdomain(*set.Name, name) || *set.Type != "TXT" { if !isSubdomain(*set.Name, name) || set.Type != types.RRTypeTxt {
continue continue
} }
s := recordSet{ttl: *set.TTL} s := recordSet{ttl: *set.TTL}
for _, rec := range set.ResourceRecords { for _, rec := range set.ResourceRecords {
s.values = append(s.values, *rec.Value) s.values = append(s.values, *rec.Value)
@ -276,28 +304,38 @@ func (c *route53Client) collectRecords(name string) (map[string]recordSet, error
name := strings.TrimSuffix(*set.Name, ".") name := strings.TrimSuffix(*set.Name, ".")
existing[name] = s existing[name] = s
} }
return true
}) if !resp.IsTruncated {
return existing, err break
}
// sets the cursor to the next batch
req.StartRecordIdentifier = resp.NextRecordIdentifier
}
return existing, nil
} }
// newTXTChange creates a change to a TXT record. // newTXTChange creates a change to a TXT record.
func newTXTChange(action, name string, ttl int64, values ...string) *route53.Change { func newTXTChange(action, name string, ttl int64, values ...string) types.Change {
var c route53.Change r := types.ResourceRecordSet{
var r route53.ResourceRecordSet Type: types.RRTypeTxt,
var rrs []*route53.ResourceRecord Name: &name,
TTL: &ttl,
}
var rrs []types.ResourceRecord
for _, val := range values { for _, val := range values {
rr := new(route53.ResourceRecord) var rr types.ResourceRecord
rr.SetValue(val) rr.Value = aws.String(val)
rrs = append(rrs, rr) rrs = append(rrs, rr)
} }
r.SetType("TXT")
r.SetName(name) r.ResourceRecords = rrs
r.SetTTL(ttl)
r.SetResourceRecords(rrs) return types.Change{
c.SetAction(action) Action: types.ChangeAction(action),
c.SetResourceRecordSet(&r) ResourceRecordSet: &r,
return &c }
} }
// isSubdomain returns true if name is a subdomain of domain. // isSubdomain returns true if name is a subdomain of domain.

@ -20,7 +20,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/aws/aws-sdk-go/service/route53" "github.com/aws/aws-sdk-go-v2/service/route53/types"
) )
// This test checks that computeChanges/splitChanges create DNS changes in // This test checks that computeChanges/splitChanges create DNS changes in
@ -43,93 +43,93 @@ func TestRoute53ChangeSort(t *testing.T) {
"MHTDO6TMUBRIA2XWG5LUDACK24.n": "enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o", "MHTDO6TMUBRIA2XWG5LUDACK24.n": "enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o",
} }
wantChanges := []*route53.Change{ wantChanges := []types.Change{
{ {
Action: sp("CREATE"), Action: "CREATE",
ResourceRecordSet: &route53.ResourceRecordSet{ ResourceRecordSet: &types.ResourceRecordSet{
Name: sp("2xs2367yhaxjfglzhvawlqd4zy.n"), Name: sp("2xs2367yhaxjfglzhvawlqd4zy.n"),
ResourceRecords: []*route53.ResourceRecord{{ ResourceRecords: []types.ResourceRecord{{
Value: sp(`"enr:-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA"`), Value: sp(`"enr:-HW4QOFzoVLaFJnNhbgMoDXPnOvcdVuj7pDpqRvh6BRDO68aVi5ZcjB3vzQRZH2IcLBGHzo8uUN3snqmgTiE56CH3AMBgmlkgnY0iXNlY3AyNTZrMaECC2_24YYkYHEgdzxlSNKQEnHhuNAbNlMlWJxrJxbAFvA"`),
}}, }},
TTL: ip(treeNodeTTL), TTL: ip(treeNodeTTL),
Type: sp("TXT"), Type: "TXT",
}, },
}, },
{ {
Action: sp("CREATE"), Action: "CREATE",
ResourceRecordSet: &route53.ResourceRecordSet{ ResourceRecordSet: &types.ResourceRecordSet{
Name: sp("c7hrfpf3blgf3yr4dy5kx3smbe.n"), Name: sp("c7hrfpf3blgf3yr4dy5kx3smbe.n"),
ResourceRecords: []*route53.ResourceRecord{{ ResourceRecords: []types.ResourceRecord{{
Value: sp(`"enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org"`), Value: sp(`"enrtree://AM5FCQLWIZX2QFPNJAP7VUERCCRNGRHWZG3YYHIUV7BVDQ5FDPRT2@morenodes.example.org"`),
}}, }},
TTL: ip(treeNodeTTL), TTL: ip(treeNodeTTL),
Type: sp("TXT"), Type: "TXT",
}, },
}, },
{ {
Action: sp("CREATE"), Action: "CREATE",
ResourceRecordSet: &route53.ResourceRecordSet{ ResourceRecordSet: &types.ResourceRecordSet{
Name: sp("h4fht4b454p6uxfd7jcyq5pwdy.n"), Name: sp("h4fht4b454p6uxfd7jcyq5pwdy.n"),
ResourceRecords: []*route53.ResourceRecord{{ ResourceRecords: []types.ResourceRecord{{
Value: sp(`"enr:-HW4QAggRauloj2SDLtIHN1XBkvhFZ1vtf1raYQp9TBW2RD5EEawDzbtSmlXUfnaHcvwOizhVYLtr7e6vw7NAf6mTuoCgmlkgnY0iXNlY3AyNTZrMaECjrXI8TLNXU0f8cthpAMxEshUyQlK-AM0PW2wfrnacNI"`), Value: sp(`"enr:-HW4QAggRauloj2SDLtIHN1XBkvhFZ1vtf1raYQp9TBW2RD5EEawDzbtSmlXUfnaHcvwOizhVYLtr7e6vw7NAf6mTuoCgmlkgnY0iXNlY3AyNTZrMaECjrXI8TLNXU0f8cthpAMxEshUyQlK-AM0PW2wfrnacNI"`),
}}, }},
TTL: ip(treeNodeTTL), TTL: ip(treeNodeTTL),
Type: sp("TXT"), Type: "TXT",
}, },
}, },
{ {
Action: sp("CREATE"), Action: "CREATE",
ResourceRecordSet: &route53.ResourceRecordSet{ ResourceRecordSet: &types.ResourceRecordSet{
Name: sp("jwxydbpxywg6fx3gmdibfa6cj4.n"), Name: sp("jwxydbpxywg6fx3gmdibfa6cj4.n"),
ResourceRecords: []*route53.ResourceRecord{{ ResourceRecords: []types.ResourceRecord{{
Value: sp(`"enrtree-branch:2XS2367YHAXJFGLZHVAWLQD4ZY,H4FHT4B454P6UXFD7JCYQ5PWDY,MHTDO6TMUBRIA2XWG5LUDACK24"`), Value: sp(`"enrtree-branch:2XS2367YHAXJFGLZHVAWLQD4ZY,H4FHT4B454P6UXFD7JCYQ5PWDY,MHTDO6TMUBRIA2XWG5LUDACK24"`),
}}, }},
TTL: ip(treeNodeTTL), TTL: ip(treeNodeTTL),
Type: sp("TXT"), Type: "TXT",
}, },
}, },
{ {
Action: sp("CREATE"), Action: "CREATE",
ResourceRecordSet: &route53.ResourceRecordSet{ ResourceRecordSet: &types.ResourceRecordSet{
Name: sp("mhtdo6tmubria2xwg5ludack24.n"), Name: sp("mhtdo6tmubria2xwg5ludack24.n"),
ResourceRecords: []*route53.ResourceRecord{{ ResourceRecords: []types.ResourceRecord{{
Value: sp(`"enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o"`), Value: sp(`"enr:-HW4QLAYqmrwllBEnzWWs7I5Ev2IAs7x_dZlbYdRdMUx5EyKHDXp7AV5CkuPGUPdvbv1_Ms1CPfhcGCvSElSosZmyoqAgmlkgnY0iXNlY3AyNTZrMaECriawHKWdDRk2xeZkrOXBQ0dfMFLHY4eENZwdufn1S1o"`),
}}, }},
TTL: ip(treeNodeTTL), TTL: ip(treeNodeTTL),
Type: sp("TXT"), Type: "TXT",
}, },
}, },
{ {
Action: sp("UPSERT"), Action: "UPSERT",
ResourceRecordSet: &route53.ResourceRecordSet{ ResourceRecordSet: &types.ResourceRecordSet{
Name: sp("n"), Name: sp("n"),
ResourceRecords: []*route53.ResourceRecord{{ ResourceRecords: []types.ResourceRecord{{
Value: sp(`"enrtree-root:v1 e=JWXYDBPXYWG6FX3GMDIBFA6CJ4 l=C7HRFPF3BLGF3YR4DY5KX3SMBE seq=1 sig=o908WmNp7LibOfPsr4btQwatZJ5URBr2ZAuxvK4UWHlsB9sUOTJQaGAlLPVAhM__XJesCHxLISo94z5Z2a463gA"`), Value: sp(`"enrtree-root:v1 e=JWXYDBPXYWG6FX3GMDIBFA6CJ4 l=C7HRFPF3BLGF3YR4DY5KX3SMBE seq=1 sig=o908WmNp7LibOfPsr4btQwatZJ5URBr2ZAuxvK4UWHlsB9sUOTJQaGAlLPVAhM__XJesCHxLISo94z5Z2a463gA"`),
}}, }},
TTL: ip(rootTTL), TTL: ip(rootTTL),
Type: sp("TXT"), Type: "TXT",
}, },
}, },
{ {
Action: sp("DELETE"), Action: "DELETE",
ResourceRecordSet: &route53.ResourceRecordSet{ ResourceRecordSet: &types.ResourceRecordSet{
Name: sp("2kfjogvxdqtxxugbh7gs7naaai.n"), Name: sp("2kfjogvxdqtxxugbh7gs7naaai.n"),
ResourceRecords: []*route53.ResourceRecord{ ResourceRecords: []types.ResourceRecord{
{Value: sp(`"enr:-HW4QO1ml1DdXLeZLsUxewnthhUy8eROqkDyoMTyavfks9JlYQIlMFEUoM78PovJDPQrAkrb3LRJ-""vtrymDguKCOIAWAgmlkgnY0iXNlY3AyNTZrMaEDffaGfJzgGhUif1JqFruZlYmA31HzathLSWxfbq_QoQ4"`)}, {Value: sp(`"enr:-HW4QO1ml1DdXLeZLsUxewnthhUy8eROqkDyoMTyavfks9JlYQIlMFEUoM78PovJDPQrAkrb3LRJ-""vtrymDguKCOIAWAgmlkgnY0iXNlY3AyNTZrMaEDffaGfJzgGhUif1JqFruZlYmA31HzathLSWxfbq_QoQ4"`)},
}, },
TTL: ip(3333), TTL: ip(3333),
Type: sp("TXT"), Type: "TXT",
}, },
}, },
{ {
Action: sp("DELETE"), Action: "DELETE",
ResourceRecordSet: &route53.ResourceRecordSet{ ResourceRecordSet: &types.ResourceRecordSet{
Name: sp("fdxn3sn67na5dka4j2gok7bvqi.n"), Name: sp("fdxn3sn67na5dka4j2gok7bvqi.n"),
ResourceRecords: []*route53.ResourceRecord{{ ResourceRecords: []types.ResourceRecord{{
Value: sp(`"enrtree-branch:"`), Value: sp(`"enrtree-branch:"`),
}}, }},
TTL: ip(treeNodeTTL), TTL: ip(treeNodeTTL),
Type: sp("TXT"), Type: "TXT",
}, },
}, },
} }
@ -141,7 +141,7 @@ func TestRoute53ChangeSort(t *testing.T) {
} }
// Check splitting according to size. // Check splitting according to size.
wantSplit := [][]*route53.Change{ wantSplit := [][]types.Change{
wantChanges[:4], wantChanges[:4],
wantChanges[4:6], wantChanges[4:6],
wantChanges[6:], wantChanges[6:],
@ -152,7 +152,7 @@ func TestRoute53ChangeSort(t *testing.T) {
} }
// Check splitting according to count. // Check splitting according to count.
wantSplit = [][]*route53.Change{ wantSplit = [][]types.Change{
wantChanges[:5], wantChanges[:5],
wantChanges[5:], wantChanges[5:],
} }

7
go.mod

@ -1,11 +1,14 @@
module github.com/ethereum/go-ethereum module github.com/ethereum/go-ethereum
go 1.13 go 1.15
require ( require (
github.com/Azure/azure-storage-blob-go v0.7.0 github.com/Azure/azure-storage-blob-go v0.7.0
github.com/VictoriaMetrics/fastcache v1.5.7 github.com/VictoriaMetrics/fastcache v1.5.7
github.com/aws/aws-sdk-go v1.25.48 github.com/aws/aws-sdk-go-v2 v1.2.0
github.com/aws/aws-sdk-go-v2/config v1.1.1
github.com/aws/aws-sdk-go-v2/credentials v1.1.1
github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1
github.com/btcsuite/btcd v0.20.1-beta github.com/btcsuite/btcd v0.20.1-beta
github.com/cespare/cp v0.1.0 github.com/cespare/cp v0.1.0
github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9 github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9

25
go.sum

@ -62,6 +62,24 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go v1.25.48 h1:J82DYDGZHOKHdhx6hD24Tm30c2C3GchYGfN0mf9iKUk= github.com/aws/aws-sdk-go v1.25.48 h1:J82DYDGZHOKHdhx6hD24Tm30c2C3GchYGfN0mf9iKUk=
github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v1.2.0 h1:BS+UYpbsElC82gB+2E2jiCBg36i8HlubTB/dO/moQ9c=
github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo=
github.com/aws/aws-sdk-go-v2/config v1.1.1 h1:ZAoq32boMzcaTW9bcUacBswAmHTbvlvDJICgHFZuECo=
github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y=
github.com/aws/aws-sdk-go-v2/credentials v1.1.1 h1:NbvWIM1Mx6sNPTxowHgS2ewXCRp+NGTzUYb/96FZJbY=
github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 h1:EtEU7WRaWliitZh2nmuxEXrN0Cb8EgPUFGIoTMeqbzI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 h1:4AH9fFjUlVktQMznF+YN33aWNXaR4VgDXyP28qokJC0=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8=
github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1 h1:cKr6St+CtC3/dl/rEBJvlk7A/IN5D5F02GNkGzfbtVU=
github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4=
github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 h1:37QubsarExl5ZuCBlnRP+7l1tNwZPBSTqpTBrPH98RU=
github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0=
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 h1:TJoIfnIFubCX0ACVeJ0w46HEH5MwjwYN4iFhuYIhfIY=
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM=
github.com/aws/smithy-go v1.1.0 h1:D6CSsM3gdxaGaqXnPgOBCeL6Mophqzu7KJOu7zW78sU=
github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
@ -193,6 +211,9 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64=
github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
@ -265,6 +286,10 @@ github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1C
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=