chain: Use f2 code
This commit is contained in:
parent
fd7daf4a31
commit
bd0b189d1e
123
chain/actors.go
Normal file
123
chain/actors.go
Normal file
@ -0,0 +1,123 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cbor.RegisterCborType(InitActorState{})
|
||||
cbor.RegisterCborType(AccountActorState{})
|
||||
}
|
||||
|
||||
var AccountActorCodeCid cid.Cid
|
||||
var StorageMarketActorCodeCid cid.Cid
|
||||
var StorageMinerCodeCid cid.Cid
|
||||
var MultisigActorCodeCid cid.Cid
|
||||
var InitActorCodeCid cid.Cid
|
||||
|
||||
var InitActorAddress = mustIDAddress(0)
|
||||
var NetworkAddress = mustIDAddress(1)
|
||||
var StorageMarketAddress = mustIDAddress(2)
|
||||
|
||||
func mustIDAddress(i uint64) address.Address {
|
||||
a, err := address.NewIDAddress(i)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func init() {
|
||||
pref := cid.NewPrefixV1(cid.Raw, mh.ID)
|
||||
mustSum := func(s string) cid.Cid {
|
||||
c, err := pref.Sum([]byte(s))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
AccountActorCodeCid = mustSum("account")
|
||||
StorageMarketActorCodeCid = mustSum("smarket")
|
||||
StorageMinerCodeCid = mustSum("sminer")
|
||||
MultisigActorCodeCid = mustSum("multisig")
|
||||
InitActorCodeCid = mustSum("init")
|
||||
}
|
||||
|
||||
type VMActor struct {
|
||||
}
|
||||
|
||||
type InitActorState struct {
|
||||
AddressMap cid.Cid
|
||||
|
||||
NextID uint64
|
||||
}
|
||||
|
||||
func (ias *InitActorState) AddActor(vmctx *VMContext, addr address.Address) (address.Address, error) {
|
||||
nid := ias.NextID
|
||||
ias.NextID++
|
||||
|
||||
amap, err := hamt.LoadNode(context.TODO(), vmctx.Ipld(), ias.AddressMap)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
if err := amap.Set(context.TODO(), string(addr.Bytes()), nid); err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
if err := amap.Flush(context.TODO()); err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
ncid, err := vmctx.Ipld().Put(context.TODO(), amap)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
ias.AddressMap = ncid
|
||||
|
||||
return address.NewIDAddress(nid)
|
||||
}
|
||||
|
||||
func (ias *InitActorState) Lookup(cst *hamt.CborIpldStore, addr address.Address) (address.Address, error) {
|
||||
amap, err := hamt.LoadNode(context.TODO(), cst, ias.AddressMap)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
val, err := amap.Find(context.TODO(), string(addr.Bytes()))
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
ival, ok := val.(uint64)
|
||||
if !ok {
|
||||
return address.Undef, fmt.Errorf("invalid value in init actor state, expected uint64, got %T", val)
|
||||
}
|
||||
|
||||
return address.NewIDAddress(ival)
|
||||
}
|
||||
|
||||
type AccountActorState struct {
|
||||
Address address.Address
|
||||
}
|
||||
|
||||
func DeductFunds(act *Actor, amt BigInt) error {
|
||||
if BigCmp(act.Balance, amt) < 0 {
|
||||
return fmt.Errorf("not enough funds")
|
||||
}
|
||||
|
||||
act.Balance = BigSub(act.Balance, amt)
|
||||
return nil
|
||||
}
|
||||
|
||||
func DepositFunds(act *Actor, amt BigInt) {
|
||||
act.Balance = BigAdd(act.Balance, amt)
|
||||
}
|
315
chain/address/address.go
Normal file
315
chain/address/address.go
Normal file
@ -0,0 +1,315 @@
|
||||
package address
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/filecoin-project/go-filecoin/bls-signatures"
|
||||
|
||||
"github.com/filecoin-project/go-leb128"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
"github.com/minio/blake2b-simd"
|
||||
"github.com/polydawn/refmt/obj/atlas"
|
||||
)
|
||||
|
||||
func init() {
|
||||
cbor.RegisterCborType(addressAtlasEntry)
|
||||
}
|
||||
|
||||
var addressAtlasEntry = atlas.BuildEntry(Address{}).Transform().
|
||||
TransformMarshal(atlas.MakeMarshalTransformFunc(
|
||||
func(a Address) ([]byte, error) {
|
||||
return a.Bytes(), nil
|
||||
})).
|
||||
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
|
||||
func(x []byte) (Address, error) {
|
||||
return NewFromBytes(x)
|
||||
})).
|
||||
Complete()
|
||||
|
||||
// Address is the go type that represents an address in the filecoin network.
|
||||
type Address struct{ str string }
|
||||
|
||||
// Undef is the type that represents an undefined address.
|
||||
var Undef = Address{}
|
||||
|
||||
// Network represents which network an address belongs to.
|
||||
type Network = byte
|
||||
|
||||
const (
|
||||
// Mainnet is the main network.
|
||||
Mainnet Network = iota
|
||||
// Testnet is the test network.
|
||||
Testnet
|
||||
)
|
||||
|
||||
// MainnetPrefix is the main network prefix.
|
||||
const MainnetPrefix = "f"
|
||||
|
||||
// TestnetPrefix is the main network prefix.
|
||||
const TestnetPrefix = "t"
|
||||
|
||||
// Protocol represents which protocol an address uses.
|
||||
type Protocol = byte
|
||||
|
||||
const (
|
||||
// ID represents the address ID protocol.
|
||||
ID Protocol = iota
|
||||
// SECP256K1 represents the address SECP256K1 protocol.
|
||||
SECP256K1
|
||||
// Actor represents the address Actor protocol.
|
||||
Actor
|
||||
// BLS represents the address BLS protocol.
|
||||
BLS
|
||||
)
|
||||
|
||||
// Protocol returns the protocol used by the address.
|
||||
func (a Address) Protocol() Protocol {
|
||||
return a.str[0]
|
||||
}
|
||||
|
||||
// Payload returns the payload of the address.
|
||||
func (a Address) Payload() []byte {
|
||||
return []byte(a.str[1:])
|
||||
}
|
||||
|
||||
// Bytes returns the address as bytes.
|
||||
func (a Address) Bytes() []byte {
|
||||
return []byte(a.str)
|
||||
}
|
||||
|
||||
// String returns an address encoded as a string.
|
||||
func (a Address) String() string {
|
||||
str, err := encode(Testnet, a)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// Empty returns true if the address is empty, false otherwise.
|
||||
func (a Address) Empty() bool {
|
||||
return a == Undef
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals the cbor bytes into the address.
|
||||
func (a Address) Unmarshal(b []byte) error {
|
||||
return cbor.DecodeInto(b, &a)
|
||||
}
|
||||
|
||||
// Marshal marshals the address to cbor.
|
||||
func (a Address) Marshal() ([]byte, error) {
|
||||
return cbor.DumpObject(a)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json unmarshal interface.
|
||||
func (a *Address) UnmarshalJSON(b []byte) error {
|
||||
in := strings.TrimSuffix(strings.TrimPrefix(string(b), `"`), `"`)
|
||||
addr, err := decode(in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*a = addr
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json marshal interface.
|
||||
func (a Address) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(a.String())
|
||||
}
|
||||
|
||||
// Format implements the Formatter interface.
|
||||
func (a Address) Format(f fmt.State, c rune) {
|
||||
switch c {
|
||||
case 'v':
|
||||
if a.Empty() {
|
||||
fmt.Fprint(f, UndefAddressString) //nolint: errcheck
|
||||
} else {
|
||||
fmt.Fprintf(f, "[%x - %x]", a.Protocol(), a.Payload()) // nolint: errcheck
|
||||
}
|
||||
case 's':
|
||||
fmt.Fprintf(f, "%s", a.String()) // nolint: errcheck
|
||||
default:
|
||||
fmt.Fprintf(f, "%"+string(c), a.Bytes()) // nolint: errcheck
|
||||
}
|
||||
}
|
||||
|
||||
// NewIDAddress returns an address using the ID protocol.
|
||||
func NewIDAddress(id uint64) (Address, error) {
|
||||
return newAddress(ID, leb128.FromUInt64(id))
|
||||
}
|
||||
|
||||
// NewSecp256k1Address returns an address using the SECP256K1 protocol.
|
||||
func NewSecp256k1Address(pubkey []byte) (Address, error) {
|
||||
return newAddress(SECP256K1, addressHash(pubkey))
|
||||
}
|
||||
|
||||
// NewActorAddress returns an address using the Actor protocol.
|
||||
func NewActorAddress(data []byte) (Address, error) {
|
||||
return newAddress(Actor, addressHash(data))
|
||||
}
|
||||
|
||||
// NewBLSAddress returns an address using the BLS protocol.
|
||||
func NewBLSAddress(pubkey []byte) (Address, error) {
|
||||
return newAddress(BLS, pubkey)
|
||||
}
|
||||
|
||||
// NewFromString returns the address represented by the string `addr`.
|
||||
func NewFromString(addr string) (Address, error) {
|
||||
return decode(addr)
|
||||
}
|
||||
|
||||
// NewFromBytes return the address represented by the bytes `addr`.
|
||||
func NewFromBytes(addr []byte) (Address, error) {
|
||||
if len(addr) == 0 {
|
||||
return Undef, nil
|
||||
}
|
||||
if len(addr) == 1 {
|
||||
return Undef, ErrInvalidLength
|
||||
}
|
||||
return newAddress(addr[0], addr[1:])
|
||||
}
|
||||
|
||||
// Checksum returns the checksum of `ingest`.
|
||||
func Checksum(ingest []byte) []byte {
|
||||
return hash(ingest, checksumHashConfig)
|
||||
}
|
||||
|
||||
// ValidateChecksum returns true if the checksum of `ingest` is equal to `expected`>
|
||||
func ValidateChecksum(ingest, expect []byte) bool {
|
||||
digest := Checksum(ingest)
|
||||
return bytes.Equal(digest, expect)
|
||||
}
|
||||
|
||||
func addressHash(ingest []byte) []byte {
|
||||
return hash(ingest, payloadHashConfig)
|
||||
}
|
||||
|
||||
func newAddress(protocol Protocol, payload []byte) (Address, error) {
|
||||
switch protocol {
|
||||
case ID:
|
||||
case SECP256K1, Actor:
|
||||
if len(payload) != PayloadHashLength {
|
||||
return Undef, ErrInvalidPayload
|
||||
}
|
||||
case BLS:
|
||||
if len(payload) != bls.PublicKeyBytes {
|
||||
return Undef, ErrInvalidPayload
|
||||
}
|
||||
default:
|
||||
return Undef, ErrUnknownProtocol
|
||||
}
|
||||
explen := 1 + len(payload)
|
||||
buf := make([]byte, explen)
|
||||
|
||||
buf[0] = protocol
|
||||
copy(buf[1:], payload)
|
||||
|
||||
return Address{string(buf)}, nil
|
||||
}
|
||||
|
||||
func encode(network Network, addr Address) (string, error) {
|
||||
if addr == Undef {
|
||||
return UndefAddressString, nil
|
||||
}
|
||||
var ntwk string
|
||||
switch network {
|
||||
case Mainnet:
|
||||
ntwk = MainnetPrefix
|
||||
case Testnet:
|
||||
ntwk = TestnetPrefix
|
||||
default:
|
||||
return UndefAddressString, ErrUnknownNetwork
|
||||
}
|
||||
|
||||
var strAddr string
|
||||
switch addr.Protocol() {
|
||||
case SECP256K1, Actor, BLS:
|
||||
cksm := Checksum(append([]byte{addr.Protocol()}, addr.Payload()...))
|
||||
strAddr = ntwk + fmt.Sprintf("%d", addr.Protocol()) + AddressEncoding.WithPadding(-1).EncodeToString(append(addr.Payload(), cksm[:]...))
|
||||
case ID:
|
||||
strAddr = ntwk + fmt.Sprintf("%d", addr.Protocol()) + fmt.Sprintf("%d", leb128.ToUInt64(addr.Payload()))
|
||||
default:
|
||||
return UndefAddressString, ErrUnknownProtocol
|
||||
}
|
||||
return strAddr, nil
|
||||
}
|
||||
|
||||
func decode(a string) (Address, error) {
|
||||
if len(a) == 0 {
|
||||
return Undef, nil
|
||||
}
|
||||
if a == UndefAddressString {
|
||||
return Undef, nil
|
||||
}
|
||||
if len(a) > MaxAddressStringLength || len(a) < 3 {
|
||||
return Undef, ErrInvalidLength
|
||||
}
|
||||
|
||||
if string(a[0]) != MainnetPrefix && string(a[0]) != TestnetPrefix {
|
||||
return Undef, ErrUnknownNetwork
|
||||
}
|
||||
|
||||
var protocol Protocol
|
||||
switch a[1] {
|
||||
case '0':
|
||||
protocol = ID
|
||||
case '1':
|
||||
protocol = SECP256K1
|
||||
case '2':
|
||||
protocol = Actor
|
||||
case '3':
|
||||
protocol = BLS
|
||||
default:
|
||||
return Undef, ErrUnknownProtocol
|
||||
}
|
||||
|
||||
raw := a[2:]
|
||||
if protocol == ID {
|
||||
// 20 is length of math.MaxUint64 as a string
|
||||
if len(raw) > 20 {
|
||||
return Undef, ErrInvalidLength
|
||||
}
|
||||
id, err := strconv.ParseUint(raw, 10, 64)
|
||||
if err != nil {
|
||||
return Undef, ErrInvalidPayload
|
||||
}
|
||||
return newAddress(protocol, leb128.FromUInt64(id))
|
||||
}
|
||||
|
||||
payloadcksm, err := AddressEncoding.WithPadding(-1).DecodeString(raw)
|
||||
if err != nil {
|
||||
return Undef, err
|
||||
}
|
||||
payload := payloadcksm[:len(payloadcksm)-ChecksumHashLength]
|
||||
cksm := payloadcksm[len(payloadcksm)-ChecksumHashLength:]
|
||||
|
||||
if protocol == SECP256K1 || protocol == Actor {
|
||||
if len(payload) != 20 {
|
||||
return Undef, ErrInvalidPayload
|
||||
}
|
||||
}
|
||||
|
||||
if !ValidateChecksum(append([]byte{protocol}, payload...), cksm) {
|
||||
return Undef, ErrInvalidChecksum
|
||||
}
|
||||
|
||||
return newAddress(protocol, payload)
|
||||
}
|
||||
|
||||
func hash(ingest []byte, cfg *blake2b.Config) []byte {
|
||||
hasher, err := blake2b.New(cfg)
|
||||
if err != nil {
|
||||
// If this happens sth is very wrong.
|
||||
panic(fmt.Sprintf("invalid address hash configuration: %v", err))
|
||||
}
|
||||
if _, err := hasher.Write(ingest); err != nil {
|
||||
// blake2bs Write implementation never returns an error in its current
|
||||
// setup. So if this happens sth went very wrong.
|
||||
panic(fmt.Sprintf("blake2b is unable to process hashes: %v", err))
|
||||
}
|
||||
return hasher.Sum(nil)
|
||||
}
|
448
chain/address/address_test.go
Normal file
448
chain/address/address_test.go
Normal file
@ -0,0 +1,448 @@
|
||||
package address
|
||||
|
||||
import (
|
||||
"encoding/base32"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/filecoin-project/go-leb128"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-filecoin/bls-signatures"
|
||||
"github.com/filecoin-project/go-filecoin/crypto"
|
||||
tf "github.com/filecoin-project/go-filecoin/testhelpers/testflags"
|
||||
)
|
||||
|
||||
func init() {
|
||||
rand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
||||
func TestRandomIDAddress(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
addr, err := NewIDAddress(uint64(rand.Int()))
|
||||
assert.NoError(err)
|
||||
assert.Equal(ID, addr.Protocol())
|
||||
|
||||
str, err := encode(Testnet, addr)
|
||||
assert.NoError(err)
|
||||
|
||||
maybe, err := decode(str)
|
||||
assert.NoError(err)
|
||||
assert.Equal(addr, maybe)
|
||||
|
||||
}
|
||||
|
||||
func TestVectorsIDAddress(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
testCases := []struct {
|
||||
input uint64
|
||||
expected string
|
||||
}{
|
||||
{uint64(0), "t00"},
|
||||
{uint64(1), "t01"},
|
||||
{uint64(10), "t010"},
|
||||
{uint64(150), "t0150"},
|
||||
{uint64(499), "t0499"},
|
||||
{uint64(1024), "t01024"},
|
||||
{uint64(1729), "t01729"},
|
||||
{uint64(999999), "t0999999"},
|
||||
{math.MaxUint64, fmt.Sprintf("t0%s", strconv.FormatUint(math.MaxUint64, 10))},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("testing actorID address: %s", tc.expected), func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// Round trip encoding and decoding from string
|
||||
addr, err := NewIDAddress(tc.input)
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.expected, addr.String())
|
||||
|
||||
maybeAddr, err := NewFromString(tc.expected)
|
||||
assert.NoError(err)
|
||||
assert.Equal(ID, maybeAddr.Protocol())
|
||||
assert.Equal(tc.input, leb128.ToUInt64(maybeAddr.Payload()))
|
||||
|
||||
// Round trip to and from bytes
|
||||
maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes())
|
||||
assert.NoError(err)
|
||||
assert.Equal(maybeAddr, maybeAddrBytes)
|
||||
|
||||
// Round trip encoding and decoding json
|
||||
b, err := addr.MarshalJSON()
|
||||
assert.NoError(err)
|
||||
|
||||
var newAddr Address
|
||||
err = newAddr.UnmarshalJSON(b)
|
||||
assert.NoError(err)
|
||||
assert.Equal(addr, newAddr)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSecp256k1Address(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
sk, err := crypto.GenerateKey()
|
||||
assert.NoError(err)
|
||||
|
||||
addr, err := NewSecp256k1Address(crypto.PublicKey(sk))
|
||||
assert.NoError(err)
|
||||
assert.Equal(SECP256K1, addr.Protocol())
|
||||
|
||||
str, err := encode(Mainnet, addr)
|
||||
assert.NoError(err)
|
||||
|
||||
maybe, err := decode(str)
|
||||
assert.NoError(err)
|
||||
assert.Equal(addr, maybe)
|
||||
|
||||
}
|
||||
|
||||
func TestVectorSecp256k1Address(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
testCases := []struct {
|
||||
input []byte
|
||||
expected string
|
||||
}{
|
||||
{[]byte{4, 148, 2, 250, 195, 126, 100, 50, 164, 22, 163, 160, 202, 84,
|
||||
38, 181, 24, 90, 179, 178, 79, 97, 52, 239, 162, 92, 228, 135, 200,
|
||||
45, 46, 78, 19, 191, 69, 37, 17, 224, 210, 36, 84, 33, 248, 97, 59,
|
||||
193, 13, 114, 250, 33, 102, 102, 169, 108, 59, 193, 57, 32, 211,
|
||||
255, 35, 63, 208, 188, 5},
|
||||
"t15ihq5ibzwki2b4ep2f46avlkrqzhpqgtga7pdrq"},
|
||||
|
||||
{[]byte{4, 118, 135, 185, 16, 55, 155, 242, 140, 190, 58, 234, 103, 75,
|
||||
18, 0, 12, 107, 125, 186, 70, 255, 192, 95, 108, 148, 254, 42, 34,
|
||||
187, 204, 38, 2, 255, 127, 92, 118, 242, 28, 165, 93, 54, 149, 145,
|
||||
82, 176, 225, 232, 135, 145, 124, 57, 53, 118, 238, 240, 147, 246,
|
||||
30, 189, 58, 208, 111, 127, 218},
|
||||
"t12fiakbhe2gwd5cnmrenekasyn6v5tnaxaqizq6a"},
|
||||
{[]byte{4, 222, 253, 208, 16, 1, 239, 184, 110, 1, 222, 213, 206, 52,
|
||||
248, 71, 167, 58, 20, 129, 158, 230, 65, 188, 182, 11, 185, 41, 147,
|
||||
89, 111, 5, 220, 45, 96, 95, 41, 133, 248, 209, 37, 129, 45, 172,
|
||||
65, 99, 163, 150, 52, 155, 35, 193, 28, 194, 255, 53, 157, 229, 75,
|
||||
226, 135, 234, 98, 49, 155},
|
||||
"t1wbxhu3ypkuo6eyp6hjx6davuelxaxrvwb2kuwva"},
|
||||
{[]byte{4, 3, 237, 18, 200, 20, 182, 177, 13, 46, 224, 157, 149, 180,
|
||||
104, 141, 178, 209, 128, 208, 169, 163, 122, 107, 106, 125, 182, 61,
|
||||
41, 129, 30, 233, 115, 4, 121, 216, 239, 145, 57, 233, 18, 73, 202,
|
||||
189, 57, 50, 145, 207, 229, 210, 119, 186, 118, 222, 69, 227, 224,
|
||||
133, 163, 118, 129, 191, 54, 69, 210},
|
||||
"t1xtwapqc6nh4si2hcwpr3656iotzmlwumogqbuaa"},
|
||||
{[]byte{4, 247, 150, 129, 154, 142, 39, 22, 49, 175, 124, 24, 151, 151,
|
||||
181, 69, 214, 2, 37, 147, 97, 71, 230, 1, 14, 101, 98, 179, 206, 158,
|
||||
254, 139, 16, 20, 65, 97, 169, 30, 208, 180, 236, 137, 8, 0, 37, 63,
|
||||
166, 252, 32, 172, 144, 251, 241, 251, 242, 113, 48, 164, 236, 195,
|
||||
228, 3, 183, 5, 118},
|
||||
"t1xcbgdhkgkwht3hrrnui3jdopeejsoatkzmoltqy"},
|
||||
{[]byte{4, 66, 131, 43, 248, 124, 206, 158, 163, 69, 185, 3, 80, 222,
|
||||
125, 52, 149, 133, 156, 164, 73, 5, 156, 94, 136, 221, 231, 66, 133,
|
||||
223, 251, 158, 192, 30, 186, 188, 95, 200, 98, 104, 207, 234, 235,
|
||||
167, 174, 5, 191, 184, 214, 142, 183, 90, 82, 104, 120, 44, 248, 111,
|
||||
200, 112, 43, 239, 138, 31, 224},
|
||||
"t17uoq6tp427uzv7fztkbsnn64iwotfrristwpryy"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("testing secp256k1 address: %s", tc.expected), func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// Round trip encoding and decoding from string
|
||||
addr, err := NewSecp256k1Address(tc.input)
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.expected, addr.String())
|
||||
|
||||
maybeAddr, err := NewFromString(tc.expected)
|
||||
assert.NoError(err)
|
||||
assert.Equal(SECP256K1, maybeAddr.Protocol())
|
||||
assert.Equal(addressHash(tc.input), maybeAddr.Payload())
|
||||
|
||||
// Round trip to and from bytes
|
||||
maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes())
|
||||
assert.NoError(err)
|
||||
assert.Equal(maybeAddr, maybeAddrBytes)
|
||||
|
||||
// Round trip encoding and decoding json
|
||||
b, err := addr.MarshalJSON()
|
||||
assert.NoError(err)
|
||||
|
||||
var newAddr Address
|
||||
err = newAddr.UnmarshalJSON(b)
|
||||
assert.NoError(err)
|
||||
assert.Equal(addr, newAddr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandomActorAddress(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
actorMsg := make([]byte, 20)
|
||||
rand.Read(actorMsg)
|
||||
|
||||
addr, err := NewActorAddress(actorMsg)
|
||||
assert.NoError(err)
|
||||
assert.Equal(Actor, addr.Protocol())
|
||||
|
||||
str, err := encode(Mainnet, addr)
|
||||
assert.NoError(err)
|
||||
|
||||
maybe, err := decode(str)
|
||||
assert.NoError(err)
|
||||
assert.Equal(addr, maybe)
|
||||
|
||||
}
|
||||
|
||||
func TestVectorActorAddress(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
testCases := []struct {
|
||||
input []byte
|
||||
expected string
|
||||
}{
|
||||
{[]byte{118, 18, 129, 144, 205, 240, 104, 209, 65, 128, 68, 172, 192,
|
||||
62, 11, 103, 129, 151, 13, 96},
|
||||
"t24vg6ut43yw2h2jqydgbg2xq7x6f4kub3bg6as6i"},
|
||||
{[]byte{44, 175, 184, 226, 224, 107, 186, 152, 234, 101, 124, 92, 245,
|
||||
244, 32, 35, 170, 35, 232, 142},
|
||||
"t25nml2cfbljvn4goqtclhifepvfnicv6g7mfmmvq"},
|
||||
{[]byte{2, 44, 158, 14, 162, 157, 143, 64, 197, 106, 190, 195, 92, 141,
|
||||
88, 125, 160, 166, 76, 24},
|
||||
"t2nuqrg7vuysaue2pistjjnt3fadsdzvyuatqtfei"},
|
||||
{[]byte{223, 236, 3, 14, 32, 79, 15, 89, 216, 15, 29, 94, 233, 29, 253,
|
||||
6, 109, 127, 99, 189},
|
||||
"t24dd4ox4c2vpf5vk5wkadgyyn6qtuvgcpxxon64a"},
|
||||
{[]byte{61, 58, 137, 232, 221, 171, 84, 120, 50, 113, 108, 109, 70, 140,
|
||||
53, 96, 201, 244, 127, 216},
|
||||
"t2gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr23y"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("testing Actor address: %s", tc.expected), func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// Round trip encoding and decoding from string
|
||||
addr, err := NewActorAddress(tc.input)
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.expected, addr.String())
|
||||
|
||||
maybeAddr, err := NewFromString(tc.expected)
|
||||
assert.NoError(err)
|
||||
assert.Equal(Actor, maybeAddr.Protocol())
|
||||
assert.Equal(addressHash(tc.input), maybeAddr.Payload())
|
||||
|
||||
// Round trip to and from bytes
|
||||
maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes())
|
||||
assert.NoError(err)
|
||||
assert.Equal(maybeAddr, maybeAddrBytes)
|
||||
|
||||
// Round trip encoding and decoding json
|
||||
b, err := addr.MarshalJSON()
|
||||
assert.NoError(err)
|
||||
|
||||
var newAddr Address
|
||||
err = newAddr.UnmarshalJSON(b)
|
||||
assert.NoError(err)
|
||||
assert.Equal(addr, newAddr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandomBLSAddress(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
pk := bls.PrivateKeyPublicKey(bls.PrivateKeyGenerate())
|
||||
|
||||
addr, err := NewBLSAddress(pk[:])
|
||||
assert.NoError(err)
|
||||
assert.Equal(BLS, addr.Protocol())
|
||||
|
||||
str, err := encode(Mainnet, addr)
|
||||
assert.NoError(err)
|
||||
|
||||
maybe, err := decode(str)
|
||||
assert.NoError(err)
|
||||
assert.Equal(addr, maybe)
|
||||
|
||||
}
|
||||
|
||||
func TestVectorBLSAddress(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
testCases := []struct {
|
||||
input []byte
|
||||
expected string
|
||||
}{
|
||||
{[]byte{173, 88, 223, 105, 110, 45, 78, 145, 234, 134, 200, 129, 233, 56,
|
||||
186, 78, 168, 27, 57, 94, 18, 121, 123, 132, 185, 207, 49, 75, 149, 70,
|
||||
112, 94, 131, 156, 122, 153, 214, 6, 178, 71, 221, 180, 249, 172, 122,
|
||||
52, 20, 221},
|
||||
"t3vvmn62lofvhjd2ugzca6sof2j2ubwok6cj4xxbfzz4yuxfkgobpihhd2thlanmsh3w2ptld2gqkn2jvlss4a"},
|
||||
{[]byte{179, 41, 79, 10, 46, 41, 224, 198, 110, 188, 35, 93, 47, 237,
|
||||
202, 86, 151, 191, 120, 74, 246, 5, 199, 90, 246, 8, 230, 166, 61, 92,
|
||||
211, 142, 168, 92, 168, 152, 158, 14, 253, 233, 24, 139, 56, 47,
|
||||
147, 114, 70, 13},
|
||||
"t3wmuu6crofhqmm3v4enos73okk2l366ck6yc4owxwbdtkmpk42ohkqxfitcpa57pjdcftql4tojda2poeruwa"},
|
||||
{[]byte{150, 161, 163, 228, 234, 122, 20, 212, 153, 133, 230, 97, 178,
|
||||
36, 1, 212, 79, 237, 64, 45, 29, 9, 37, 178, 67, 201, 35, 88, 156,
|
||||
15, 188, 126, 50, 205, 4, 226, 158, 215, 141, 21, 211, 125, 58, 170,
|
||||
63, 230, 218, 51},
|
||||
"t3s2q2hzhkpiknjgmf4zq3ejab2rh62qbndueslmsdzervrhapxr7dftie4kpnpdiv2n6tvkr743ndhrsw6d3a"},
|
||||
{[]byte{134, 180, 84, 37, 140, 88, 148, 117, 247, 209, 111, 90, 172, 1,
|
||||
138, 121, 246, 193, 22, 157, 32, 252, 51, 146, 29, 216, 181, 206, 28,
|
||||
172, 108, 52, 143, 144, 163, 96, 54, 36, 246, 174, 185, 27, 100, 81,
|
||||
140, 46, 128, 149},
|
||||
"t3q22fijmmlckhl56rn5nkyamkph3mcfu5ed6dheq53c244hfmnq2i7efdma3cj5voxenwiummf2ajlsbxc65a"},
|
||||
{[]byte{167, 114, 107, 3, 128, 34, 247, 90, 56, 70, 23, 88, 83, 96, 206,
|
||||
230, 41, 7, 10, 45, 157, 40, 113, 41, 101, 229, 242, 110, 204, 64,
|
||||
133, 131, 130, 128, 55, 36, 237, 52, 242, 114, 3, 54, 240, 157, 182,
|
||||
49, 240, 116},
|
||||
"t3u5zgwa4ael3vuocgc5mfgygo4yuqocrntuuhcklf4xzg5tcaqwbyfabxetwtj4tsam3pbhnwghyhijr5mixa"},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("testing bls address: %s", tc.expected), func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// Round trip encoding and decoding from string
|
||||
addr, err := NewBLSAddress(tc.input)
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.expected, addr.String())
|
||||
|
||||
maybeAddr, err := NewFromString(tc.expected)
|
||||
assert.NoError(err)
|
||||
assert.Equal(BLS, maybeAddr.Protocol())
|
||||
assert.Equal(tc.input, maybeAddr.Payload())
|
||||
|
||||
// Round trip to and from bytes
|
||||
maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes())
|
||||
assert.NoError(err)
|
||||
assert.Equal(maybeAddr, maybeAddrBytes)
|
||||
|
||||
// Round trip encoding and decoding json
|
||||
b, err := addr.MarshalJSON()
|
||||
assert.NoError(err)
|
||||
|
||||
var newAddr Address
|
||||
err = newAddr.UnmarshalJSON(b)
|
||||
assert.NoError(err)
|
||||
assert.Equal(addr, newAddr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidStringAddresses(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
testCases := []struct {
|
||||
input string
|
||||
expetErr error
|
||||
}{
|
||||
{"Q2gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr23y", ErrUnknownNetwork},
|
||||
{"t4gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr23y", ErrUnknownProtocol},
|
||||
{"t2gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr24y", ErrInvalidChecksum},
|
||||
{"t0banananananannnnnnnnn", ErrInvalidLength},
|
||||
{"t0banananananannnnnnnn", ErrInvalidPayload},
|
||||
{"t2gfvuyh7v2sx3patm1k23wdzmhyhtmqctasbr24y", base32.CorruptInputError(16)}, // '1' is not in base32 alphabet
|
||||
{"t2gfvuyh7v2sx3paTm1k23wdzmhyhtmqctasbr24y", base32.CorruptInputError(14)}, // 'T' is not in base32 alphabet
|
||||
{"t2", ErrInvalidLength},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("testing string address: %s", tc.expetErr), func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
_, err := NewFromString(tc.input)
|
||||
assert.Equal(tc.expetErr, err)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestInvalidByteAddresses(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
testCases := []struct {
|
||||
input []byte
|
||||
expetErr error
|
||||
}{
|
||||
// Unknown Protocol
|
||||
{[]byte{4, 4, 4}, ErrUnknownProtocol},
|
||||
|
||||
// ID protocol
|
||||
{[]byte{0}, ErrInvalidLength},
|
||||
|
||||
// SECP256K1 Protocol
|
||||
{append([]byte{1}, make([]byte, PayloadHashLength-1)...), ErrInvalidPayload},
|
||||
{append([]byte{1}, make([]byte, PayloadHashLength+1)...), ErrInvalidPayload},
|
||||
// Actor Protocol
|
||||
{append([]byte{2}, make([]byte, PayloadHashLength-1)...), ErrInvalidPayload},
|
||||
{append([]byte{2}, make([]byte, PayloadHashLength+1)...), ErrInvalidPayload},
|
||||
|
||||
// BLS Protocol
|
||||
{append([]byte{3}, make([]byte, bls.PublicKeyBytes-1)...), ErrInvalidPayload},
|
||||
{append([]byte{3}, make([]byte, bls.PrivateKeyBytes+1)...), ErrInvalidPayload},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("testing byte address: %s", tc.expetErr), func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
_, err := NewFromBytes(tc.input)
|
||||
assert.Equal(tc.expetErr, err)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestChecksum(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
assert := assert.New(t)
|
||||
|
||||
data := []byte("helloworld")
|
||||
bata := []byte("kittinmittins")
|
||||
|
||||
cksm := Checksum(data)
|
||||
assert.Len(cksm, ChecksumHashLength)
|
||||
|
||||
assert.True(ValidateChecksum(data, cksm))
|
||||
assert.False(ValidateChecksum(bata, cksm))
|
||||
|
||||
}
|
||||
|
||||
func TestAddressFormat(t *testing.T) {
|
||||
tf.UnitTest(t)
|
||||
|
||||
assert := assert.New(t)
|
||||
require := require.New(t)
|
||||
|
||||
a, err := NewActorAddress([]byte("hello"))
|
||||
require.NoError(err)
|
||||
|
||||
assert.Equal("t2wvjry4bx6bwj6kkhcmvgu5zafqyi5cjzbtet3va", a.String())
|
||||
assert.Equal("02B5531C7037F06C9F2947132A6A77202C308E8939", fmt.Sprintf("%X", a))
|
||||
assert.Equal("[2 - b5531c7037f06c9f2947132a6a77202c308e8939]", fmt.Sprintf("%v", a))
|
||||
|
||||
assert.Equal("", fmt.Sprintf("%X", Undef))
|
||||
assert.Equal(UndefAddressString, Undef.String())
|
||||
assert.Equal(UndefAddressString, fmt.Sprintf("%v", Undef))
|
||||
}
|
88
chain/address/constants.go
Normal file
88
chain/address/constants.go
Normal file
@ -0,0 +1,88 @@
|
||||
package address
|
||||
|
||||
|
||||
import (
|
||||
"encoding/base32"
|
||||
|
||||
"github.com/minio/blake2b-simd"
|
||||
errors "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
var err error
|
||||
|
||||
TestAddress, err = NewActorAddress([]byte("satoshi"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
TestAddress2, err = NewActorAddress([]byte("nakamoto"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
NetworkAddress, err = NewActorAddress([]byte("filecoin"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
StorageMarketAddress, err = NewActorAddress([]byte("storage"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
PaymentBrokerAddress, err = NewActorAddress([]byte("payments"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
// TestAddress is an account with some initial funds in it.
|
||||
TestAddress Address
|
||||
// TestAddress2 is an account with some initial funds in it.
|
||||
TestAddress2 Address
|
||||
|
||||
// NetworkAddress is the filecoin network.
|
||||
NetworkAddress Address
|
||||
// StorageMarketAddress is the hard-coded address of the filecoin storage market.
|
||||
StorageMarketAddress Address
|
||||
// PaymentBrokerAddress is the hard-coded address of the filecoin storage market.
|
||||
PaymentBrokerAddress Address
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrUnknownNetwork is returned when encountering an unknown network in an address.
|
||||
ErrUnknownNetwork = errors.New("unknown address network")
|
||||
|
||||
// ErrUnknownProtocol is returned when encountering an unknown protocol in an address.
|
||||
ErrUnknownProtocol = errors.New("unknown address protocol")
|
||||
// ErrInvalidPayload is returned when encountering an invalid address payload.
|
||||
ErrInvalidPayload = errors.New("invalid address payload")
|
||||
// ErrInvalidLength is returned when encountering an address of invalid length.
|
||||
ErrInvalidLength = errors.New("invalid address length")
|
||||
// ErrInvalidChecksum is returned when encountering an invalid address checksum.
|
||||
ErrInvalidChecksum = errors.New("invalid address checksum")
|
||||
)
|
||||
|
||||
// UndefAddressString is the string used to represent an empty address when encoded to a string.
|
||||
var UndefAddressString = "empty"
|
||||
|
||||
// PayloadHashLength defines the hash length taken over addresses using the Actor and SECP256K1 protocols.
|
||||
const PayloadHashLength = 20
|
||||
|
||||
// ChecksumHashLength defines the hash length used for calculating address checksums.
|
||||
const ChecksumHashLength = 4
|
||||
|
||||
// MaxAddressStringLength is the max length of an address encoded as a string
|
||||
// it include the network prefx, protocol, and bls publickey
|
||||
const MaxAddressStringLength = 2 + 84
|
||||
|
||||
var payloadHashConfig = &blake2b.Config{Size: PayloadHashLength}
|
||||
var checksumHashConfig = &blake2b.Config{Size: ChecksumHashLength}
|
||||
|
||||
const encodeStd = "abcdefghijklmnopqrstuvwxyz234567"
|
||||
|
||||
// AddressEncoding defines the base32 config used for address encoding and decoding.
|
||||
var AddressEncoding = base32.NewEncoding(encodeStd)
|
20
chain/address/testing.go
Normal file
20
chain/address/testing.go
Normal file
@ -0,0 +1,20 @@
|
||||
package address
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// NewForTestGetter returns a closure that returns an address unique to that invocation.
|
||||
// The address is unique wrt the closure returned, not globally.
|
||||
func NewForTestGetter() func() Address {
|
||||
i := 0
|
||||
return func() Address {
|
||||
s := fmt.Sprintf("address%d", i)
|
||||
i++
|
||||
newAddr, err := NewActorAddress([]byte(s))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return newAddr
|
||||
}
|
||||
}
|
431
chain/blocksync.go
Normal file
431
chain/blocksync.go
Normal file
@ -0,0 +1,431 @@
|
||||
package chain
|
||||
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"sync"
|
||||
|
||||
"github.com/ipfs/go-bitswap"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
inet "github.com/libp2p/go-libp2p-core/network"
|
||||
"github.com/libp2p/go-libp2p-peer"
|
||||
//"github.com/libp2p/go-libp2p-protocol"
|
||||
)
|
||||
|
||||
const BlockSyncProtocolID = "/fil/sync/blk/0.0.1"
|
||||
|
||||
func init() {
|
||||
cbor.RegisterCborType(BlockSyncRequest{})
|
||||
cbor.RegisterCborType(BlockSyncResponse{})
|
||||
cbor.RegisterCborType(BSTipSet{})
|
||||
}
|
||||
|
||||
type BlockSyncService struct {
|
||||
cs *ChainStore
|
||||
}
|
||||
|
||||
type BlockSyncRequest struct {
|
||||
Start []cid.Cid
|
||||
RequestLength uint64
|
||||
|
||||
Options uint64
|
||||
}
|
||||
|
||||
type BSOptions struct {
|
||||
IncludeBlocks bool
|
||||
IncludeMessages bool
|
||||
}
|
||||
|
||||
func ParseBSOptions(optfield uint64) *BSOptions {
|
||||
return &BSOptions{
|
||||
IncludeBlocks: optfield&(BSOptBlocks) != 0,
|
||||
IncludeMessages: optfield&(BSOptMessages) != 0,
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
BSOptBlocks = 1 << 0
|
||||
BSOptMessages = 1 << 1
|
||||
)
|
||||
|
||||
type BlockSyncResponse struct {
|
||||
Chain []*BSTipSet
|
||||
|
||||
Status uint
|
||||
Message string
|
||||
}
|
||||
|
||||
type BSTipSet struct {
|
||||
Blocks []*BlockHeader
|
||||
|
||||
Messages []*SignedMessage
|
||||
MsgIncludes [][]int
|
||||
}
|
||||
|
||||
func NewBlockSyncService(cs *ChainStore) *BlockSyncService {
|
||||
return &BlockSyncService{
|
||||
cs: cs,
|
||||
}
|
||||
}
|
||||
|
||||
func (bss *BlockSyncService) HandleStream(s inet.Stream) {
|
||||
defer s.Close()
|
||||
log.Error("handling block sync request")
|
||||
|
||||
var req BlockSyncRequest
|
||||
if err := ReadCborRPC(bufio.NewReader(s), &req); err != nil {
|
||||
log.Errorf("failed to read block sync request: %s", err)
|
||||
return
|
||||
}
|
||||
log.Errorf("block sync request for: %s %d", req.Start, req.RequestLength)
|
||||
|
||||
resp, err := bss.processRequest(&req)
|
||||
if err != nil {
|
||||
log.Error("failed to process block sync request: ", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := WriteCborRPC(s, resp); err != nil {
|
||||
log.Error("failed to write back response for handle stream: ", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (bss *BlockSyncService) processRequest(req *BlockSyncRequest) (*BlockSyncResponse, error) {
|
||||
opts := ParseBSOptions(req.Options)
|
||||
chain, err := bss.collectChainSegment(req.Start, req.RequestLength, opts)
|
||||
if err != nil {
|
||||
log.Error("encountered error while responding to block sync request: ", err)
|
||||
return &BlockSyncResponse{
|
||||
Status: 203,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &BlockSyncResponse{
|
||||
Chain: chain,
|
||||
Status: 0,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (bss *BlockSyncService) collectChainSegment(start []cid.Cid, length uint64, opts *BSOptions) ([]*BSTipSet, error) {
|
||||
var bstips []*BSTipSet
|
||||
cur := start
|
||||
for {
|
||||
var bst BSTipSet
|
||||
ts, err := bss.cs.LoadTipSet(cur)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if opts.IncludeMessages {
|
||||
log.Error("INCLUDING MESSAGES IN SYNC RESPONSE")
|
||||
msgs, mincl, err := bss.gatherMessages(ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Errorf("messages: ", msgs)
|
||||
|
||||
bst.Messages = msgs
|
||||
bst.MsgIncludes = mincl
|
||||
}
|
||||
|
||||
if opts.IncludeBlocks {
|
||||
log.Error("INCLUDING BLOCKS IN SYNC RESPONSE")
|
||||
bst.Blocks = ts.Blocks()
|
||||
}
|
||||
|
||||
bstips = append(bstips, &bst)
|
||||
|
||||
if uint64(len(bstips)) >= length || ts.Height() == 0 {
|
||||
return bstips, nil
|
||||
}
|
||||
|
||||
cur = ts.Parents()
|
||||
}
|
||||
}
|
||||
|
||||
func (bss *BlockSyncService) gatherMessages(ts *TipSet) ([]*SignedMessage, [][]int, error) {
|
||||
msgmap := make(map[cid.Cid]int)
|
||||
var allmsgs []*SignedMessage
|
||||
var msgincl [][]int
|
||||
|
||||
for _, b := range ts.Blocks() {
|
||||
msgs, err := bss.cs.MessagesForBlock(b)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
log.Errorf("MESSAGES FOR BLOCK: %d", len(msgs))
|
||||
|
||||
msgindexes := make([]int, 0, len(msgs))
|
||||
for _, m := range msgs {
|
||||
i, ok := msgmap[m.Cid()]
|
||||
if !ok {
|
||||
i = len(allmsgs)
|
||||
allmsgs = append(allmsgs, m)
|
||||
msgmap[m.Cid()] = i
|
||||
}
|
||||
|
||||
msgindexes = append(msgindexes, i)
|
||||
}
|
||||
msgincl = append(msgincl, msgindexes)
|
||||
}
|
||||
|
||||
return allmsgs, msgincl, nil
|
||||
}
|
||||
|
||||
type BlockSync struct {
|
||||
bswap *bitswap.Bitswap
|
||||
newStream NewStreamFunc
|
||||
|
||||
syncPeersLk sync.Mutex
|
||||
syncPeers map[peer.ID]struct{}
|
||||
}
|
||||
|
||||
func NewBlockSyncClient(bswap *bitswap.Bitswap, newStreamF NewStreamFunc) *BlockSync {
|
||||
return &BlockSync{
|
||||
bswap: bswap,
|
||||
newStream: newStreamF,
|
||||
syncPeers: make(map[peer.ID]struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BlockSync) getPeers() []peer.ID {
|
||||
bs.syncPeersLk.Lock()
|
||||
defer bs.syncPeersLk.Unlock()
|
||||
var out []peer.ID
|
||||
for p := range bs.syncPeers {
|
||||
out = append(out, p)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (bs *BlockSync) GetBlocks(ctx context.Context, tipset []cid.Cid, count int) ([]*TipSet, error) {
|
||||
peers := bs.getPeers()
|
||||
perm := rand.Perm(len(peers))
|
||||
// TODO: round robin through these peers on error
|
||||
|
||||
req := &BlockSyncRequest{
|
||||
Start: tipset,
|
||||
RequestLength: uint64(count),
|
||||
Options: BSOptBlocks,
|
||||
}
|
||||
|
||||
res, err := bs.sendRequestToPeer(ctx, peers[perm[0]], req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch res.Status {
|
||||
case 0: // Success
|
||||
return bs.processBlocksResponse(req, res)
|
||||
case 101: // Partial Response
|
||||
panic("not handled")
|
||||
case 201: // req.Start not found
|
||||
return nil, fmt.Errorf("not found")
|
||||
case 202: // Go Away
|
||||
panic("not handled")
|
||||
case 203: // Internal Error
|
||||
return nil, fmt.Errorf("block sync peer errored: %s", res.Message)
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognized response code")
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BlockSync) GetFullTipSet(ctx context.Context, p peer.ID, h []cid.Cid) (*FullTipSet, error) {
|
||||
// TODO: round robin through these peers on error
|
||||
|
||||
req := &BlockSyncRequest{
|
||||
Start: h,
|
||||
RequestLength: 1,
|
||||
Options: BSOptBlocks | BSOptMessages,
|
||||
}
|
||||
|
||||
res, err := bs.sendRequestToPeer(ctx, p, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch res.Status {
|
||||
case 0: // Success
|
||||
if len(res.Chain) == 0 {
|
||||
return nil, fmt.Errorf("got zero length chain response")
|
||||
}
|
||||
bts := res.Chain[0]
|
||||
|
||||
return bstsToFullTipSet(bts)
|
||||
case 101: // Partial Response
|
||||
panic("not handled")
|
||||
case 201: // req.Start not found
|
||||
return nil, fmt.Errorf("not found")
|
||||
case 202: // Go Away
|
||||
panic("not handled")
|
||||
case 203: // Internal Error
|
||||
return nil, fmt.Errorf("block sync peer errored: %s", res.Message)
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognized response code")
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BlockSync) GetChainMessages(ctx context.Context, h *TipSet, count uint64) ([]*BSTipSet, error) {
|
||||
peers := bs.getPeers()
|
||||
perm := rand.Perm(len(peers))
|
||||
// TODO: round robin through these peers on error
|
||||
|
||||
req := &BlockSyncRequest{
|
||||
Start: h.Cids(),
|
||||
RequestLength: count,
|
||||
Options: BSOptMessages,
|
||||
}
|
||||
|
||||
res, err := bs.sendRequestToPeer(ctx, peers[perm[0]], req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch res.Status {
|
||||
case 0: // Success
|
||||
return res.Chain, nil
|
||||
case 101: // Partial Response
|
||||
panic("not handled")
|
||||
case 201: // req.Start not found
|
||||
return nil, fmt.Errorf("not found")
|
||||
case 202: // Go Away
|
||||
panic("not handled")
|
||||
case 203: // Internal Error
|
||||
return nil, fmt.Errorf("block sync peer errored: %s", res.Message)
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognized response code")
|
||||
}
|
||||
}
|
||||
|
||||
func bstsToFullTipSet(bts *BSTipSet) (*FullTipSet, error) {
|
||||
fts := &FullTipSet{}
|
||||
for i, b := range bts.Blocks {
|
||||
fb := &FullBlock{
|
||||
Header: b,
|
||||
}
|
||||
for _, mi := range bts.MsgIncludes[i] {
|
||||
fb.Messages = append(fb.Messages, bts.Messages[mi])
|
||||
}
|
||||
fts.Blocks = append(fts.Blocks, fb)
|
||||
}
|
||||
|
||||
return fts, nil
|
||||
}
|
||||
|
||||
func (bs *BlockSync) sendRequestToPeer(ctx context.Context, p peer.ID, req *BlockSyncRequest) (*BlockSyncResponse, error) {
|
||||
s, err := bs.newStream(inet.WithNoDial(ctx, "should already have connection"), p, BlockSyncProtocolID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteCborRPC(s, req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var res BlockSyncResponse
|
||||
if err := ReadCborRPC(bufio.NewReader(s), &res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func (bs *BlockSync) processBlocksResponse(req *BlockSyncRequest, res *BlockSyncResponse) ([]*TipSet, error) {
|
||||
cur, err := NewTipSet(res.Chain[0].Blocks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := []*TipSet{cur}
|
||||
for bi := 1; bi < len(res.Chain); bi++ {
|
||||
next := res.Chain[bi].Blocks
|
||||
nts, err := NewTipSet(next)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !cidArrsEqual(cur.Parents(), nts.Cids()) {
|
||||
return nil, fmt.Errorf("parents of tipset[%d] were not tipset[%d]", bi-1, bi)
|
||||
}
|
||||
|
||||
out = append(out, nts)
|
||||
cur = nts
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func cidArrsEqual(a, b []cid.Cid) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i, v := range a {
|
||||
if b[i] != v {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (bs *BlockSync) GetBlock(ctx context.Context, c cid.Cid) (*BlockHeader, error) {
|
||||
sb, err := bs.bswap.GetBlock(ctx, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return DecodeBlock(sb.RawData())
|
||||
}
|
||||
|
||||
func (bs *BlockSync) AddPeer(p peer.ID) {
|
||||
bs.syncPeersLk.Lock()
|
||||
defer bs.syncPeersLk.Unlock()
|
||||
bs.syncPeers[p] = struct{}{}
|
||||
}
|
||||
|
||||
func (bs *BlockSync) FetchMessagesByCids(cids []cid.Cid) ([]*SignedMessage, error) {
|
||||
out := make([]*SignedMessage, len(cids))
|
||||
|
||||
resp, err := bs.bswap.GetBlocks(context.TODO(), cids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m := make(map[cid.Cid]int)
|
||||
for i, c := range cids {
|
||||
m[c] = i
|
||||
}
|
||||
|
||||
for i := 0; i < len(cids); i++ {
|
||||
select {
|
||||
case v, ok := <-resp:
|
||||
if !ok {
|
||||
if i == len(cids)-1 {
|
||||
break
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("failed to fetch all messages")
|
||||
}
|
||||
|
||||
sm, err := DecodeSignedMessage(v.RawData())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ix, ok := m[sm.Cid()]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("received message we didnt ask for")
|
||||
}
|
||||
|
||||
if out[ix] != nil {
|
||||
return nil, fmt.Errorf("received duplicate message")
|
||||
}
|
||||
|
||||
out[ix] = sm
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
117
chain/buf_bstore.go
Normal file
117
chain/buf_bstore.go
Normal file
@ -0,0 +1,117 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
block "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
ds "github.com/ipfs/go-datastore"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
)
|
||||
|
||||
type BufferedBS struct {
|
||||
read bstore.Blockstore
|
||||
write bstore.Blockstore
|
||||
}
|
||||
|
||||
func NewBufferedBstore(base bstore.Blockstore) *BufferedBS {
|
||||
buf := bstore.NewBlockstore(ds.NewMapDatastore())
|
||||
return &BufferedBS{
|
||||
read: base,
|
||||
write: buf,
|
||||
}
|
||||
}
|
||||
|
||||
var _ (bstore.Blockstore) = &BufferedBS{}
|
||||
|
||||
func (bs *BufferedBS) AllKeysChan(ctx context.Context) (<-chan cid.Cid, error) {
|
||||
a, err := bs.read.AllKeysChan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err := bs.write.AllKeysChan(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := make(chan cid.Cid)
|
||||
go func() {
|
||||
defer close(out)
|
||||
for a != nil || b != nil {
|
||||
select {
|
||||
case val, ok := <-a:
|
||||
if !ok {
|
||||
a = nil
|
||||
} else {
|
||||
select {
|
||||
case out <- val:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
case val, ok := <-b:
|
||||
if !ok {
|
||||
b = nil
|
||||
} else {
|
||||
select {
|
||||
case out <- val:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (bs *BufferedBS) DeleteBlock(c cid.Cid) error {
|
||||
if err := bs.read.DeleteBlock(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return bs.write.DeleteBlock(c)
|
||||
}
|
||||
|
||||
func (bs *BufferedBS) Get(c cid.Cid) (block.Block, error) {
|
||||
if out, err := bs.read.Get(c); err != nil {
|
||||
if err != bstore.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
return bs.write.Get(c)
|
||||
}
|
||||
|
||||
func (bs *BufferedBS) GetSize(c cid.Cid) (int, error) {
|
||||
panic("nyi")
|
||||
}
|
||||
|
||||
func (bs *BufferedBS) Put(blk block.Block) error {
|
||||
return bs.write.Put(blk)
|
||||
}
|
||||
|
||||
func (bs *BufferedBS) Has(c cid.Cid) (bool, error) {
|
||||
has, err := bs.read.Has(c)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if has {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return bs.write.Has(c)
|
||||
}
|
||||
|
||||
func (bs *BufferedBS) HashOnRead(hor bool) {
|
||||
bs.read.HashOnRead(hor)
|
||||
bs.write.HashOnRead(hor)
|
||||
}
|
||||
|
||||
func (bs *BufferedBS) PutMany(blks []block.Block) error {
|
||||
return bs.write.PutMany(blks)
|
||||
}
|
459
chain/chain.go
Normal file
459
chain/chain.go
Normal file
@ -0,0 +1,459 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"sync"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
datastore "github.com/ipfs/go-datastore"
|
||||
dstore "github.com/ipfs/go-datastore"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
logging "github.com/ipfs/go-log"
|
||||
"github.com/pkg/errors"
|
||||
sharray "github.com/whyrusleeping/sharray"
|
||||
pubsub "github.com/whyrusleeping/pubsub"
|
||||
)
|
||||
|
||||
const ForkLengthThreshold = 20
|
||||
|
||||
var log = logging.Logger("f2")
|
||||
|
||||
type GenesisBootstrap struct {
|
||||
Genesis *BlockHeader
|
||||
MinerKey address.Address
|
||||
}
|
||||
|
||||
func SetupInitActor(bs bstore.Blockstore, addrs []address.Address) (*Actor, error) {
|
||||
var ias InitActorState
|
||||
ias.NextID = 100
|
||||
|
||||
cst := hamt.CSTFromBstore(bs)
|
||||
amap := hamt.NewNode(cst)
|
||||
|
||||
for i, a := range addrs {
|
||||
if err := amap.Set(context.TODO(), string(a.Bytes()), 100+uint64(i)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
ias.NextID += uint64(len(addrs))
|
||||
if err := amap.Flush(context.TODO()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
amapcid, err := cst.Put(context.TODO(), amap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ias.AddressMap = amapcid
|
||||
|
||||
statecid, err := cst.Put(context.TODO(), &ias)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
act := &Actor{
|
||||
Code: InitActorCodeCid,
|
||||
Head: statecid,
|
||||
}
|
||||
|
||||
return act, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
bs := bstore.NewBlockstore(dstore.NewMapDatastore())
|
||||
cst := hamt.CSTFromBstore(bs)
|
||||
emptyobject, err := cst.Put(context.TODO(), map[string]string{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
EmptyObjectCid = emptyobject
|
||||
}
|
||||
|
||||
var EmptyObjectCid cid.Cid
|
||||
|
||||
func MakeGenesisBlock(bs bstore.Blockstore, w *Wallet) (*GenesisBootstrap, error) {
|
||||
cst := hamt.CSTFromBstore(bs)
|
||||
state, err := NewStateTree(cst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
emptyobject, err := cst.Put(context.TODO(), map[string]string{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
minerAddr, err := w.GenerateKey(KTSecp256k1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
initact, err := SetupInitActor(bs, []address.Address{minerAddr})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := state.SetActor(InitActorAddress, initact); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = state.SetActor(NetworkAddress, &Actor{
|
||||
Code: AccountActorCodeCid,
|
||||
Balance: NewInt(100000000000),
|
||||
Head: emptyobject,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = state.SetActor(minerAddr, &Actor{
|
||||
Code: AccountActorCodeCid,
|
||||
Balance: NewInt(5000000),
|
||||
Head: emptyobject,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println("about to flush state...")
|
||||
|
||||
stateroot, err := state.Flush()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println("at end of make genesis block")
|
||||
|
||||
emptyroot, err := sharray.Build(context.TODO(), 4, []interface{}{}, cst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fmt.Println("Empty genesis root: ", emptyroot)
|
||||
|
||||
b := &BlockHeader{
|
||||
Miner: InitActorAddress,
|
||||
Tickets: []Ticket{},
|
||||
ElectionProof: []byte("the genesis block"),
|
||||
Parents: []cid.Cid{},
|
||||
Height: 0,
|
||||
ParentWeight: NewInt(0),
|
||||
StateRoot: stateroot,
|
||||
Messages: emptyroot,
|
||||
MessageReceipts: emptyroot,
|
||||
}
|
||||
|
||||
sb, err := b.ToStorageBlock()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := bs.Put(sb); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &GenesisBootstrap{
|
||||
Genesis: b,
|
||||
MinerKey: minerAddr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type ChainStore struct {
|
||||
bs bstore.Blockstore
|
||||
ds datastore.Datastore
|
||||
|
||||
heaviestLk sync.Mutex
|
||||
heaviest *TipSet
|
||||
|
||||
bestTips *pubsub.PubSub
|
||||
|
||||
headChange func(rev, app []*TipSet) error
|
||||
}
|
||||
|
||||
func NewChainStore(bs bstore.Blockstore, ds datastore.Datastore) *ChainStore {
|
||||
return &ChainStore{
|
||||
bs: bs,
|
||||
ds: ds,
|
||||
bestTips: pubsub.New(64),
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ChainStore) SubNewTips() chan interface{} {
|
||||
return cs.bestTips.Sub("best")
|
||||
}
|
||||
|
||||
func (cs *ChainStore) SetGenesis(b *BlockHeader) error {
|
||||
gents, err := NewTipSet([]*BlockHeader{b})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fts := &FullTipSet{
|
||||
Blocks: []*FullBlock{
|
||||
{Header: b},
|
||||
},
|
||||
}
|
||||
|
||||
cs.heaviest = gents
|
||||
|
||||
if err := cs.PutTipSet(fts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return cs.ds.Put(datastore.NewKey("0"), b.Cid().Bytes())
|
||||
}
|
||||
|
||||
func (cs *ChainStore) PutTipSet(ts *FullTipSet) error {
|
||||
for _, b := range ts.Blocks {
|
||||
if err := cs.persistBlock(b); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cs.maybeTakeHeavierTipSet(ts.TipSet())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) maybeTakeHeavierTipSet(ts *TipSet) error {
|
||||
cs.heaviestLk.Lock()
|
||||
defer cs.heaviestLk.Unlock()
|
||||
if cs.heaviest == nil || cs.Weight(ts) > cs.Weight(cs.heaviest) {
|
||||
revert, apply, err := cs.ReorgOps(cs.heaviest, ts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cs.headChange(revert, apply)
|
||||
log.Errorf("New heaviest tipset! %s", ts.Cids())
|
||||
cs.heaviest = ts
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) Contains(ts *TipSet) (bool, error) {
|
||||
for _, c := range ts.cids {
|
||||
has, err := cs.bs.Has(c)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if !has {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetBlock(c cid.Cid) (*BlockHeader, error) {
|
||||
sb, err := cs.bs.Get(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return DecodeBlock(sb.RawData())
|
||||
}
|
||||
|
||||
func (cs *ChainStore) LoadTipSet(cids []cid.Cid) (*TipSet, error) {
|
||||
var blks []*BlockHeader
|
||||
for _, c := range cids {
|
||||
b, err := cs.GetBlock(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blks = append(blks, b)
|
||||
}
|
||||
|
||||
return NewTipSet(blks)
|
||||
}
|
||||
|
||||
// returns true if 'a' is an ancestor of 'b'
|
||||
func (cs *ChainStore) IsAncestorOf(a, b *TipSet) (bool, error) {
|
||||
if b.Height() <= a.Height() {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
cur := b
|
||||
for !a.Equals(cur) && cur.Height() > a.Height() {
|
||||
next, err := cs.LoadTipSet(b.Parents())
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
cur = next
|
||||
}
|
||||
|
||||
return cur.Equals(a), nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) NearestCommonAncestor(a, b *TipSet) (*TipSet, error) {
|
||||
l, _, err := cs.ReorgOps(a, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cs.LoadTipSet(l[len(l)-1].Parents())
|
||||
}
|
||||
|
||||
func (cs *ChainStore) ReorgOps(a, b *TipSet) ([]*TipSet, []*TipSet, error) {
|
||||
left := a
|
||||
right := b
|
||||
|
||||
var leftChain, rightChain []*TipSet
|
||||
for !left.Equals(right) {
|
||||
if left.Height() > right.Height() {
|
||||
leftChain = append(leftChain, left)
|
||||
par, err := cs.LoadTipSet(left.Parents())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
left = par
|
||||
} else {
|
||||
rightChain = append(rightChain, right)
|
||||
par, err := cs.LoadTipSet(right.Parents())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
right = par
|
||||
}
|
||||
}
|
||||
|
||||
return leftChain, rightChain, nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) Weight(ts *TipSet) uint64 {
|
||||
return ts.Blocks()[0].ParentWeight.Uint64() + uint64(len(ts.Cids()))
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetHeaviestTipSet() *TipSet {
|
||||
cs.heaviestLk.Lock()
|
||||
defer cs.heaviestLk.Unlock()
|
||||
return cs.heaviest
|
||||
}
|
||||
|
||||
func (cs *ChainStore) persistBlockHeader(b *BlockHeader) error {
|
||||
sb, err := b.ToStorageBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return cs.bs.Put(sb)
|
||||
}
|
||||
|
||||
func (cs *ChainStore) persistBlock(b *FullBlock) error {
|
||||
if err := cs.persistBlockHeader(b.Header); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, m := range b.Messages {
|
||||
if err := cs.PutMessage(m); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) PutMessage(m *SignedMessage) error {
|
||||
sb, err := m.ToStorageBlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return cs.bs.Put(sb)
|
||||
}
|
||||
|
||||
func (cs *ChainStore) AddBlock(b *BlockHeader) error {
|
||||
if err := cs.persistBlockHeader(b); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ts, _ := NewTipSet([]*BlockHeader{b})
|
||||
cs.maybeTakeHeavierTipSet(ts)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetGenesis() (*BlockHeader, error) {
|
||||
data, err := cs.ds.Get(datastore.NewKey("0"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := cid.Cast(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
genb, err := cs.bs.Get(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return DecodeBlock(genb.RawData())
|
||||
}
|
||||
|
||||
func (cs *ChainStore) TipSetState(cids []cid.Cid) (cid.Cid, error) {
|
||||
ts, err := cs.LoadTipSet(cids)
|
||||
if err != nil {
|
||||
log.Error("failed loading tipset: ", cids)
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
if len(ts.Blocks()) == 1 {
|
||||
return ts.Blocks()[0].StateRoot, nil
|
||||
}
|
||||
|
||||
panic("cant handle multiblock tipsets yet")
|
||||
|
||||
}
|
||||
|
||||
func (cs *ChainStore) GetMessage(c cid.Cid) (*SignedMessage, error) {
|
||||
sb, err := cs.bs.Get(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return DecodeSignedMessage(sb.RawData())
|
||||
}
|
||||
|
||||
func (cs *ChainStore) MessagesForBlock(b *BlockHeader) ([]*SignedMessage, error) {
|
||||
cst := hamt.CSTFromBstore(cs.bs)
|
||||
shar, err := sharray.Load(context.TODO(), b.Messages, 4, cst)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "sharray load")
|
||||
}
|
||||
|
||||
var cids []cid.Cid
|
||||
err = shar.ForEach(context.TODO(), func(i interface{}) error {
|
||||
c, ok := i.(cid.Cid)
|
||||
if !ok {
|
||||
return fmt.Errorf("value in message sharray was not a cid")
|
||||
}
|
||||
|
||||
cids = append(cids, c)
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cs.LoadMessagesFromCids(cids)
|
||||
}
|
||||
|
||||
func (cs *ChainStore) LoadMessagesFromCids(cids []cid.Cid) ([]*SignedMessage, error) {
|
||||
msgs := make([]*SignedMessage, 0, len(cids))
|
||||
for _, c := range cids {
|
||||
m, err := cs.GetMessage(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
msgs = append(msgs, m)
|
||||
}
|
||||
|
||||
return msgs, nil
|
||||
}
|
||||
|
256
chain/statetree.go
Normal file
256
chain/statetree.go
Normal file
@ -0,0 +1,256 @@
|
||||
package chain
|
||||
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
)
|
||||
|
||||
var ErrActorNotFound = fmt.Errorf("actor not found")
|
||||
|
||||
type StateTree struct {
|
||||
root *hamt.Node
|
||||
store *hamt.CborIpldStore
|
||||
|
||||
actorcache map[address.Address]*Actor
|
||||
snapshot cid.Cid
|
||||
}
|
||||
|
||||
func NewStateTree(cst *hamt.CborIpldStore) (*StateTree, error) {
|
||||
return &StateTree{
|
||||
root: hamt.NewNode(cst),
|
||||
store: cst,
|
||||
actorcache: make(map[address.Address]*Actor),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func LoadStateTree(cst *hamt.CborIpldStore, c cid.Cid) (*StateTree, error) {
|
||||
nd, err := hamt.LoadNode(context.Background(), cst, c)
|
||||
if err != nil {
|
||||
log.Errorf("loading hamt node failed: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &StateTree{
|
||||
root: nd,
|
||||
store: cst,
|
||||
actorcache: make(map[address.Address]*Actor),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (st *StateTree) SetActor(addr address.Address, act *Actor) error {
|
||||
if addr.Protocol() != address.ID {
|
||||
iaddr, err := st.lookupID(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
addr = iaddr
|
||||
}
|
||||
|
||||
cact, ok := st.actorcache[addr]
|
||||
if ok {
|
||||
if act == cact {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return st.root.Set(context.TODO(), string(addr.Bytes()), act)
|
||||
}
|
||||
|
||||
func (st *StateTree) lookupID(addr address.Address) (address.Address, error) {
|
||||
act, err := st.GetActor(InitActorAddress)
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
var ias InitActorState
|
||||
if err := st.store.Get(context.TODO(), act.Head, &ias); err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
return ias.Lookup(st.store, addr)
|
||||
}
|
||||
|
||||
func (st *StateTree) GetActor(addr address.Address) (*Actor, error) {
|
||||
if addr.Protocol() != address.ID {
|
||||
iaddr, err := st.lookupID(addr)
|
||||
if err != nil {
|
||||
if err == hamt.ErrNotFound {
|
||||
return nil, ErrActorNotFound
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
addr = iaddr
|
||||
}
|
||||
|
||||
cact, ok := st.actorcache[addr]
|
||||
if ok {
|
||||
return cact, nil
|
||||
}
|
||||
|
||||
thing, err := st.root.Find(context.TODO(), string(addr.Bytes()))
|
||||
if err != nil {
|
||||
if err == hamt.ErrNotFound {
|
||||
return nil, ErrActorNotFound
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var act Actor
|
||||
badout, err := cbor.DumpObject(thing)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := cbor.DecodeInto(badout, &act); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
st.actorcache[addr] = &act
|
||||
|
||||
return &act, nil
|
||||
}
|
||||
|
||||
func (st *StateTree) Flush() (cid.Cid, error) {
|
||||
for addr, act := range st.actorcache {
|
||||
if err := st.root.Set(context.TODO(), string(addr.Bytes()), act); err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
}
|
||||
st.actorcache = make(map[address.Address]*Actor)
|
||||
|
||||
if err := st.root.Flush(context.TODO()); err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
return st.store.Put(context.TODO(), st.root)
|
||||
}
|
||||
|
||||
func (st *StateTree) Snapshot() error {
|
||||
ss, err := st.Flush()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st.snapshot = ss
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *StateTree) RegisterNewAddress(addr address.Address, act *Actor) (address.Address, error) {
|
||||
var out address.Address
|
||||
err := st.MutateActor(InitActorAddress, func(initact *Actor) error {
|
||||
var ias InitActorState
|
||||
if err := st.store.Get(context.TODO(), initact.Head, &ias); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fvm := &VMContext{cst: st.store}
|
||||
oaddr, err := ias.AddActor(fvm, addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out = oaddr
|
||||
|
||||
ncid, err := st.store.Put(context.TODO(), &ias)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
initact.Head = ncid
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
if err := st.SetActor(out, act); err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (st *StateTree) Revert() error {
|
||||
nd, err := hamt.LoadNode(context.Background(), st.store, st.snapshot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
st.root = nd
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *StateTree) MutateActor(addr address.Address, f func(*Actor) error) error {
|
||||
act, err := st.GetActor(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := f(act); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return st.SetActor(addr, act)
|
||||
}
|
||||
|
||||
func NewBLSAccountActor(st *StateTree, addr address.Address) (*Actor, error) {
|
||||
var acstate AccountActorState
|
||||
acstate.Address = addr
|
||||
|
||||
c, err := st.store.Put(context.TODO(), acstate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nact := &Actor{
|
||||
Code: AccountActorCodeCid,
|
||||
Balance: NewInt(0),
|
||||
Head: c,
|
||||
}
|
||||
|
||||
return nact, nil
|
||||
}
|
||||
|
||||
func NewSecp256k1AccountActor(st *StateTree, addr address.Address) (*Actor, error) {
|
||||
nact := &Actor{
|
||||
Code: AccountActorCodeCid,
|
||||
Balance: NewInt(0),
|
||||
Head: EmptyObjectCid,
|
||||
}
|
||||
|
||||
return nact, nil
|
||||
}
|
||||
|
||||
func TryCreateAccountActor(st *StateTree, addr address.Address) (*Actor, error) {
|
||||
act, err := makeActor(st, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = st.RegisterNewAddress(addr, act)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return act, nil
|
||||
}
|
||||
|
||||
func makeActor(st *StateTree, addr address.Address) (*Actor, error) {
|
||||
switch addr.Protocol() {
|
||||
case address.BLS:
|
||||
return NewBLSAccountActor(st, addr)
|
||||
case address.SECP256K1:
|
||||
return NewSecp256k1AccountActor(st, addr)
|
||||
case address.ID:
|
||||
return nil, fmt.Errorf("no actor with given ID")
|
||||
case address.Actor:
|
||||
return nil, fmt.Errorf("no such actor")
|
||||
default:
|
||||
return nil, fmt.Errorf("address has unsupported protocol: %d", addr.Protocol())
|
||||
}
|
||||
}
|
696
chain/sync.go
Normal file
696
chain/sync.go
Normal file
@ -0,0 +1,696 @@
|
||||
package chain
|
||||
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/ipfs/go-cid"
|
||||
dstore "github.com/ipfs/go-datastore"
|
||||
"github.com/ipfs/go-hamt-ipld"
|
||||
bstore "github.com/ipfs/go-ipfs-blockstore"
|
||||
peer "github.com/libp2p/go-libp2p-peer"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/whyrusleeping/sharray"
|
||||
)
|
||||
|
||||
type Syncer struct {
|
||||
// The heaviest known tipset in the network.
|
||||
head *TipSet
|
||||
|
||||
// The interface for accessing and putting tipsets into local storage
|
||||
store *ChainStore
|
||||
|
||||
// The known genesis tipset
|
||||
genesis *TipSet
|
||||
|
||||
// the current mode the syncer is in
|
||||
syncMode SyncMode
|
||||
|
||||
syncLock sync.Mutex
|
||||
|
||||
// TipSets known to be invalid
|
||||
bad BadTipSetCache
|
||||
|
||||
// handle to the block sync service
|
||||
bsync *BlockSync
|
||||
|
||||
// peer heads
|
||||
// Note: clear cache on disconnects
|
||||
peerHeads map[peer.ID]*TipSet
|
||||
peerHeadsLk sync.Mutex
|
||||
}
|
||||
|
||||
func NewSyncer(cs *ChainStore, bsync *BlockSync) (*Syncer, error) {
|
||||
gen, err := cs.GetGenesis()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gent, err := NewTipSet([]*BlockHeader{gen})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Syncer{
|
||||
syncMode: Bootstrap,
|
||||
genesis: gent,
|
||||
bsync: bsync,
|
||||
peerHeads: make(map[peer.ID]*TipSet),
|
||||
head: cs.GetHeaviestTipSet(),
|
||||
store: cs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type SyncMode int
|
||||
|
||||
const (
|
||||
Unknown = SyncMode(iota)
|
||||
Bootstrap
|
||||
CaughtUp
|
||||
)
|
||||
|
||||
type BadTipSetCache struct {
|
||||
badBlocks map[cid.Cid]struct{}
|
||||
}
|
||||
|
||||
type BlockSet struct {
|
||||
tset map[uint64]*TipSet
|
||||
head *TipSet
|
||||
}
|
||||
|
||||
func (bs *BlockSet) Insert(ts *TipSet) {
|
||||
if bs.tset == nil {
|
||||
bs.tset = make(map[uint64]*TipSet)
|
||||
}
|
||||
|
||||
if bs.head == nil || ts.Height() > bs.head.Height() {
|
||||
bs.head = ts
|
||||
}
|
||||
bs.tset[ts.Height()] = ts
|
||||
}
|
||||
|
||||
func (bs *BlockSet) GetByHeight(h uint64) *TipSet {
|
||||
return bs.tset[h]
|
||||
}
|
||||
|
||||
func (bs *BlockSet) PersistTo(cs *ChainStore) error {
|
||||
for _, ts := range bs.tset {
|
||||
for _, b := range ts.Blocks() {
|
||||
if err := cs.persistBlockHeader(b); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bs *BlockSet) Head() *TipSet {
|
||||
return bs.head
|
||||
}
|
||||
|
||||
const BootstrapPeerThreshold = 1
|
||||
|
||||
// InformNewHead informs the syncer about a new potential tipset
|
||||
// This should be called when connecting to new peers, and additionally
|
||||
// when receiving new blocks from the network
|
||||
func (syncer *Syncer) InformNewHead(from peer.ID, fts *FullTipSet) {
|
||||
if fts == nil {
|
||||
panic("bad")
|
||||
}
|
||||
syncer.peerHeadsLk.Lock()
|
||||
syncer.peerHeads[from] = fts.TipSet()
|
||||
syncer.peerHeadsLk.Unlock()
|
||||
syncer.bsync.AddPeer(from)
|
||||
|
||||
go func() {
|
||||
syncer.syncLock.Lock()
|
||||
defer syncer.syncLock.Unlock()
|
||||
|
||||
switch syncer.syncMode {
|
||||
case Bootstrap:
|
||||
syncer.SyncBootstrap()
|
||||
case CaughtUp:
|
||||
if err := syncer.SyncCaughtUp(fts); err != nil {
|
||||
log.Errorf("sync error: %s", err)
|
||||
}
|
||||
case Unknown:
|
||||
panic("invalid syncer state")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (syncer *Syncer) GetPeers() []peer.ID {
|
||||
syncer.peerHeadsLk.Lock()
|
||||
defer syncer.peerHeadsLk.Unlock()
|
||||
var out []peer.ID
|
||||
for p, _ := range syncer.peerHeads {
|
||||
out = append(out, p)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func (syncer *Syncer) InformNewBlock(from peer.ID, blk *FullBlock) {
|
||||
// TODO: search for other blocks that could form a tipset with this block
|
||||
// and then send that tipset to InformNewHead
|
||||
|
||||
fts := &FullTipSet{Blocks: []*FullBlock{blk}}
|
||||
syncer.InformNewHead(from, fts)
|
||||
}
|
||||
|
||||
// SyncBootstrap is used to synchronise your chain when first joining
|
||||
// the network, or when rejoining after significant downtime.
|
||||
func (syncer *Syncer) SyncBootstrap() {
|
||||
fmt.Println("Sync bootstrap!")
|
||||
defer fmt.Println("bye bye sync bootstrap")
|
||||
ctx := context.Background()
|
||||
|
||||
if syncer.syncMode == CaughtUp {
|
||||
log.Errorf("Called SyncBootstrap while in caught up mode")
|
||||
return
|
||||
}
|
||||
|
||||
selectedHead, err := syncer.selectHead(syncer.peerHeads)
|
||||
if err != nil {
|
||||
log.Error("failed to select head: ", err)
|
||||
return
|
||||
}
|
||||
|
||||
blockSet := []*TipSet{selectedHead}
|
||||
cur := selectedHead.Cids()
|
||||
for /* would be cool to have a terminating condition maybe */ {
|
||||
// NB: GetBlocks validates that the blocks are in-fact the ones we
|
||||
// requested, and that they are correctly linked to eachother. It does
|
||||
// not validate any state transitions
|
||||
fmt.Println("Get blocks: ", cur)
|
||||
blks, err := syncer.bsync.GetBlocks(context.TODO(), cur, 10)
|
||||
if err != nil {
|
||||
log.Error("failed to get blocks: ", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, b := range blks {
|
||||
blockSet = append(blockSet, b)
|
||||
}
|
||||
if blks[len(blks)-1].Height() == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
cur = blks[len(blks)-1].Parents()
|
||||
}
|
||||
|
||||
// hacks. in the case that we request X blocks starting at height X+1, we
|
||||
// won't get the genesis block in the returned blockset. This hacks around it
|
||||
if blockSet[len(blockSet)-1].Height() != 0 {
|
||||
blockSet = append(blockSet, syncer.genesis)
|
||||
}
|
||||
|
||||
blockSet = reverse(blockSet)
|
||||
|
||||
genesis := blockSet[0]
|
||||
if !genesis.Equals(syncer.genesis) {
|
||||
// TODO: handle this...
|
||||
log.Errorf("We synced to the wrong chain! %s != %s", genesis, syncer.genesis)
|
||||
return
|
||||
}
|
||||
|
||||
for _, ts := range blockSet {
|
||||
for _, b := range ts.Blocks() {
|
||||
if err := syncer.store.persistBlockHeader(b); err != nil {
|
||||
log.Errorf("failed to persist synced blocks to the chainstore: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch all the messages for all the blocks in this chain
|
||||
|
||||
windowSize := uint64(10)
|
||||
for i := uint64(0); i <= selectedHead.Height(); i += windowSize {
|
||||
bs := bstore.NewBlockstore(dstore.NewMapDatastore())
|
||||
cst := hamt.CSTFromBstore(bs)
|
||||
|
||||
nextHeight := i + windowSize - 1
|
||||
if nextHeight > selectedHead.Height() {
|
||||
nextHeight = selectedHead.Height()
|
||||
}
|
||||
|
||||
next := blockSet[nextHeight]
|
||||
bstips, err := syncer.bsync.GetChainMessages(ctx, next, (nextHeight+1)-i)
|
||||
if err != nil {
|
||||
log.Errorf("failed to fetch messages: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
for bsi := 0; bsi < len(bstips); bsi++ {
|
||||
cur := blockSet[i+uint64(bsi)]
|
||||
bstip := bstips[len(bstips)-(bsi+1)]
|
||||
fmt.Println("that loop: ", bsi, len(bstips))
|
||||
fts, err := zipTipSetAndMessages(cst, cur, bstip.Messages, bstip.MsgIncludes)
|
||||
if err != nil {
|
||||
log.Error("zipping failed: ", err, bsi, i)
|
||||
log.Error("height: ", selectedHead.Height())
|
||||
log.Error("bstips: ", bstips)
|
||||
log.Error("next height: ", nextHeight)
|
||||
return
|
||||
}
|
||||
|
||||
if err := syncer.ValidateTipSet(fts); err != nil {
|
||||
log.Errorf("failed to validate tipset: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, bst := range bstips {
|
||||
for _, m := range bst.Messages {
|
||||
if _, err := cst.Put(context.TODO(), m); err != nil {
|
||||
log.Error("failed to persist messages: ", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := copyBlockstore(bs, syncer.store.bs); err != nil {
|
||||
log.Errorf("failed to persist temp blocks: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
head := blockSet[len(blockSet)-1]
|
||||
log.Errorf("Finished syncing! new head: %s", head.Cids())
|
||||
syncer.store.maybeTakeHeavierTipSet(selectedHead)
|
||||
syncer.head = head
|
||||
syncer.syncMode = CaughtUp
|
||||
}
|
||||
|
||||
func reverse(tips []*TipSet) []*TipSet {
|
||||
out := make([]*TipSet, len(tips))
|
||||
for i := 0; i < len(tips); i++ {
|
||||
out[i] = tips[len(tips)-(i+1)]
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func copyBlockstore(from, to bstore.Blockstore) error {
|
||||
cids, err := from.AllKeysChan(context.TODO())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for c := range cids {
|
||||
b, err := from.Get(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := to.Put(b); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func zipTipSetAndMessages(cst *hamt.CborIpldStore, ts *TipSet, messages []*SignedMessage, msgincl [][]int) (*FullTipSet, error) {
|
||||
if len(ts.Blocks()) != len(msgincl) {
|
||||
return nil, fmt.Errorf("msgincl length didnt match tipset size")
|
||||
}
|
||||
fmt.Println("zipping messages: ", msgincl)
|
||||
fmt.Println("into block: ", ts.Blocks()[0].Height)
|
||||
|
||||
fts := &FullTipSet{}
|
||||
for bi, b := range ts.Blocks() {
|
||||
var msgs []*SignedMessage
|
||||
var msgCids []interface{}
|
||||
for _, m := range msgincl[bi] {
|
||||
msgs = append(msgs, messages[m])
|
||||
msgCids = append(msgCids, messages[m].Cid())
|
||||
}
|
||||
|
||||
mroot, err := sharray.Build(context.TODO(), 4, msgCids, cst)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println("messages: ", msgCids)
|
||||
fmt.Println("message root: ", b.Messages, mroot)
|
||||
if b.Messages != mroot {
|
||||
return nil, fmt.Errorf("messages didnt match message root in header")
|
||||
}
|
||||
|
||||
fb := &FullBlock{
|
||||
Header: b,
|
||||
Messages: msgs,
|
||||
}
|
||||
|
||||
fts.Blocks = append(fts.Blocks, fb)
|
||||
}
|
||||
|
||||
return fts, nil
|
||||
}
|
||||
|
||||
func (syncer *Syncer) selectHead(heads map[peer.ID]*TipSet) (*TipSet, error) {
|
||||
var headsArr []*TipSet
|
||||
for _, ts := range heads {
|
||||
headsArr = append(headsArr, ts)
|
||||
}
|
||||
|
||||
sel := headsArr[0]
|
||||
for i := 1; i < len(headsArr); i++ {
|
||||
cur := headsArr[i]
|
||||
|
||||
yes, err := syncer.store.IsAncestorOf(cur, sel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if yes {
|
||||
continue
|
||||
}
|
||||
|
||||
yes, err = syncer.store.IsAncestorOf(sel, cur)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if yes {
|
||||
sel = cur
|
||||
continue
|
||||
}
|
||||
|
||||
nca, err := syncer.store.NearestCommonAncestor(cur, sel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if sel.Height()-nca.Height() > ForkLengthThreshold {
|
||||
// TODO: handle this better than refusing to sync
|
||||
return nil, fmt.Errorf("Conflict exists in heads set")
|
||||
}
|
||||
|
||||
if syncer.store.Weight(cur) > syncer.store.Weight(sel) {
|
||||
sel = cur
|
||||
}
|
||||
}
|
||||
return sel, nil
|
||||
}
|
||||
|
||||
func (syncer *Syncer) FetchTipSet(ctx context.Context, p peer.ID, cids []cid.Cid) (*FullTipSet, error) {
|
||||
if fts, err := syncer.tryLoadFullTipSet(cids); err == nil {
|
||||
return fts, nil
|
||||
}
|
||||
|
||||
return syncer.bsync.GetFullTipSet(ctx, p, cids)
|
||||
}
|
||||
|
||||
func (syncer *Syncer) tryLoadFullTipSet(cids []cid.Cid) (*FullTipSet, error) {
|
||||
ts, err := syncer.store.LoadTipSet(cids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fts := &FullTipSet{}
|
||||
for _, b := range ts.Blocks() {
|
||||
messages, err := syncer.store.MessagesForBlock(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fb := &FullBlock{
|
||||
Header: b,
|
||||
Messages: messages,
|
||||
}
|
||||
fts.Blocks = append(fts.Blocks, fb)
|
||||
}
|
||||
|
||||
return fts, nil
|
||||
}
|
||||
|
||||
// FullTipSet is an expanded version of the TipSet that contains all the blocks and messages
|
||||
type FullTipSet struct {
|
||||
Blocks []*FullBlock
|
||||
tipset *TipSet
|
||||
cids []cid.Cid
|
||||
}
|
||||
|
||||
func NewFullTipSet(blks []*FullBlock) *FullTipSet {
|
||||
return &FullTipSet{
|
||||
Blocks: blks,
|
||||
}
|
||||
}
|
||||
|
||||
func (fts *FullTipSet) Cids() []cid.Cid {
|
||||
if fts.cids != nil {
|
||||
return fts.cids
|
||||
}
|
||||
|
||||
var cids []cid.Cid
|
||||
for _, b := range fts.Blocks {
|
||||
cids = append(cids, b.Cid())
|
||||
}
|
||||
fts.cids = cids
|
||||
|
||||
return cids
|
||||
}
|
||||
|
||||
func (fts *FullTipSet) TipSet() *TipSet {
|
||||
if fts.tipset != nil {
|
||||
return fts.tipset
|
||||
}
|
||||
|
||||
var headers []*BlockHeader
|
||||
for _, b := range fts.Blocks {
|
||||
headers = append(headers, b.Header)
|
||||
}
|
||||
|
||||
ts, err := NewTipSet(headers)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return ts
|
||||
}
|
||||
|
||||
// SyncCaughtUp is used to stay in sync once caught up to
|
||||
// the rest of the network.
|
||||
func (syncer *Syncer) SyncCaughtUp(maybeHead *FullTipSet) error {
|
||||
ts := maybeHead.TipSet()
|
||||
if syncer.genesis.Equals(ts) {
|
||||
return nil
|
||||
}
|
||||
|
||||
chain, err := syncer.collectChainCaughtUp(maybeHead)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := len(chain) - 1; i >= 0; i-- {
|
||||
ts := chain[i]
|
||||
if err := syncer.ValidateTipSet(ts); err != nil {
|
||||
return errors.Wrap(err, "validate tipset failed")
|
||||
}
|
||||
|
||||
syncer.store.PutTipSet(ts)
|
||||
}
|
||||
|
||||
if err := syncer.store.PutTipSet(maybeHead); err != nil {
|
||||
return errors.Wrap(err, "failed to put synced tipset to chainstore")
|
||||
}
|
||||
|
||||
if syncer.store.Weight(chain[0].TipSet()) > syncer.store.Weight(syncer.head) {
|
||||
fmt.Println("Accepted new head: ", chain[0].Cids())
|
||||
syncer.head = chain[0].TipSet()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (syncer *Syncer) ValidateTipSet(fts *FullTipSet) error {
|
||||
ts := fts.TipSet()
|
||||
if ts.Equals(syncer.genesis) {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, b := range fts.Blocks {
|
||||
if err := syncer.ValidateBlock(b); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (syncer *Syncer) ValidateBlock(b *FullBlock) error {
|
||||
h := b.Header
|
||||
stateroot, err := syncer.store.TipSetState(h.Parents)
|
||||
if err != nil {
|
||||
log.Error("get tipsetstate failed: ", h.Height, h.Parents, err)
|
||||
return err
|
||||
}
|
||||
baseTs, err := syncer.store.LoadTipSet(b.Header.Parents)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
vm, err := NewVM(stateroot, b.Header.Height, b.Header.Miner, syncer.store)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := vm.TransferFunds(NetworkAddress, b.Header.Miner, miningRewardForBlock(baseTs)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var receipts []interface{}
|
||||
for _, m := range b.Messages {
|
||||
receipt, err := vm.ApplyMessage(&m.Message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
receipts = append(receipts, receipt)
|
||||
}
|
||||
|
||||
cst := hamt.CSTFromBstore(syncer.store.bs)
|
||||
recptRoot, err := sharray.Build(context.TODO(), 4, receipts, cst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if recptRoot != b.Header.MessageReceipts {
|
||||
return fmt.Errorf("receipts mismatched")
|
||||
}
|
||||
|
||||
final, err := vm.Flush(context.TODO())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.Header.StateRoot != final {
|
||||
return fmt.Errorf("final state root does not match block")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func DeductFunds(act *Actor, amt BigInt) error {
|
||||
if BigCmp(act.Balance, amt) < 0 {
|
||||
return fmt.Errorf("not enough funds")
|
||||
}
|
||||
|
||||
act.Balance = BigSub(act.Balance, amt)
|
||||
return nil
|
||||
}
|
||||
|
||||
func DepositFunds(act *Actor, amt BigInt) {
|
||||
act.Balance = BigAdd(act.Balance, amt)
|
||||
}
|
||||
|
||||
func TryCreateAccountActor(st *StateTree, addr address.Address) (*Actor, error) {
|
||||
act, err := makeActor(st, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = st.RegisterNewAddress(addr, act)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return act, nil
|
||||
}
|
||||
|
||||
func makeActor(st *StateTree, addr address.Address) (*Actor, error) {
|
||||
switch addr.Protocol() {
|
||||
case address.BLS:
|
||||
return NewBLSAccountActor(st, addr)
|
||||
case address.SECP256K1:
|
||||
return NewSecp256k1AccountActor(st, addr)
|
||||
case address.ID:
|
||||
return nil, fmt.Errorf("no actor with given ID")
|
||||
case address.Actor:
|
||||
return nil, fmt.Errorf("no such actor")
|
||||
default:
|
||||
return nil, fmt.Errorf("address has unsupported protocol: %d", addr.Protocol())
|
||||
}
|
||||
}
|
||||
|
||||
func NewBLSAccountActor(st *StateTree, addr address.Address) (*Actor, error) {
|
||||
var acstate AccountActorState
|
||||
acstate.Address = addr
|
||||
|
||||
c, err := st.store.Put(context.TODO(), acstate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nact := &Actor{
|
||||
Code: AccountActorCodeCid,
|
||||
Balance: NewInt(0),
|
||||
Head: c,
|
||||
}
|
||||
|
||||
return nact, nil
|
||||
}
|
||||
|
||||
func NewSecp256k1AccountActor(st *StateTree, addr address.Address) (*Actor, error) {
|
||||
nact := &Actor{
|
||||
Code: AccountActorCodeCid,
|
||||
Balance: NewInt(0),
|
||||
Head: EmptyObjectCid,
|
||||
}
|
||||
|
||||
return nact, nil
|
||||
}
|
||||
|
||||
func (syncer *Syncer) Punctual(ts *TipSet) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (syncer *Syncer) collectChainCaughtUp(fts *FullTipSet) ([]*FullTipSet, error) {
|
||||
// fetch tipset and messages via bitswap
|
||||
|
||||
chain := []*FullTipSet{fts}
|
||||
cur := fts.TipSet()
|
||||
|
||||
for {
|
||||
ts, err := syncer.store.LoadTipSet(cur.Parents())
|
||||
if err != nil {
|
||||
panic("should do something better, like fetch? or error?")
|
||||
}
|
||||
|
||||
return chain, nil // return the chain because we have this last block in our cache already.
|
||||
|
||||
if ts.Equals(syncer.genesis) {
|
||||
break
|
||||
}
|
||||
|
||||
/*
|
||||
if !syncer.Punctual(ts) {
|
||||
syncer.bad.InvalidateChain(chain)
|
||||
syncer.bad.InvalidateTipSet(ts)
|
||||
return nil, errors.New("tipset forks too far back from head")
|
||||
}
|
||||
*/
|
||||
|
||||
chain = append(chain, fts)
|
||||
log.Error("received unknown chain in caught up mode...")
|
||||
panic("for now, we panic...")
|
||||
|
||||
has, err := syncer.store.Contains(ts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if has {
|
||||
// Store has record of this tipset.
|
||||
return chain, nil
|
||||
}
|
||||
|
||||
/*
|
||||
parent, err := syncer.FetchTipSet(context.TODO(), ts.Parents())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ts = parent
|
||||
*/
|
||||
}
|
||||
|
||||
return chain, nil
|
||||
}
|
593
chain/types.go
Normal file
593
chain/types.go
Normal file
@ -0,0 +1,593 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"math/big"
|
||||
|
||||
block "github.com/ipfs/go-block-format"
|
||||
"github.com/ipfs/go-cid"
|
||||
cbor "github.com/ipfs/go-ipld-cbor"
|
||||
ipld "github.com/ipfs/go-ipld-format"
|
||||
"github.com/multiformats/go-multihash"
|
||||
"github.com/polydawn/refmt/obj/atlas"
|
||||
)
|
||||
|
||||
func init() {
|
||||
ipld.Register(0x1f, IpldDecode)
|
||||
|
||||
cbor.RegisterCborType(MessageReceipt{})
|
||||
cbor.RegisterCborType(Actor{})
|
||||
cbor.RegisterCborType(BlockMsg{})
|
||||
|
||||
///*
|
||||
cbor.RegisterCborType(atlas.BuildEntry(BigInt{}).UseTag(2).Transform().
|
||||
TransformMarshal(atlas.MakeMarshalTransformFunc(
|
||||
func(i BigInt) ([]byte, error) {
|
||||
if i.Int == nil {
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
return i.Bytes(), nil
|
||||
})).
|
||||
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
|
||||
func(x []byte) (BigInt, error) {
|
||||
return BigFromBytes(x), nil
|
||||
})).
|
||||
Complete())
|
||||
//*/
|
||||
cbor.RegisterCborType(atlas.BuildEntry(SignedMessage{}).UseTag(45).Transform().
|
||||
TransformMarshal(atlas.MakeMarshalTransformFunc(
|
||||
func(sm SignedMessage) ([]interface{}, error) {
|
||||
return []interface{}{
|
||||
sm.Message,
|
||||
sm.Signature,
|
||||
}, nil
|
||||
})).
|
||||
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
|
||||
func(x []interface{}) (SignedMessage, error) {
|
||||
sigb, ok := x[1].([]byte)
|
||||
if !ok {
|
||||
return SignedMessage{}, fmt.Errorf("signature in signed message was not bytes")
|
||||
}
|
||||
|
||||
sig, err := SignatureFromBytes(sigb)
|
||||
if err != nil {
|
||||
return SignedMessage{}, err
|
||||
}
|
||||
|
||||
return SignedMessage{
|
||||
Message: x[0].(Message),
|
||||
Signature: sig,
|
||||
}, nil
|
||||
})).
|
||||
Complete())
|
||||
cbor.RegisterCborType(atlas.BuildEntry(Signature{}).Transform().
|
||||
TransformMarshal(atlas.MakeMarshalTransformFunc(
|
||||
func(s Signature) ([]byte, error) {
|
||||
buf := make([]byte, 4)
|
||||
n := binary.PutUvarint(buf, uint64(s.TypeCode()))
|
||||
return append(buf[:n], s.Data...), nil
|
||||
})).
|
||||
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
|
||||
func(x []byte) (Signature, error) {
|
||||
return SignatureFromBytes(x)
|
||||
})).
|
||||
Complete())
|
||||
cbor.RegisterCborType(atlas.BuildEntry(Message{}).UseTag(44).Transform().
|
||||
TransformMarshal(atlas.MakeMarshalTransformFunc(
|
||||
func(m Message) ([]interface{}, error) {
|
||||
return []interface{}{
|
||||
m.To.Bytes(),
|
||||
m.From.Bytes(),
|
||||
m.Nonce,
|
||||
m.Value,
|
||||
m.GasPrice,
|
||||
m.GasLimit,
|
||||
m.Method,
|
||||
m.Params,
|
||||
}, nil
|
||||
})).
|
||||
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
|
||||
func(arr []interface{}) (Message, error) {
|
||||
to, err := address.NewFromBytes(arr[0].([]byte))
|
||||
if err != nil {
|
||||
return Message{}, err
|
||||
}
|
||||
|
||||
from, err := address.NewFromBytes(arr[1].([]byte))
|
||||
if err != nil {
|
||||
return Message{}, err
|
||||
}
|
||||
|
||||
nonce, ok := arr[2].(uint64)
|
||||
if !ok {
|
||||
return Message{}, fmt.Errorf("expected uint64 nonce at index 2")
|
||||
}
|
||||
|
||||
value := arr[3].(BigInt)
|
||||
gasPrice := arr[4].(BigInt)
|
||||
gasLimit := arr[5].(BigInt)
|
||||
method, _ := arr[6].(uint64)
|
||||
params, _ := arr[7].([]byte)
|
||||
|
||||
if gasPrice.Nil() {
|
||||
gasPrice = NewInt(0)
|
||||
}
|
||||
|
||||
if gasLimit.Nil() {
|
||||
gasLimit = NewInt(0)
|
||||
}
|
||||
|
||||
return Message{
|
||||
To: to,
|
||||
From: from,
|
||||
Nonce: nonce,
|
||||
Value: value,
|
||||
GasPrice: gasPrice,
|
||||
GasLimit: gasLimit,
|
||||
Method: method,
|
||||
Params: params,
|
||||
}, nil
|
||||
})).
|
||||
Complete())
|
||||
cbor.RegisterCborType(atlas.BuildEntry(BlockHeader{}).UseTag(43).Transform().
|
||||
TransformMarshal(atlas.MakeMarshalTransformFunc(
|
||||
func(blk BlockHeader) ([]interface{}, error) {
|
||||
if blk.Tickets == nil {
|
||||
blk.Tickets = []Ticket{}
|
||||
}
|
||||
if blk.Parents == nil {
|
||||
blk.Parents = []cid.Cid{}
|
||||
}
|
||||
return []interface{}{
|
||||
blk.Miner.Bytes(),
|
||||
blk.Tickets,
|
||||
blk.ElectionProof,
|
||||
blk.Parents,
|
||||
blk.ParentWeight,
|
||||
blk.Height,
|
||||
blk.StateRoot,
|
||||
blk.Messages,
|
||||
blk.MessageReceipts,
|
||||
}, nil
|
||||
})).
|
||||
TransformUnmarshal(atlas.MakeUnmarshalTransformFunc(
|
||||
func(arr []interface{}) (BlockHeader, error) {
|
||||
miner, err := address.NewFromBytes(arr[0].([]byte))
|
||||
if err != nil {
|
||||
return BlockHeader{}, err
|
||||
}
|
||||
|
||||
tickets := []Ticket{}
|
||||
ticketarr, _ := arr[1].([]interface{})
|
||||
for _, t := range ticketarr {
|
||||
tickets = append(tickets, Ticket(t.([]byte)))
|
||||
}
|
||||
electionProof, _ := arr[2].([]byte)
|
||||
|
||||
parents := []cid.Cid{}
|
||||
parentsArr, _ := arr[3].([]interface{})
|
||||
for _, p := range parentsArr {
|
||||
parents = append(parents, p.(cid.Cid))
|
||||
}
|
||||
parentWeight := arr[4].(BigInt)
|
||||
height := arr[5].(uint64)
|
||||
stateRoot := arr[6].(cid.Cid)
|
||||
|
||||
msgscid := arr[7].(cid.Cid)
|
||||
recscid := arr[8].(cid.Cid)
|
||||
|
||||
return BlockHeader{
|
||||
Miner: miner,
|
||||
Tickets: tickets,
|
||||
ElectionProof: electionProof,
|
||||
Parents: parents,
|
||||
ParentWeight: parentWeight,
|
||||
Height: height,
|
||||
StateRoot: stateRoot,
|
||||
Messages: msgscid,
|
||||
MessageReceipts: recscid,
|
||||
}, nil
|
||||
})).
|
||||
Complete())
|
||||
}
|
||||
|
||||
type BigInt struct {
|
||||
*big.Int
|
||||
}
|
||||
|
||||
func NewInt(i uint64) BigInt {
|
||||
return BigInt{big.NewInt(0).SetUint64(i)}
|
||||
}
|
||||
|
||||
func BigFromBytes(b []byte) BigInt {
|
||||
i := big.NewInt(0).SetBytes(b)
|
||||
return BigInt{i}
|
||||
}
|
||||
|
||||
func BigMul(a, b BigInt) BigInt {
|
||||
return BigInt{big.NewInt(0).Mul(a.Int, b.Int)}
|
||||
}
|
||||
|
||||
func BigAdd(a, b BigInt) BigInt {
|
||||
return BigInt{big.NewInt(0).Add(a.Int, b.Int)}
|
||||
}
|
||||
|
||||
func BigSub(a, b BigInt) BigInt {
|
||||
return BigInt{big.NewInt(0).Sub(a.Int, b.Int)}
|
||||
}
|
||||
|
||||
func BigCmp(a, b BigInt) int {
|
||||
return a.Int.Cmp(b.Int)
|
||||
}
|
||||
|
||||
func (bi *BigInt) Nil() bool {
|
||||
return bi.Int == nil
|
||||
}
|
||||
|
||||
type Actor struct {
|
||||
Code cid.Cid
|
||||
Head cid.Cid
|
||||
Nonce uint64
|
||||
Balance BigInt
|
||||
}
|
||||
|
||||
type BlockHeader struct {
|
||||
Miner address.Address
|
||||
|
||||
Tickets []Ticket
|
||||
|
||||
ElectionProof []byte
|
||||
|
||||
Parents []cid.Cid
|
||||
|
||||
ParentWeight BigInt
|
||||
|
||||
Height uint64
|
||||
|
||||
StateRoot cid.Cid
|
||||
|
||||
Messages cid.Cid
|
||||
|
||||
BLSAggregate Signature
|
||||
|
||||
MessageReceipts cid.Cid
|
||||
}
|
||||
|
||||
func (b *BlockHeader) ToStorageBlock() (block.Block, error) {
|
||||
data, err := b.Serialize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pref := cid.NewPrefixV1(0x1f, multihash.BLAKE2B_MIN+31)
|
||||
c, err := pref.Sum(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return block.NewBlockWithCid(data, c)
|
||||
}
|
||||
|
||||
func (b *BlockHeader) Cid() cid.Cid {
|
||||
sb, err := b.ToStorageBlock()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return sb.Cid()
|
||||
}
|
||||
|
||||
func DecodeBlock(b []byte) (*BlockHeader, error) {
|
||||
var blk BlockHeader
|
||||
if err := cbor.DecodeInto(b, &blk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &blk, nil
|
||||
}
|
||||
|
||||
func (blk *BlockHeader) Serialize() ([]byte, error) {
|
||||
return cbor.DumpObject(blk)
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
To address.Address
|
||||
From address.Address
|
||||
|
||||
Nonce uint64
|
||||
|
||||
Value BigInt
|
||||
|
||||
GasPrice BigInt
|
||||
GasLimit BigInt
|
||||
|
||||
Method uint64
|
||||
Params []byte
|
||||
}
|
||||
|
||||
func DecodeMessage(b []byte) (*Message, error) {
|
||||
var msg Message
|
||||
if err := cbor.DecodeInto(b, &msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
func (m *Message) Serialize() ([]byte, error) {
|
||||
return cbor.DumpObject(m)
|
||||
}
|
||||
|
||||
func (m *Message) ToStorageBlock() (block.Block, error) {
|
||||
data, err := m.Serialize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pref := cid.NewPrefixV1(0x1f, multihash.BLAKE2B_MIN+31)
|
||||
c, err := pref.Sum(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return block.NewBlockWithCid(data, c)
|
||||
}
|
||||
|
||||
func (m *SignedMessage) ToStorageBlock() (block.Block, error) {
|
||||
data, err := m.Serialize()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pref := cid.NewPrefixV1(0x1f, multihash.BLAKE2B_MIN+31)
|
||||
c, err := pref.Sum(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return block.NewBlockWithCid(data, c)
|
||||
}
|
||||
|
||||
func (m *SignedMessage) Cid() cid.Cid {
|
||||
sb, err := m.ToStorageBlock()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return sb.Cid()
|
||||
}
|
||||
|
||||
type MessageReceipt struct {
|
||||
ExitCode uint8
|
||||
|
||||
Return []byte
|
||||
|
||||
GasUsed BigInt
|
||||
}
|
||||
|
||||
func (mr *MessageReceipt) Equals(o *MessageReceipt) bool {
|
||||
return mr.ExitCode == o.ExitCode && bytes.Equal(mr.Return, o.Return) && BigCmp(mr.GasUsed, o.GasUsed) == 0
|
||||
}
|
||||
|
||||
type SignedMessage struct {
|
||||
Message Message
|
||||
Signature Signature
|
||||
}
|
||||
|
||||
func DecodeSignedMessage(data []byte) (*SignedMessage, error) {
|
||||
var msg SignedMessage
|
||||
if err := cbor.DecodeInto(data, &msg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &msg, nil
|
||||
}
|
||||
|
||||
func (sm *SignedMessage) Serialize() ([]byte, error) {
|
||||
data, err := cbor.DumpObject(sm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
type TipSet struct {
|
||||
cids []cid.Cid
|
||||
blks []*BlockHeader
|
||||
height uint64
|
||||
}
|
||||
|
||||
func NewTipSet(blks []*BlockHeader) (*TipSet, error) {
|
||||
var ts TipSet
|
||||
ts.cids = []cid.Cid{blks[0].Cid()}
|
||||
ts.blks = blks
|
||||
for _, b := range blks[1:] {
|
||||
if b.Height != blks[0].Height {
|
||||
return nil, fmt.Errorf("cannot create tipset with mismatching heights")
|
||||
}
|
||||
ts.cids = append(ts.cids, b.Cid())
|
||||
}
|
||||
ts.height = blks[0].Height
|
||||
|
||||
return &ts, nil
|
||||
}
|
||||
|
||||
func (ts *TipSet) Cids() []cid.Cid {
|
||||
return ts.cids
|
||||
}
|
||||
|
||||
func (ts *TipSet) Height() uint64 {
|
||||
return ts.height
|
||||
}
|
||||
|
||||
func (ts *TipSet) Parents() []cid.Cid {
|
||||
return ts.blks[0].Parents
|
||||
}
|
||||
|
||||
func (ts *TipSet) Blocks() []*BlockHeader {
|
||||
return ts.blks
|
||||
}
|
||||
|
||||
func (ts *TipSet) Equals(ots *TipSet) bool {
|
||||
if len(ts.blks) != len(ots.blks) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, b := range ts.blks {
|
||||
if b.Cid() != ots.blks[i].Cid() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
type Ticket []byte
|
||||
type ElectionProof []byte
|
||||
|
||||
func IpldDecode(block block.Block) (ipld.Node, error) {
|
||||
var i interface{}
|
||||
if err := cbor.DecodeInto(block.RawData(), &i); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println("IPLD DECODE!")
|
||||
return &filecoinIpldNode{i}, nil
|
||||
}
|
||||
|
||||
type filecoinIpldNode struct {
|
||||
val interface{}
|
||||
}
|
||||
|
||||
func (f *filecoinIpldNode) Cid() cid.Cid {
|
||||
switch t := f.val.(type) {
|
||||
case BlockHeader:
|
||||
return t.Cid()
|
||||
case SignedMessage:
|
||||
return t.Cid()
|
||||
default:
|
||||
panic("whats going on")
|
||||
}
|
||||
}
|
||||
|
||||
func (f *filecoinIpldNode) Copy() ipld.Node {
|
||||
panic("no")
|
||||
}
|
||||
|
||||
func (f *filecoinIpldNode) Links() []*ipld.Link {
|
||||
switch t := f.val.(type) {
|
||||
case BlockHeader:
|
||||
fmt.Println("block links!", t.StateRoot)
|
||||
return []*ipld.Link{
|
||||
{
|
||||
Cid: t.StateRoot,
|
||||
},
|
||||
{
|
||||
Cid: t.Messages,
|
||||
},
|
||||
{
|
||||
Cid: t.MessageReceipts,
|
||||
},
|
||||
}
|
||||
case Message:
|
||||
return nil
|
||||
default:
|
||||
panic("whats going on")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (f *filecoinIpldNode) Resolve(path []string) (interface{}, []string, error) {
|
||||
/*
|
||||
switch t := f.val.(type) {
|
||||
case Block:
|
||||
switch path[0] {
|
||||
}
|
||||
case Message:
|
||||
default:
|
||||
panic("whats going on")
|
||||
}
|
||||
*/
|
||||
panic("please dont call this")
|
||||
}
|
||||
|
||||
// Tree lists all paths within the object under 'path', and up to the given depth.
|
||||
// To list the entire object (similar to `find .`) pass "" and -1
|
||||
func (f *filecoinIpldNode) Tree(path string, depth int) []string {
|
||||
panic("dont call this either")
|
||||
}
|
||||
|
||||
func (f *filecoinIpldNode) ResolveLink(path []string) (*ipld.Link, []string, error) {
|
||||
panic("please no")
|
||||
}
|
||||
|
||||
func (f *filecoinIpldNode) Stat() (*ipld.NodeStat, error) {
|
||||
panic("dont call this")
|
||||
|
||||
}
|
||||
|
||||
func (f *filecoinIpldNode) Size() (uint64, error) {
|
||||
panic("dont call this")
|
||||
}
|
||||
|
||||
func (f *filecoinIpldNode) Loggable() map[string]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *filecoinIpldNode) RawData() []byte {
|
||||
switch t := f.val.(type) {
|
||||
case BlockHeader:
|
||||
sb, err := t.ToStorageBlock()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return sb.RawData()
|
||||
case SignedMessage:
|
||||
sb, err := t.ToStorageBlock()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return sb.RawData()
|
||||
default:
|
||||
panic("whats going on")
|
||||
}
|
||||
}
|
||||
|
||||
func (f *filecoinIpldNode) String() string {
|
||||
return "cats"
|
||||
}
|
||||
|
||||
type FullBlock struct {
|
||||
Header *BlockHeader
|
||||
Messages []*SignedMessage
|
||||
}
|
||||
|
||||
func (fb *FullBlock) Cid() cid.Cid {
|
||||
return fb.Header.Cid()
|
||||
}
|
||||
|
||||
type BlockMsg struct {
|
||||
Header *BlockHeader
|
||||
Messages []cid.Cid
|
||||
}
|
||||
|
||||
func DecodeBlockMsg(b []byte) (*BlockMsg, error) {
|
||||
var bm BlockMsg
|
||||
if err := cbor.DecodeInto(b, &bm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &bm, nil
|
||||
}
|
||||
|
||||
func (bm *BlockMsg) Cid() cid.Cid {
|
||||
return bm.Header.Cid()
|
||||
}
|
||||
|
||||
func (bm *BlockMsg) Serialize() ([]byte, error) {
|
||||
return cbor.DumpObject(bm)
|
||||
}
|
207
chain/vm.go
Normal file
207
chain/vm.go
Normal file
@ -0,0 +1,207 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
"github.com/pkg/errors"
|
||||
"math/big"
|
||||
|
||||
bserv "github.com/ipfs/go-blockservice"
|
||||
cid "github.com/ipfs/go-cid"
|
||||
hamt "github.com/ipfs/go-hamt-ipld"
|
||||
ipld "github.com/ipfs/go-ipld-format"
|
||||
dag "github.com/ipfs/go-merkledag"
|
||||
)
|
||||
|
||||
type VMContext struct {
|
||||
state *StateTree
|
||||
msg *Message
|
||||
height uint64
|
||||
cst *hamt.CborIpldStore
|
||||
}
|
||||
|
||||
// Message is the message that kicked off the current invocation
|
||||
func (vmc *VMContext) Message() *Message {
|
||||
return vmc.msg
|
||||
}
|
||||
|
||||
/*
|
||||
// Storage provides access to the VM storage layer
|
||||
func (vmc *VMContext) Storage() Storage {
|
||||
panic("nyi")
|
||||
}
|
||||
*/
|
||||
|
||||
func (vmc *VMContext) Ipld() *hamt.CborIpldStore {
|
||||
return vmc.cst
|
||||
}
|
||||
|
||||
// Send allows the current execution context to invoke methods on other actors in the system
|
||||
func (vmc *VMContext) Send(to address.Address, method string, value *big.Int, params []interface{}) ([][]byte, uint8, error) {
|
||||
panic("nyi")
|
||||
}
|
||||
|
||||
// BlockHeight returns the height of the block this message was added to the chain in
|
||||
func (vmc *VMContext) BlockHeight() uint64 {
|
||||
return vmc.height
|
||||
}
|
||||
|
||||
func (vmc *VMContext) GasUsed() BigInt {
|
||||
return NewInt(0)
|
||||
}
|
||||
|
||||
func makeVMContext(state *StateTree, msg *Message, height uint64) *VMContext {
|
||||
return &VMContext{
|
||||
state: state,
|
||||
msg: msg,
|
||||
height: height,
|
||||
}
|
||||
}
|
||||
|
||||
type VM struct {
|
||||
cstate *StateTree
|
||||
base cid.Cid
|
||||
cs *ChainStore
|
||||
buf *BufferedBS
|
||||
blockHeight uint64
|
||||
blockMiner address.Address
|
||||
}
|
||||
|
||||
func NewVM(base cid.Cid, height uint64, maddr address.Address, cs *ChainStore) (*VM, error) {
|
||||
buf := NewBufferedBstore(cs.bs)
|
||||
cst := hamt.CSTFromBstore(buf)
|
||||
state, err := LoadStateTree(cst, base)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &VM{
|
||||
cstate: state,
|
||||
base: base,
|
||||
cs: cs,
|
||||
buf: buf,
|
||||
blockHeight: height,
|
||||
blockMiner: maddr,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (vm *VM) ApplyMessage(msg *Message) (*MessageReceipt, error) {
|
||||
st := vm.cstate
|
||||
st.Snapshot()
|
||||
fromActor, err := st.GetActor(msg.From)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "from actor not found")
|
||||
}
|
||||
|
||||
gascost := BigMul(msg.GasLimit, msg.GasPrice)
|
||||
totalCost := BigAdd(gascost, msg.Value)
|
||||
if BigCmp(fromActor.Balance, totalCost) < 0 {
|
||||
return nil, fmt.Errorf("not enough funds")
|
||||
}
|
||||
|
||||
if msg.Nonce != fromActor.Nonce {
|
||||
return nil, fmt.Errorf("invalid nonce")
|
||||
}
|
||||
fromActor.Nonce++
|
||||
|
||||
toActor, err := st.GetActor(msg.To)
|
||||
if err != nil {
|
||||
if err == ErrActorNotFound {
|
||||
a, err := TryCreateAccountActor(st, msg.To)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
toActor = a
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := DeductFunds(fromActor, totalCost); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to deduct funds")
|
||||
}
|
||||
DepositFunds(toActor, msg.Value)
|
||||
|
||||
vmctx := makeVMContext(st, msg, vm.blockHeight)
|
||||
|
||||
var errcode byte
|
||||
var ret []byte
|
||||
if msg.Method != 0 {
|
||||
ret, errcode, err = vm.Invoke(toActor, vmctx, msg.Method, msg.Params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if errcode != 0 {
|
||||
// revert all state changes since snapshot
|
||||
st.Revert()
|
||||
gascost := BigMul(vmctx.GasUsed(), msg.GasPrice)
|
||||
if err := DeductFunds(fromActor, gascost); err != nil {
|
||||
panic("invariant violated: " + err.Error())
|
||||
}
|
||||
} else {
|
||||
// refund unused gas
|
||||
refund := BigMul(BigSub(msg.GasLimit, vmctx.GasUsed()), msg.GasPrice)
|
||||
DepositFunds(fromActor, refund)
|
||||
}
|
||||
}
|
||||
|
||||
// reward miner gas fees
|
||||
miner, err := st.GetActor(vm.blockMiner)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getting block miner actor failed")
|
||||
}
|
||||
|
||||
gasReward := BigMul(msg.GasPrice, vmctx.GasUsed())
|
||||
DepositFunds(miner, gasReward)
|
||||
|
||||
return &MessageReceipt{
|
||||
ExitCode: errcode,
|
||||
Return: ret,
|
||||
GasUsed: vmctx.GasUsed(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (vm *VM) Flush(ctx context.Context) (cid.Cid, error) {
|
||||
from := dag.NewDAGService(bserv.New(vm.buf, nil))
|
||||
to := dag.NewDAGService(bserv.New(vm.buf.read, nil))
|
||||
|
||||
root, err := vm.cstate.Flush()
|
||||
if err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
if err := ipld.Copy(ctx, from, to, root); err != nil {
|
||||
return cid.Undef, err
|
||||
}
|
||||
|
||||
return root, nil
|
||||
}
|
||||
|
||||
func (vm *VM) TransferFunds(from, to address.Address, amt BigInt) error {
|
||||
if from == to {
|
||||
return nil
|
||||
}
|
||||
|
||||
fromAct, err := vm.cstate.GetActor(from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
toAct, err := vm.cstate.GetActor(from)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := DeductFunds(fromAct, amt); err != nil {
|
||||
return errors.Wrap(err, "failed to deduct funds")
|
||||
}
|
||||
DepositFunds(toAct, amt)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vm *VM) Invoke(act *Actor, vmctx *VMContext, method uint64, params []byte) ([]byte, byte, error) {
|
||||
panic("Implement me")
|
||||
}
|
196
chain/wallet.go
Normal file
196
chain/wallet.go
Normal file
@ -0,0 +1,196 @@
|
||||
package chain
|
||||
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"github.com/filecoin-project/go-lotus/chain/address"
|
||||
|
||||
"github.com/minio/blake2b-simd"
|
||||
|
||||
bls "github.com/filecoin-project/go-filecoin/bls-signatures"
|
||||
crypto "github.com/filecoin-project/go-filecoin/crypto"
|
||||
)
|
||||
|
||||
const (
|
||||
KTSecp256k1 = "secp256k1"
|
||||
KTBLS = "bls"
|
||||
)
|
||||
|
||||
type Wallet struct {
|
||||
keys map[address.Address]*KeyInfo
|
||||
}
|
||||
|
||||
func NewWallet() *Wallet {
|
||||
return &Wallet{keys: make(map[address.Address]*KeyInfo)}
|
||||
}
|
||||
|
||||
type Signature struct {
|
||||
Type string
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func SignatureFromBytes(x []byte) (Signature, error) {
|
||||
val, nr := binary.Uvarint(x)
|
||||
if nr != 1 {
|
||||
return Signature{}, fmt.Errorf("signatures with type field longer than one byte are invalid")
|
||||
}
|
||||
var ts string
|
||||
switch val {
|
||||
case 1:
|
||||
ts = KTSecp256k1
|
||||
default:
|
||||
return Signature{}, fmt.Errorf("unsupported signature type: %d", val)
|
||||
}
|
||||
|
||||
return Signature{
|
||||
Type: ts,
|
||||
Data: x[1:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Signature) Verify(addr address.Address, msg []byte) error {
|
||||
b2sum := blake2b.Sum256(msg)
|
||||
|
||||
switch s.Type {
|
||||
case KTSecp256k1:
|
||||
pubk, err := crypto.EcRecover(b2sum[:], s.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
maybeaddr, err := address.NewSecp256k1Address(pubk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if addr != maybeaddr {
|
||||
return fmt.Errorf("signature did not match")
|
||||
}
|
||||
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("cannot verify signature of unsupported type: %s", s.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Signature) TypeCode() int {
|
||||
switch s.Type {
|
||||
case KTSecp256k1:
|
||||
return 1
|
||||
case KTBLS:
|
||||
return 2
|
||||
default:
|
||||
panic("unsupported signature type")
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Wallet) Sign(addr address.Address, msg []byte) (*Signature, error) {
|
||||
ki, err := w.findKey(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch ki.Type {
|
||||
case KTSecp256k1:
|
||||
b2sum := blake2b.Sum256(msg)
|
||||
sig, err := crypto.Sign(ki.PrivateKey, b2sum[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Signature{
|
||||
Type: KTSecp256k1,
|
||||
Data: sig,
|
||||
}, nil
|
||||
case KTBLS:
|
||||
var pk bls.PrivateKey
|
||||
copy(pk[:], ki.PrivateKey)
|
||||
sig := bls.PrivateKeySign(pk, msg)
|
||||
|
||||
return &Signature{
|
||||
Type: KTBLS,
|
||||
Data: sig[:],
|
||||
}, nil
|
||||
|
||||
default:
|
||||
panic("cant do it sir")
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Wallet) findKey(addr address.Address) (*KeyInfo, error) {
|
||||
ki, ok := w.keys[addr]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("key not for given address not found in wallet")
|
||||
}
|
||||
return ki, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) Export(addr address.Address) ([]byte, error) {
|
||||
panic("nyi")
|
||||
}
|
||||
|
||||
func (w *Wallet) Import(kdata []byte) (address.Address, error) {
|
||||
panic("nyi")
|
||||
}
|
||||
|
||||
func (w *Wallet) GenerateKey(typ string) (address.Address, error) {
|
||||
switch typ {
|
||||
case KTSecp256k1:
|
||||
k, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
return address.Undef, err
|
||||
}
|
||||
ki := &KeyInfo{
|
||||
PrivateKey: k,
|
||||
Type: typ,
|
||||
}
|
||||
|
||||
addr := ki.Address()
|
||||
w.keys[addr] = ki
|
||||
return addr, nil
|
||||
case KTBLS:
|
||||
priv := bls.PrivateKeyGenerate()
|
||||
|
||||
ki := &KeyInfo{
|
||||
PrivateKey: priv[:],
|
||||
Type: KTBLS,
|
||||
}
|
||||
|
||||
addr := ki.Address()
|
||||
w.keys[addr] = ki
|
||||
return addr, nil
|
||||
default:
|
||||
return address.Undef, fmt.Errorf("invalid key type: %s", typ)
|
||||
}
|
||||
}
|
||||
|
||||
type KeyInfo struct {
|
||||
PrivateKey []byte
|
||||
|
||||
Type string
|
||||
}
|
||||
|
||||
func (ki *KeyInfo) Address() address.Address {
|
||||
switch ki.Type {
|
||||
case KTSecp256k1:
|
||||
pub := crypto.PublicKey(ki.PrivateKey)
|
||||
addr, err := address.NewSecp256k1Address(pub)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return addr
|
||||
case KTBLS:
|
||||
var pk bls.PrivateKey
|
||||
copy(pk[:], ki.PrivateKey)
|
||||
pub := bls.PrivateKeyPublicKey(pk)
|
||||
a, err := address.NewBLSAddress(pub[:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return a
|
||||
default:
|
||||
panic("unsupported key type")
|
||||
}
|
||||
}
|
11
go.mod
11
go.mod
@ -4,10 +4,12 @@ go 1.12
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/filecoin-project/go-filecoin v0.0.1 // indirect
|
||||
github.com/golang/protobuf v1.3.1 // indirect
|
||||
github.com/ipfs/go-datastore v0.0.5
|
||||
github.com/ipfs/go-ipfs-routing v0.1.0
|
||||
github.com/ipfs/go-ipld-cbor v0.0.2 // indirect
|
||||
github.com/ipfs/go-ipld-format v0.0.2 // indirect
|
||||
github.com/ipfs/go-log v0.0.2-0.20190703113630-0c3cfb1eccc4
|
||||
github.com/libp2p/go-libp2p v0.2.0
|
||||
github.com/libp2p/go-libp2p-circuit v0.1.0
|
||||
@ -28,11 +30,16 @@ require (
|
||||
github.com/libp2p/go-maddr-filter v0.0.4
|
||||
github.com/multiformats/go-multiaddr v0.0.4
|
||||
github.com/multiformats/go-multihash v0.0.5
|
||||
github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14 // indirect
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7
|
||||
github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d // indirect
|
||||
github.com/whyrusleeping/sharray v0.0.0-20190520213710-bd32aab369f8 // indirect
|
||||
go.uber.org/dig v1.7.0 // indirect
|
||||
go.uber.org/fx v1.9.0
|
||||
go.uber.org/goleak v0.10.0 // indirect
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 // indirect
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138 // indirect
|
||||
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8
|
||||
gopkg.in/yaml.v2 v2.2.2 // indirect
|
||||
)
|
||||
|
342
go.sum
342
go.sum
@ -1,9 +1,26 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo=
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk=
|
||||
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
|
||||
github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/OpenPeeDeeP/depguard v0.0.0-20180806142446-a69c782687b2/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/Stebalien/go-bitfield v0.0.0-20180330043415-076a62f9ce6e h1:2Z+EBRrOJsA3psnUPcEWMIH2EIga1xHflQcr/EZslx8=
|
||||
github.com/Stebalien/go-bitfield v0.0.0-20180330043415-076a62f9ce6e/go.mod h1:3oM7gXIttpYDAJXpVNnSCiUMYBLIZ6cb1t+Ip982MRo=
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
||||
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c h1:aEbSeNALREWXk0G7UdNhR3ayBV7tZ4M2PNmnrCAph6Q=
|
||||
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
|
||||
@ -18,8 +35,11 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/cskr/pubsub v1.0.2 h1:vlOzMhl6PFn60gRlTQQsIfVwaPB/B/8MziK8FhEPt/0=
|
||||
github.com/cskr/pubsub v1.0.2/go.mod h1:/8MzYXk/NJAz782G8RPkFzXTZVu63VotefPnR9TIRis=
|
||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -27,16 +47,51 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018 h1:6xT9KW8zLC5IlbaIF5Q7JNieBoACT7iW0YTxQHR0in0=
|
||||
github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4=
|
||||
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f h1:6itBiEUtu+gOzXZWn46bM5/qm8LlV6/byR7Yflx/y6M=
|
||||
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f h1:dDxpBYafY/GYpcl+LS4Bn3ziLPuEdGRkRjYAbSlWxSA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v0.7.3-0.20190315170154-87d593639c77/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E=
|
||||
github.com/filecoin-project/go-filecoin v0.0.1 h1:1n0HpvqCiNmTHLDEUAWnMsyXoNHr1RdtInf/9GpQVKg=
|
||||
github.com/filecoin-project/go-filecoin v0.0.1/go.mod h1:e+Rc+H4tXgAqhdT5tsu1GYXalaHeOYMjmK3KBLKaQcE=
|
||||
github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543 h1:aMJGfgqe1QDhAVwxRg5fjCRF533xHidiKsugk7Vvzug=
|
||||
github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543/go.mod h1:mjrHv1cDGJWDlGmC0eDc1E5VJr8DmL9XMUcaFwiuKg8=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI=
|
||||
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
|
||||
github.com/go-critic/go-critic v0.0.0-20181204210945-ee9bf5809ead/go.mod h1:3MzXZKJdeXqdU9cj+rvZdNiN7SZ8V9OjybF8loZDmHU=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-toolsmith/astcast v0.0.0-20181028201508-b7a89ed70af1/go.mod h1:TEo3Ghaj7PsZawQHxT/oBvo4HK/sl1RcuUHDKTTju+o=
|
||||
github.com/go-toolsmith/astcopy v0.0.0-20180903214859-79b422d080c4/go.mod h1:c9CPdq2AzM8oPomdlPniEfPAC6g1s7NqZzODt8y6ib8=
|
||||
github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
|
||||
github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg=
|
||||
github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk=
|
||||
github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks=
|
||||
github.com/go-toolsmith/strparse v0.0.0-20180903215201-830b6daa1241/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
|
||||
github.com/go-toolsmith/typep v0.0.0-20181030061450-d63dc7650676/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
@ -46,14 +101,39 @@ github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
|
||||
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
|
||||
github.com/golangci/errcheck v0.0.0-20181003203344-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0=
|
||||
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
|
||||
github.com/golangci/go-tools v0.0.0-20180109140146-35a9f45a5db0/go.mod h1:unzUULGw35sjyOYjUt0jMTXqHlZPpPc6e+xfO4cd6mM=
|
||||
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o=
|
||||
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
|
||||
github.com/golangci/gofmt v0.0.0-20181105071733-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
|
||||
github.com/golangci/golangci-lint v1.15.0/go.mod h1:iEsyA2h6yMxPzFAlb/Q9UuXBrXIDtXkbUoukuqUAX/8=
|
||||
github.com/golangci/gosec v0.0.0-20180901114220-66fb7fc33547/go.mod h1:0qUabqiIQgfmlAmulqxyiGkkyF6/tOGSnY2cnPVwrzU=
|
||||
github.com/golangci/govet v0.0.0-20180818181408-44ddbe260190/go.mod h1:pPwb+AK755h3/r73avHz5bEN6sa51/2HEZlLaV53hCo=
|
||||
github.com/golangci/ineffassign v0.0.0-20180808204949-2ee8f2867dde/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
|
||||
github.com/golangci/lint-1 v0.0.0-20180610141402-4bf9709227d1/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
|
||||
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
|
||||
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI=
|
||||
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
|
||||
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
|
||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/gxed/go-shellwords v1.0.3/go.mod h1:N7paucT91ByIjmVJHhvoarjoQnmsi3Jd3vH7VqgtMxQ=
|
||||
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
|
||||
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
|
||||
github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
||||
@ -61,11 +141,27 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huin/goupnp v0.0.0-20180415215157-1395d1447324/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag=
|
||||
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
|
||||
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
|
||||
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/ipfs/bbloom v0.0.1 h1:s7KkiBPfxCeDVo47KySjK0ACPc5GJRUxFpdyWEuDjhw=
|
||||
github.com/ipfs/bbloom v0.0.1/go.mod h1:oqo8CVWsJFMOZqTglBG4wydCE4IQA/G2/SEofB0rjUI=
|
||||
github.com/ipfs/go-bitswap v0.0.1/go.mod h1:z+tP3h+HTJ810n1R5yMy2ccKFffJ2F6Vqm/5Bf7vs2c=
|
||||
github.com/ipfs/go-bitswap v0.0.2 h1:zlYqGWXAGuroihkjc7eAKqepwlJOcGm3ZwmFWnPUKks=
|
||||
github.com/ipfs/go-bitswap v0.0.2/go.mod h1:hBpOzPZHLBNPmuOkL/RXDD0tY8e8xyaL6yBuGBWaIso=
|
||||
github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc=
|
||||
github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE=
|
||||
github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY=
|
||||
github.com/ipfs/go-blockservice v0.0.1/go.mod h1:2Ao89U7jV1KIqqNk5EdhSTBG/Pgc1vMFr0bhkx376j4=
|
||||
github.com/ipfs/go-blockservice v0.0.2 h1:ZiKTWdZAPifdWhjjO7HjAF8grUVE86IPzcUtGCTYw4w=
|
||||
github.com/ipfs/go-blockservice v0.0.2/go.mod h1:2Ao89U7jV1KIqqNk5EdhSTBG/Pgc1vMFr0bhkx376j4=
|
||||
github.com/ipfs/go-car v0.0.1 h1:Nn3RjJbysnDud4wILAybzOAvzsaycrCoKM4BMIK0Y04=
|
||||
github.com/ipfs/go-car v0.0.1/go.mod h1:pUz3tUIpudsTch0ZQrEPOvNUBT1LufCXg8aZ4KOrEMM=
|
||||
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
|
||||
github.com/ipfs/go-cid v0.0.2 h1:tuuKaZPU1M6HcejsO3AcYWW8sZ8MTvyxfc4uqB4eFE8=
|
||||
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
|
||||
@ -74,21 +170,72 @@ github.com/ipfs/go-datastore v0.0.5 h1:q3OfiOZV5rlsK1H5V8benjeUApRfMGs4Mrhmr6Nri
|
||||
github.com/ipfs/go-datastore v0.0.5/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
|
||||
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
|
||||
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
|
||||
github.com/ipfs/go-ds-badger v0.0.2 h1:7ToQt7QByBhOTuZF2USMv+PGlMcBC7FW7FdgQ4FCsoo=
|
||||
github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8=
|
||||
github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc=
|
||||
github.com/ipfs/go-fs-lock v0.0.1 h1:XHX8uW4jQBYWHj59XXcjg7BHlHxV9ZOYs6Y43yb7/l0=
|
||||
github.com/ipfs/go-fs-lock v0.0.1/go.mod h1:DNBekbboPKcxs1aukPSaOtFA3QfSdi5C855v0i9XJ8Y=
|
||||
github.com/ipfs/go-hamt-ipld v0.0.1 h1:dOS1Bp9hyZUozI4Y7rC+FJqitur00tWlIFmLLgNev38=
|
||||
github.com/ipfs/go-hamt-ipld v0.0.1/go.mod h1:WrX60HHX2SeMb602Z1s9Ztnf/4fzNHzwH9gxNTVpEmk=
|
||||
github.com/ipfs/go-ipfs-blockstore v0.0.1 h1:O9n3PbmTYZoNhkgkEyrXTznbmktIXif62xLX+8dPHzc=
|
||||
github.com/ipfs/go-ipfs-blockstore v0.0.1/go.mod h1:d3WClOmRQKFnJ0Jz/jj/zmksX0ma1gROTlovZKBmN08=
|
||||
github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk=
|
||||
github.com/ipfs/go-ipfs-chunker v0.0.1 h1:cHUUxKFQ99pozdahi+uSC/3Y6HeRpi9oTeUHbE27SEw=
|
||||
github.com/ipfs/go-ipfs-chunker v0.0.1/go.mod h1:tWewYK0we3+rMbOh7pPFGDyypCtvGcBFymgY4rSDLAw=
|
||||
github.com/ipfs/go-ipfs-cmdkit v0.0.1 h1:X6YXEAjUljTzevE6DPUKXSqcgf+4FXzcn5B957F5MXo=
|
||||
github.com/ipfs/go-ipfs-cmdkit v0.0.1/go.mod h1:9FtbMdUabcSqv/G4/8WCxSLxkZxn/aZEFrxxqnVcRbg=
|
||||
github.com/ipfs/go-ipfs-cmds v0.0.1 h1:wPTynLMa+JImcTsPaVmrUDP8mJ3S8HQVUWixnKi7+k4=
|
||||
github.com/ipfs/go-ipfs-cmds v0.0.1/go.mod h1:k7I8PptE2kCJchR3ta546LRyxl4/uBYbLQHOJM0sUQ8=
|
||||
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
|
||||
github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ=
|
||||
github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
|
||||
github.com/ipfs/go-ipfs-ds-help v0.0.1 h1:QBg+Ts2zgeemK/dB0saiF/ykzRGgfoFMT90Rzo0OnVU=
|
||||
github.com/ipfs/go-ipfs-ds-help v0.0.1/go.mod h1:gtP9xRaZXqIQRh1HRpp595KbBEdgqWFxefeVKOV8sxo=
|
||||
github.com/ipfs/go-ipfs-exchange-interface v0.0.1 h1:LJXIo9W7CAmugqI+uofioIpRb6rY30GUu7G6LUfpMvM=
|
||||
github.com/ipfs/go-ipfs-exchange-interface v0.0.1/go.mod h1:c8MwfHjtQjPoDyiy9cFquVtVHkO9b9Ob3FG91qJnWCM=
|
||||
github.com/ipfs/go-ipfs-exchange-offline v0.0.1 h1:P56jYKZF7lDDOLx5SotVh5KFxoY6C81I1NSHW1FxGew=
|
||||
github.com/ipfs/go-ipfs-exchange-offline v0.0.1/go.mod h1:WhHSFCVYX36H/anEKQboAzpUws3x7UeEGkzQc3iNkM0=
|
||||
github.com/ipfs/go-ipfs-files v0.0.1 h1:OroTsI58plHGX70HPLKy6LQhPR3HZJ5ip61fYlo6POM=
|
||||
github.com/ipfs/go-ipfs-files v0.0.1/go.mod h1:INEFm0LL2LWXBhNJ2PMIIb2w45hpXgPjNoE7yA8Y1d4=
|
||||
github.com/ipfs/go-ipfs-flags v0.0.1 h1:OH5cEkJYL0QgA+bvD55TNG9ud8HA2Nqaav47b2c/UJk=
|
||||
github.com/ipfs/go-ipfs-flags v0.0.1/go.mod h1:RnXBb9WV53GSfTrSDVK61NLTFKvWc60n+K9EgCDh+rA=
|
||||
github.com/ipfs/go-ipfs-keystore v0.0.1 h1:sE4lNCZYl7OsgZp4Nmm4TCvIN3ub5tTDfjT6lIh6Brk=
|
||||
github.com/ipfs/go-ipfs-keystore v0.0.1/go.mod h1:5WjcKN1ESzCVzYKo5JvO1iYHLE0n626HL/cr3dSkqBs=
|
||||
github.com/ipfs/go-ipfs-posinfo v0.0.1 h1:Esoxj+1JgSjX0+ylc0hUmJCOv6V2vFoZiETLR6OtpRs=
|
||||
github.com/ipfs/go-ipfs-posinfo v0.0.1/go.mod h1:SwyeVP+jCwiDu0C313l/8jg6ZxM0qqtlt2a0vILTc1A=
|
||||
github.com/ipfs/go-ipfs-pq v0.0.1 h1:zgUotX8dcAB/w/HidJh1zzc1yFq6Vm8J7T2F4itj/RU=
|
||||
github.com/ipfs/go-ipfs-pq v0.0.1/go.mod h1:LWIqQpqfRG3fNc5XsnIhz/wQ2XXGyugQwls7BgUmUfY=
|
||||
github.com/ipfs/go-ipfs-routing v0.0.1/go.mod h1:k76lf20iKFxQTjcJokbPM9iBXVXVZhcOwc360N4nuKs=
|
||||
github.com/ipfs/go-ipfs-routing v0.1.0 h1:gAJTT1cEeeLj6/DlLX6t+NxD9fQe2ymTO6qWRDI/HQQ=
|
||||
github.com/ipfs/go-ipfs-routing v0.1.0/go.mod h1:hYoUkJLyAUKhF58tysKpids8RNDPO42BVMgK5dNsoqY=
|
||||
github.com/ipfs/go-ipfs-util v0.0.1 h1:Wz9bL2wB2YBJqggkA4dD7oSmqB4cAnpNbGrlHJulv50=
|
||||
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
|
||||
github.com/ipfs/go-ipld-cbor v0.0.1/go.mod h1:RXHr8s4k0NE0TKhnrxqZC9M888QfsBN9rhS5NjfKzY8=
|
||||
github.com/ipfs/go-ipld-cbor v0.0.2/go.mod h1:wTBtrQZA3SoFKMVkp6cn6HMRteIB1VsmHA0AQFOn7Nc=
|
||||
github.com/ipfs/go-ipld-format v0.0.1 h1:HCu4eB/Gh+KD/Q0M8u888RFkorTWNIL3da4oc5dwc80=
|
||||
github.com/ipfs/go-ipld-format v0.0.1/go.mod h1:kyJtbkDALmFHv3QR6et67i35QzO3S0dCDnkOJhcZkms=
|
||||
github.com/ipfs/go-ipld-format v0.0.2/go.mod h1:4B6+FM2u9OJ9zCV+kSbgFAZlOrv1Hqbf0INGQgiKf9k=
|
||||
github.com/ipfs/go-log v0.0.1 h1:9XTUN/rW64BCG1YhPK9Hoy3q8nr4gOmHHBpgFdfw6Lc=
|
||||
github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM=
|
||||
github.com/ipfs/go-log v0.0.2-0.20190703113630-0c3cfb1eccc4 h1:4GUopYwyu/8kX0UxYB7QDYOUbnt9HCg/j6J0sMqVvNQ=
|
||||
github.com/ipfs/go-log v0.0.2-0.20190703113630-0c3cfb1eccc4/go.mod h1:YTiqro5xwLoGra88hB8tMBlN+7ByaT3Kdaa0UqwCmI0=
|
||||
github.com/ipfs/go-merkledag v0.0.1/go.mod h1:CRdtHMROECqaehAGeJ0Wd9TtlmWv/ta5cUnvbTnniEI=
|
||||
github.com/ipfs/go-merkledag v0.0.2 h1:U3Q74RLOwpbtERjCv/MODC99qSxHBw33ZeMfiGXl7ts=
|
||||
github.com/ipfs/go-merkledag v0.0.2/go.mod h1:CRdtHMROECqaehAGeJ0Wd9TtlmWv/ta5cUnvbTnniEI=
|
||||
github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg=
|
||||
github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY=
|
||||
github.com/ipfs/go-path v0.0.1 h1:6UskTq8xYVs3zVnHjXDvoCqw22dKWK1BwD1cy1cuHyc=
|
||||
github.com/ipfs/go-path v0.0.1/go.mod h1:ztzG4iSBN2/CJa93rtHAv/I+mpK+BGALeUoJzhclhw0=
|
||||
github.com/ipfs/go-todocounter v0.0.1 h1:kITWA5ZcQZfrUnDNkRn04Xzh0YFaDFXsoO2A81Eb6Lw=
|
||||
github.com/ipfs/go-todocounter v0.0.1/go.mod h1:l5aErvQc8qKE2r7NDMjmq5UNAvuZy0rC8BHOplkWvZ4=
|
||||
github.com/ipfs/go-unixfs v0.0.1 h1:CTTGqLxU5+PRkkeA+w1peStqRWFD1Kya+yZgIT4Xy1w=
|
||||
github.com/ipfs/go-unixfs v0.0.1/go.mod h1:ZlB83nMtxNMx4DAAE5/GixeKN1qHC+xspBksI7Q5NeI=
|
||||
github.com/ipfs/go-verifcid v0.0.1 h1:m2HI7zIuR5TFyQ1b79Da5N9dnnCP1vcu2QqawmWlK2E=
|
||||
github.com/ipfs/go-verifcid v0.0.1/go.mod h1:5Hrva5KBeIog4A+UpqlaIU+DEstipcJYQQZc0g37pY0=
|
||||
github.com/ipfs/iptb v1.3.8-0.20190401234037-98ccf4228a73/go.mod h1:1rzHpCYtNp87/+hTxG5TfCVn/yMY3dKnLn8tBiMfdmg=
|
||||
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c=
|
||||
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4=
|
||||
github.com/jackpal/gateway v1.0.4/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
|
||||
github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc=
|
||||
github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
|
||||
github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=
|
||||
@ -96,6 +243,7 @@ github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+
|
||||
github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs=
|
||||
github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc=
|
||||
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2 h1:vhC1OXXiT9R2pczegwz6moDvuRpggaroAXhPIseh57A=
|
||||
github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs=
|
||||
github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY=
|
||||
@ -103,11 +251,17 @@ github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr1
|
||||
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b h1:wxtKgYHEncAU00muMD06dzLiahtGM1eouRNOzVV7tdQ=
|
||||
github.com/koron/go-ssdp v0.0.0-20180514024734-4a0ed625a78b/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@ -118,20 +272,30 @@ github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpz
|
||||
github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ=
|
||||
github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs=
|
||||
github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM=
|
||||
github.com/libp2p/go-conn-security v0.0.1/go.mod h1:bGmu51N0KU9IEjX7kl2PQjgZa40JQWnayTvNMgD/vyk=
|
||||
github.com/libp2p/go-conn-security-multistream v0.0.1/go.mod h1:nc9vud7inQ+d6SO0I/6dSWrdMnHnzZNHeyUQqrAJulE=
|
||||
github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD21CIEy5eYd1Hlp0juHY0=
|
||||
github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc=
|
||||
github.com/libp2p/go-eventbus v0.0.2 h1:L9eslON8FjFBJlyUs9fyEZKnxSqZd2AMDUNldPrqmZI=
|
||||
github.com/libp2p/go-eventbus v0.0.2/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk=
|
||||
github.com/libp2p/go-flow-metrics v0.0.1 h1:0gxuFd2GuK7IIP5pKljLwps6TvcuYgvG7Atqi3INF5s=
|
||||
github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8=
|
||||
github.com/libp2p/go-libp2p v0.0.1/go.mod h1:bmRs8I0vwn6iRaVssZnJx/epY6WPSKiLoK1vyle4EX0=
|
||||
github.com/libp2p/go-libp2p v0.0.2/go.mod h1:Qu8bWqFXiocPloabFGUcVG4kk94fLvfC8mWTDdFC9wE=
|
||||
github.com/libp2p/go-libp2p v0.1.0/go.mod h1:6D/2OBauqLUoqcADOJpn9WbKqvaM07tDw68qHM0BxUM=
|
||||
github.com/libp2p/go-libp2p v0.2.0 h1:hYJgMZYdcwHzDHKb/nLePrtuSP3LqkGIFOQ2aIbKOCM=
|
||||
github.com/libp2p/go-libp2p v0.2.0/go.mod h1:5nXHmf4Hs+NmkaMsmWcFJgUHTbYNpCfxr20lwus0p1c=
|
||||
github.com/libp2p/go-libp2p-autonat v0.0.1/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9/PMaG5zXRFNnIIT4=
|
||||
github.com/libp2p/go-libp2p-autonat v0.0.2/go.mod h1:fs71q5Xk+pdnKU014o2iq1RhMs9/PMaG5zXRFNnIIT4=
|
||||
github.com/libp2p/go-libp2p-autonat v0.1.0 h1:aCWAu43Ri4nU0ZPO7NyLzUvvfqd0nE3dX0R/ZGYVgOU=
|
||||
github.com/libp2p/go-libp2p-autonat v0.1.0/go.mod h1:1tLf2yXxiE/oKGtDwPYWTSYG3PtvYlJmg7NeVtPRqH8=
|
||||
github.com/libp2p/go-libp2p-autonat-svc v0.0.2 h1:beAUwqt3wHWlguz1EYdG+bVOKyf5SIQpXfTSnfGoW7k=
|
||||
github.com/libp2p/go-libp2p-autonat-svc v0.0.2/go.mod h1:j4iMiw0d3diRm5iB0noXumtb0mPvWrM1qAyh640cp8w=
|
||||
github.com/libp2p/go-libp2p-blankhost v0.0.1/go.mod h1:Ibpbw/7cPPYwFb7PACIWdvxxv0t0XCCI10t7czjAjTc=
|
||||
github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro=
|
||||
github.com/libp2p/go-libp2p-blankhost v0.1.3 h1:0KycuXvPDhmehw0ASsg+s1o3IfXgCUDqfzAl94KEBOg=
|
||||
github.com/libp2p/go-libp2p-blankhost v0.1.3/go.mod h1:KML1//wiKR8vuuJO0y3LUd1uLv+tlkGTAr3jC0S5cLg=
|
||||
github.com/libp2p/go-libp2p-circuit v0.0.1/go.mod h1:Dqm0s/BiV63j8EEAs8hr1H5HudqvCAeXxDyic59lCwE=
|
||||
github.com/libp2p/go-libp2p-circuit v0.1.0 h1:eniLL3Y9aq/sryfyV1IAHj5rlvuyj3b7iz8tSiZpdhY=
|
||||
github.com/libp2p/go-libp2p-circuit v0.1.0/go.mod h1:Ahq4cY3V9VJcHcn1SBXjr78AbFkZeIRmfunbA7pmFh8=
|
||||
github.com/libp2p/go-libp2p-connmgr v0.1.0 h1:vp0t0F0EuT3rrlTtnMnIyyzCnly7nIlRoEbhJpgp0qU=
|
||||
@ -141,41 +305,67 @@ github.com/libp2p/go-libp2p-core v0.0.2/go.mod h1:9dAcntw/n46XycV4RnlBq3BpgrmyUi
|
||||
github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I=
|
||||
github.com/libp2p/go-libp2p-core v0.0.6 h1:SsYhfWJ47vLP1Rd9/0hqEm/W/PlFbC/3YLZyLCcvo1w=
|
||||
github.com/libp2p/go-libp2p-core v0.0.6/go.mod h1:0d9xmaYAVY5qmbp/fcgxHT3ZJsLjYeYPMJAUKpaCHrE=
|
||||
github.com/libp2p/go-libp2p-crypto v0.0.1/go.mod h1:yJkNyDmO341d5wwXxDUGO0LykUVT72ImHNUqh5D/dBE=
|
||||
github.com/libp2p/go-libp2p-crypto v0.1.0 h1:k9MFy+o2zGDNGsaoZl0MA3iZ75qXxr9OOoAZF+sD5OQ=
|
||||
github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI=
|
||||
github.com/libp2p/go-libp2p-discovery v0.0.1/go.mod h1:ZkkF9xIFRLA1xCc7bstYFkd80gBGK8Fc1JqGoU2i+zI=
|
||||
github.com/libp2p/go-libp2p-discovery v0.1.0 h1:j+R6cokKcGbnZLf4kcNwpx6mDEUPF3N6SrqMymQhmvs=
|
||||
github.com/libp2p/go-libp2p-discovery v0.1.0/go.mod h1:4F/x+aldVHjHDHuX85x1zWoFTGElt8HnoDzwkFZm29g=
|
||||
github.com/libp2p/go-libp2p-host v0.0.1 h1:dnqusU+DheGcdxrE718kG4XgHNuL2n9eEv8Rg5zy8hQ=
|
||||
github.com/libp2p/go-libp2p-host v0.0.1/go.mod h1:qWd+H1yuU0m5CwzAkvbSjqKairayEHdR5MMl7Cwa7Go=
|
||||
github.com/libp2p/go-libp2p-interface-connmgr v0.0.1 h1:Q9EkNSLAOF+u90L88qmE9z/fTdjLh8OsJwGw74mkwk4=
|
||||
github.com/libp2p/go-libp2p-interface-connmgr v0.0.1/go.mod h1:GarlRLH0LdeWcLnYM/SaBykKFl9U5JFnbBGruAk/D5k=
|
||||
github.com/libp2p/go-libp2p-interface-pnet v0.0.1/go.mod h1:el9jHpQAXK5dnTpKA4yfCNBZXvrzdOU75zz+C6ryp3k=
|
||||
github.com/libp2p/go-libp2p-kad-dht v0.0.4/go.mod h1:oaBflOQcuC8H+SVV0YN26H6AS+wcUEJyjUGV66vXuSY=
|
||||
github.com/libp2p/go-libp2p-kad-dht v0.1.1 h1:IH6NQuoUv5w5e1O8Jc3KyVDtr0rNd0G9aaADpLI1xVo=
|
||||
github.com/libp2p/go-libp2p-kad-dht v0.1.1/go.mod h1:1kj2Rk5pX3/0RwqMm9AMNCT7DzcMHYhgDN5VTi+cY0M=
|
||||
github.com/libp2p/go-libp2p-kbucket v0.0.1/go.mod h1:Y0iQDHRTk/ZgM8PC4jExoF+E4j+yXWwRkdldkMa5Xm4=
|
||||
github.com/libp2p/go-libp2p-kbucket v0.2.0 h1:FB2a0VkOTNGTP5gu/I444u4WabNM9V1zCkQcWb7zajI=
|
||||
github.com/libp2p/go-libp2p-kbucket v0.2.0/go.mod h1:JNymBToym3QXKBMKGy3m29+xprg0EVr/GJFHxFEdgh8=
|
||||
github.com/libp2p/go-libp2p-loggables v0.0.1/go.mod h1:lDipDlBNYbpyqyPX/KcoO+eq0sJYEVR2JgOexcivchg=
|
||||
github.com/libp2p/go-libp2p-loggables v0.1.0 h1:h3w8QFfCt2UJl/0/NW4K829HX/0S4KD31PQ7m8UXXO8=
|
||||
github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90=
|
||||
github.com/libp2p/go-libp2p-metrics v0.0.1 h1:yumdPC/P2VzINdmcKZd0pciSUCpou+s0lwYCjBbzQZU=
|
||||
github.com/libp2p/go-libp2p-metrics v0.0.1/go.mod h1:jQJ95SXXA/K1VZi13h52WZMa9ja78zjyy5rspMsC/08=
|
||||
github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo=
|
||||
github.com/libp2p/go-libp2p-mplex v0.2.1 h1:E1xaJBQnbSiTHGI1gaBKmKhu1TUKkErKJnE8iGvirYI=
|
||||
github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE=
|
||||
github.com/libp2p/go-libp2p-nat v0.0.1/go.mod h1:4L6ajyUIlJvx1Cbh5pc6Ma6vMDpKXf3GgLO5u7W0oQ4=
|
||||
github.com/libp2p/go-libp2p-nat v0.0.2/go.mod h1:QrjXQSD5Dj4IJOdEcjHRkWTSomyxRo6HnUkf/TfQpLQ=
|
||||
github.com/libp2p/go-libp2p-nat v0.0.4 h1:+KXK324yaY701On8a0aGjTnw8467kW3ExKcqW2wwmyw=
|
||||
github.com/libp2p/go-libp2p-nat v0.0.4/go.mod h1:N9Js/zVtAXqaeT99cXgTV9e75KpnWCvVOiGzlcHmBbY=
|
||||
github.com/libp2p/go-libp2p-net v0.0.1 h1:xJ4Vh4yKF/XKb8fd1Ev0ebAGzVjMxXzrxG2kjtU+F5Q=
|
||||
github.com/libp2p/go-libp2p-net v0.0.1/go.mod h1:Yt3zgmlsHOgUWSXmt5V/Jpz9upuJBE8EgNU9DrCcR8c=
|
||||
github.com/libp2p/go-libp2p-netutil v0.0.1/go.mod h1:GdusFvujWZI9Vt0X5BKqwWWmZFxecf9Gt03cKxm2f/Q=
|
||||
github.com/libp2p/go-libp2p-netutil v0.1.0 h1:zscYDNVEcGxyUpMd0JReUZTrpMfia8PmLKcKF72EAMQ=
|
||||
github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU=
|
||||
github.com/libp2p/go-libp2p-peer v0.0.1/go.mod h1:nXQvOBbwVqoP+T5Y5nCjeH4sP9IX/J0AMzcDUVruVoo=
|
||||
github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY=
|
||||
github.com/libp2p/go-libp2p-peerstore v0.0.1/go.mod h1:RabLyPVJLuNQ+GFyoEkfi8H4Ti6k/HtZJ7YKgtSq+20=
|
||||
github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY=
|
||||
github.com/libp2p/go-libp2p-peerstore v0.1.1 h1:AJZF2sPpVo+0aAr3IrRiGVsPjJm1INlUQ9EGClgXJ4M=
|
||||
github.com/libp2p/go-libp2p-peerstore v0.1.1/go.mod h1:ojEWnwG7JpJLkJ9REWYXQslyu9ZLrPWPEcCdiZzEbSM=
|
||||
github.com/libp2p/go-libp2p-pnet v0.1.0 h1:kRUES28dktfnHNIRW4Ro78F7rKBHBiw5MJpl0ikrLIA=
|
||||
github.com/libp2p/go-libp2p-pnet v0.1.0/go.mod h1:ZkyZw3d0ZFOex71halXRihWf9WH/j3OevcJdTmD0lyE=
|
||||
github.com/libp2p/go-libp2p-protocol v0.0.1 h1:+zkEmZ2yFDi5adpVE3t9dqh/N9TbpFWywowzeEzBbLM=
|
||||
github.com/libp2p/go-libp2p-protocol v0.0.1/go.mod h1:Af9n4PiruirSDjHycM1QuiMi/1VZNHYcK8cLgFJLZ4s=
|
||||
github.com/libp2p/go-libp2p-pubsub v0.0.1/go.mod h1:fYKlZBOF2yrJzYlgeEVFSbYWfbS+E8Zix6gMZ0A6WgE=
|
||||
github.com/libp2p/go-libp2p-pubsub v0.1.0 h1:SmQeMa7IUv5vadh0fYgYsafWCBA1sCy5d/68kIYqGcU=
|
||||
github.com/libp2p/go-libp2p-pubsub v0.1.0/go.mod h1:ZwlKzRSe1eGvSIdU5bD7+8RZN/Uzw0t1Bp9R1znpR/Q=
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.1.1 h1:MFMJzvsxIEDEVKzO89BnB/FgvMj9WI4GDGUW2ArDPUA=
|
||||
github.com/libp2p/go-libp2p-quic-transport v0.1.1/go.mod h1:wqG/jzhF3Pu2NrhJEvE+IE0NTHNXslOPn9JQzyCAxzU=
|
||||
github.com/libp2p/go-libp2p-record v0.0.1/go.mod h1:grzqg263Rug/sRex85QrDOLntdFAymLDLm7lxMgU79Q=
|
||||
github.com/libp2p/go-libp2p-record v0.1.0 h1:wHwBGbFzymoIl69BpgwIu0O6ta3TXGcMPvHUAcodzRc=
|
||||
github.com/libp2p/go-libp2p-record v0.1.0/go.mod h1:ujNc8iuE5dlKWVy6wuL6dd58t0n7xI4hAIl8pE6wu5Q=
|
||||
github.com/libp2p/go-libp2p-routing v0.0.1/go.mod h1:N51q3yTr4Zdr7V8Jt2JIktVU+3xBBylx1MZeVA6t1Ys=
|
||||
github.com/libp2p/go-libp2p-routing v0.1.0 h1:hFnj3WR3E2tOcKaGpyzfP4gvFZ3t8JkQmbapN0Ct+oU=
|
||||
github.com/libp2p/go-libp2p-routing v0.1.0/go.mod h1:zfLhI1RI8RLEzmEaaPwzonRvXeeSHddONWkcTcB54nE=
|
||||
github.com/libp2p/go-libp2p-routing-helpers v0.1.0 h1:BaFvpyv8TyhCN7TihawTiKuzeu8/Pyw7ZnMA4IvqIN8=
|
||||
github.com/libp2p/go-libp2p-routing-helpers v0.1.0/go.mod h1:oUs0h39vNwYtYXnQWOTU5BaafbedSyWCCal3gqHuoOQ=
|
||||
github.com/libp2p/go-libp2p-secio v0.0.1/go.mod h1:IdG6iQybdcYmbTzxp4J5dwtUEDTOvZrT0opIDVNPrJs=
|
||||
github.com/libp2p/go-libp2p-secio v0.1.0 h1:NNP5KLxuP97sE5Bu3iuwOWyT/dKEGMN5zSLMWdB7GTQ=
|
||||
github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8=
|
||||
github.com/libp2p/go-libp2p-swarm v0.0.1/go.mod h1:mh+KZxkbd3lQnveQ3j2q60BM1Cw2mX36XXQqwfPOShs=
|
||||
github.com/libp2p/go-libp2p-swarm v0.1.0 h1:HrFk2p0awrGEgch9JXK/qp/hfjqQfgNxpLWnCiWPg5s=
|
||||
github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4=
|
||||
github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
|
||||
@ -184,16 +374,22 @@ github.com/libp2p/go-libp2p-testing v0.0.4 h1:Qev57UR47GcLPXWjrunv5aLIQGO4n9mhI/
|
||||
github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E=
|
||||
github.com/libp2p/go-libp2p-tls v0.1.0 h1:o4bjjAdnUjNgJoPoDd0wUaZH7K+EenlNWJpgyXB3ulA=
|
||||
github.com/libp2p/go-libp2p-tls v0.1.0/go.mod h1:VZdoSWQDeNpIIAFJFv+6uqTqpnIIDHcqZQSTC/A1TT0=
|
||||
github.com/libp2p/go-libp2p-transport v0.0.1/go.mod h1:UzbUs9X+PHOSw7S3ZmeOxfnwaQY5vGDzZmKPod3N3tk=
|
||||
github.com/libp2p/go-libp2p-transport v0.0.4/go.mod h1:StoY3sx6IqsP6XKoabsPnHCwqKXWUMWU7Rfcsubee/A=
|
||||
github.com/libp2p/go-libp2p-transport-upgrader v0.0.1/go.mod h1:NJpUAgQab/8K6K0m+JmZCe5RUXG10UMEx4kWe9Ipj5c=
|
||||
github.com/libp2p/go-libp2p-transport-upgrader v0.1.1 h1:PZMS9lhjK9VytzMCW3tWHAXtKXmlURSc3ZdvwEcKCzw=
|
||||
github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA=
|
||||
github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8=
|
||||
github.com/libp2p/go-libp2p-yamux v0.2.1 h1:Q3XYNiKCC2vIxrvUJL+Jg1kiyeEaIDNKLjgEjo3VQdI=
|
||||
github.com/libp2p/go-libp2p-yamux v0.2.1/go.mod h1:1FBXiHDk1VyRM1C0aez2bCfHQ4vMZKkAQzZbkSQt5fI=
|
||||
github.com/libp2p/go-maddr-filter v0.0.1/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q=
|
||||
github.com/libp2p/go-maddr-filter v0.0.4 h1:hx8HIuuwk34KePddrp2mM5ivgPkZ09JH4AvsALRbFUs=
|
||||
github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q=
|
||||
github.com/libp2p/go-mplex v0.0.1/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0=
|
||||
github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0=
|
||||
github.com/libp2p/go-mplex v0.1.0 h1:/nBTy5+1yRyY82YaO6HXQRnO5IAGsXTjEJaR3LdTPc0=
|
||||
github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU=
|
||||
github.com/libp2p/go-msgio v0.0.1/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
|
||||
github.com/libp2p/go-msgio v0.0.2 h1:ivPvEKHxmVkTClHzg6RXTYHqaJQ0V9cDbq+6lKb3UV0=
|
||||
github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ=
|
||||
github.com/libp2p/go-msgio v0.0.4 h1:agEFehY3zWJFUHK6SEMR7UYmk2z6kC3oeCM7ybLhguA=
|
||||
@ -202,26 +398,40 @@ github.com/libp2p/go-nat v0.0.3 h1:l6fKV+p0Xa354EqQOQP+d8CivdLM4kl5GxC1hSc/UeI=
|
||||
github.com/libp2p/go-nat v0.0.3/go.mod h1:88nUEt0k0JD45Bk93NIwDqjlhiOwOoV36GchpcVc1yI=
|
||||
github.com/libp2p/go-reuseport v0.0.1 h1:7PhkfH73VXfPJYKQ6JwS5I/eVcoyYi9IMNGc6FWpFLw=
|
||||
github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA=
|
||||
github.com/libp2p/go-reuseport-transport v0.0.1/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs=
|
||||
github.com/libp2p/go-reuseport-transport v0.0.2 h1:WglMwyXyBu61CMkjCCtnmqNqnjib0GIEjMiHTwR/KN4=
|
||||
github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs=
|
||||
github.com/libp2p/go-stream-muxer v0.0.1 h1:Ce6e2Pyu+b5MC1k3eeFtAax0pW4gc6MosYSLV05UeLw=
|
||||
github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14=
|
||||
github.com/libp2p/go-stream-muxer-multistream v0.2.0 h1:714bRJ4Zy9mdhyTLJ+ZKiROmAFwUHpeRidG+q7LTQOg=
|
||||
github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc=
|
||||
github.com/libp2p/go-tcp-transport v0.0.1/go.mod h1:mnjg0o0O5TmXUaUIanYPUqkW4+u6mK0en8rlpA6BBTs=
|
||||
github.com/libp2p/go-tcp-transport v0.1.0 h1:IGhowvEqyMFknOar4FWCKSWE0zL36UFKQtiRQD60/8o=
|
||||
github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc=
|
||||
github.com/libp2p/go-testutil v0.0.1 h1:Xg+O0G2HIMfHqBOBDcMS1iSZJ3GEcId4qOxCQvsGZHk=
|
||||
github.com/libp2p/go-testutil v0.0.1/go.mod h1:iAcJc/DKJQanJ5ws2V+u5ywdL2n12X1WbbEG+Jjy69I=
|
||||
github.com/libp2p/go-ws-transport v0.0.1/go.mod h1:p3bKjDWHEgtuKKj+2OdPYs5dAPIjtpQGHF2tJfGz7Ww=
|
||||
github.com/libp2p/go-ws-transport v0.1.0 h1:F+0OvvdmPTDsVc4AjPHjV7L7Pk1B7D5QwtDcKE2oag4=
|
||||
github.com/libp2p/go-ws-transport v0.1.0/go.mod h1:rjw1MG1LU9YDC6gzmwObkPd/Sqwhw7yT74kj3raBFuo=
|
||||
github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
|
||||
github.com/libp2p/go-yamux v1.2.3 h1:xX8A36vpXb59frIzWFdEgptLMsOANMFq2K7fPRlunYI=
|
||||
github.com/libp2p/go-yamux v1.2.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
|
||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/lucas-clemente/quic-go v0.11.2 h1:Mop0ac3zALaBR3wGs6j8OYe/tcFvFsxTUFMkE/7yUOI=
|
||||
github.com/lucas-clemente/quic-go v0.11.2/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw=
|
||||
github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/marten-seemann/qtls v0.2.3 h1:0yWJ43C62LsZt08vuQJDK1uC1czUc3FJeCLPoNAI4vA=
|
||||
github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/miekg/dns v1.1.12 h1:WMhc1ik4LNkTg8U9l3hI1LvxKmIL+f1+WV/SZtCbDDA=
|
||||
github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
|
||||
@ -230,6 +440,13 @@ github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+
|
||||
github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
|
||||
github.com/minio/sha256-simd v0.1.0 h1:U41/2erhAKcmSI14xh/ZTUdBPOzDOIfS93ibzUSl8KM=
|
||||
github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
|
||||
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
|
||||
github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
|
||||
github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78=
|
||||
@ -252,49 +469,122 @@ github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/g
|
||||
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
|
||||
github.com/multiformats/go-multihash v0.0.5 h1:1wxmCvTXAifAepIMyF39vZinRw5sbqjPs/UIi93+uik=
|
||||
github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po=
|
||||
github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
|
||||
github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ=
|
||||
github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20160627004424-a22cb81b2ecd/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992 h1:bzMe+2coZJYHnhGgVlcQKuRy4FSny4ds8dLQjw5P1XE=
|
||||
github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
|
||||
github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14 h1:2m16U/rLwVaRdz7ANkHtHTodP3zTP3N451MADg64x5k=
|
||||
github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829 h1:D+CiwcpGTW6pL6bv6KI3KbyEyCKyS+1JWS2h8PNDnGA=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f h1:BVwpUVJDADN2ufcGik7W992pyps0wZ888b/y9GXcLTU=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1 h1:/K3IL0Z1quvmJ7X0A1AwNEK7CRkVK3YwfOU/QAL4WGg=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU=
|
||||
github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a h1:/eS3yfGjQKG+9kayBkj0ip1BGhq6zJ3eaVksphxAaek=
|
||||
github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0=
|
||||
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
|
||||
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
|
||||
github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e h1:T5PdfK/M1xyrHwynxMIVMWLS7f/qHwfslZphxtGnw7s=
|
||||
github.com/texttheater/golang-levenshtein v0.0.0-20180516184445-d188e65d659e/go.mod h1:XDKHRm5ThF8YJjx001LtgelzsoaEcvnA7lVWz9EeX3g=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
|
||||
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc h1:BCPnHtcboadS0DvysUuJXZ4lWVv5Bh5i7+tbIyi+ck4=
|
||||
github.com/whyrusleeping/base32 v0.0.0-20170828182744-c30ac30633cc/go.mod h1:r45hJU7yEoA81k6MWNhpMj/kms0n14dkzkxYHoB96UM=
|
||||
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E=
|
||||
github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8=
|
||||
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1 h1:EKhdznlJHPMoKr0XTrX+IlJs1LH3lyx2nfr1dOlZ79k=
|
||||
github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc=
|
||||
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc h1:9lDbC6Rz4bwmou+oE6Dt4Cb2BGMur5eR/GYptkKUVHo=
|
||||
github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM=
|
||||
github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f h1:M/lL30eFZTKnomXY6huvM6G0+gVquFNf6mxghaWlFUg=
|
||||
github.com/whyrusleeping/go-notifier v0.0.0-20170827234753-097c5d47330f/go.mod h1:cZNvX9cFybI01GriPRMXDtczuvUhgbcYr9iCGaNlRv8=
|
||||
github.com/whyrusleeping/go-smux-multiplex v3.0.16+incompatible/go.mod h1:34LEDbeKFZInPUrAG+bjuJmUXONGdEFW7XL0SpTY1y4=
|
||||
github.com/whyrusleeping/go-smux-multistream v2.0.2+incompatible/go.mod h1:dRWHHvc4HDQSHh9gbKEBbUZ+f2Q8iZTPG3UOGYODxSQ=
|
||||
github.com/whyrusleeping/go-smux-yamux v2.0.8+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI=
|
||||
github.com/whyrusleeping/go-smux-yamux v2.0.9+incompatible/go.mod h1:6qHUzBXUbB9MXmw3AUdB52L8sEb/hScCqOdW2kj/wuI=
|
||||
github.com/whyrusleeping/mafmt v1.2.8 h1:TCghSl5kkwEE0j+sU/gudyhVMRlpBin8fMBBHg59EbA=
|
||||
github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA=
|
||||
github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30 h1:nMCC9Pwz1pxfC1Y6mYncdk+kq8d5aLx0Q+/gyZGE44M=
|
||||
github.com/whyrusleeping/mdns v0.0.0-20180901202407-ef14215e6b30/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
|
||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds=
|
||||
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI=
|
||||
github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d h1:wnjWu1N8UTNf2zzF5FWlEyNNbNw5GMVHaHaaLdvdTdA=
|
||||
github.com/whyrusleeping/pubsub v0.0.0-20131020042734-02de8aa2db3d/go.mod h1:g7ckxrjiFh8mi1AY7ox23PZD0g6QU/TxW3U3unX7I3A=
|
||||
github.com/whyrusleeping/sharray v0.0.0-20190520213710-bd32aab369f8 h1:n89ErB+0d4SBbyD8ykr7Q/j+C41ysUttZG3l9/2ufC4=
|
||||
github.com/whyrusleeping/sharray v0.0.0-20190520213710-bd32aab369f8/go.mod h1:c1pwhNePDPlcYJZinQlfLTOKwTmVf45nfdTg73yOOcA=
|
||||
github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow=
|
||||
github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg=
|
||||
github.com/whyrusleeping/yamux v1.1.5/go.mod h1:E8LnQQ8HKx5KD29HZFUwM1PxCOdPRzGwur1mcYhXcD8=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
|
||||
go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A=
|
||||
go.opencensus.io v0.19.2/go.mod h1:NO/8qkisMZLZ1FCsKNqtJPwc8/TaclWyY0B6wcYNg9M=
|
||||
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
|
||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/dig v1.7.0 h1:E5/L92iQTNJTjfgJF2KgU+/JpMaiuvK2DHLBj0+kSZk=
|
||||
@ -307,7 +597,11 @@ go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go4.org v0.0.0-20190218023631-ce4c26f7be8e h1:m9LfARr2VIOW0vsV19kEKp/sWQvZnGobA8JHui/XJoY=
|
||||
go4.org v0.0.0-20190218023631-ce4c26f7be8e/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180505025534-4ec37c66abab/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@ -317,12 +611,21 @@ golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU=
|
||||
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
@ -331,44 +634,83 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09 h1:IlD35wZE03o2qJy2o37WIskL33b7PT6cHdGnE8bieZs=
|
||||
golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20170915040203-e531a2a1c15f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181205014116-22934f0fdb62/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190121143147-24cd39ecf745/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190125232054-379209517ffe/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/xerrors v0.0.0-20190212162355-a5947ffaace3/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522 h1:bhOzK9QyoD0ogCnFro1m2mz41+Ib0oOhfJnBp5MR4K4=
|
||||
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||
google.golang.org/api v0.2.0/go.mod h1:IfRCZScioGtypHNTlz3gFk67J8uePVW7uDTBzXuIkhU=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8 h1:Ggy3mWN4l3PUFPfSG0YB3n5fVYggzysUmiUQ89SnX6Y=
|
||||
gopkg.in/urfave/cli.v2 v2.0.0-20180128182452-d3ae77c26ac8/go.mod h1:cKXr3E0k4aosgycml1b5z33BVV6hai1Kh7uDgFOkbcs=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
||||
mvdan.cc/unparam v0.0.0-20190124213536-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskXg5OFSrilMRUkD8ePJpHKDPaeY=
|
||||
sourcegraph.com/sourcegraph/go-diff v0.5.1-0.20190210232911-dee78e514455/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||
|
Loading…
Reference in New Issue
Block a user