mirror of
https://github.com/logos-messaging/go-multiaddr.git
synced 2026-08-09 07:03:36 +00:00
absorb go-maddr-filter; rm stale Makefile targets; upgrade deps (#124)
This commit is contained in:
parent
8ae68cf376
commit
192ac0f7fd
16
Makefile
16
Makefile
@ -1,17 +1,3 @@
|
|||||||
gx:
|
|
||||||
go get github.com/whyrusleeping/gx
|
|
||||||
go get github.com/whyrusleeping/gx-go
|
|
||||||
|
|
||||||
covertools:
|
|
||||||
go get golang.org/x/tools/cmd/cover
|
|
||||||
|
|
||||||
deps: gx covertools
|
|
||||||
gx --verbose install --global
|
|
||||||
gx-go rewrite
|
|
||||||
|
|
||||||
publish:
|
|
||||||
gx-go rewrite --undo
|
|
||||||
|
|
||||||
conformance: tmp/multiaddr
|
conformance: tmp/multiaddr
|
||||||
go build -o tmp/multiaddr/test/go-multiaddr ./multiaddr
|
go build -o tmp/multiaddr/test/go-multiaddr ./multiaddr
|
||||||
cd tmp/multiaddr/test && MULTIADDR_BIN="./go-multiaddr" go test -v
|
cd tmp/multiaddr/test && MULTIADDR_BIN="./go-multiaddr" go test -v
|
||||||
@ -23,4 +9,4 @@ tmp/multiaddr:
|
|||||||
clean:
|
clean:
|
||||||
rm -rf tmp/
|
rm -rf tmp/
|
||||||
|
|
||||||
.PHONY: gx covertools deps publish conformance clean
|
.PHONY: conformance clean
|
||||||
|
|||||||
179
filter.go
Normal file
179
filter.go
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
package multiaddr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Action is an enum modelling all possible filter actions.
|
||||||
|
type Action int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
ActionNone Action = iota // zero value.
|
||||||
|
ActionAccept
|
||||||
|
ActionDeny
|
||||||
|
)
|
||||||
|
|
||||||
|
type filterEntry struct {
|
||||||
|
f net.IPNet
|
||||||
|
action Action
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filters is a structure representing a collection of accept/deny
|
||||||
|
// net.IPNet filters, together with the DefaultAction flag, which
|
||||||
|
// represents the default filter policy.
|
||||||
|
//
|
||||||
|
// Note that the last policy added to the Filters is authoritative.
|
||||||
|
type Filters struct {
|
||||||
|
DefaultAction Action
|
||||||
|
|
||||||
|
mu sync.RWMutex
|
||||||
|
filters []*filterEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFilters constructs and returns a new set of net.IPNet filters.
|
||||||
|
// By default, the new filter accepts all addresses.
|
||||||
|
func NewFilters() *Filters {
|
||||||
|
return &Filters{
|
||||||
|
DefaultAction: ActionAccept,
|
||||||
|
filters: make([]*filterEntry, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *Filters) find(ipnet net.IPNet) (int, *filterEntry) {
|
||||||
|
s := ipnet.String()
|
||||||
|
for idx, ft := range fs.filters {
|
||||||
|
if ft.f.String() == s {
|
||||||
|
return idx, ft
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddDialFilter adds a deny rule to this Filters set. Hosts
|
||||||
|
// matching the given net.IPNet filter will be denied, unless
|
||||||
|
// another rule is added which states that they should be accepted.
|
||||||
|
//
|
||||||
|
// No effort is made to prevent duplication of filters, or to simplify
|
||||||
|
// the filters list.
|
||||||
|
//
|
||||||
|
// Deprecated: Use AddFilter().
|
||||||
|
func (fs *Filters) AddDialFilter(f *net.IPNet) {
|
||||||
|
fs.AddFilter(*f, ActionDeny)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFilter adds a rule to the Filters set, enforcing the desired action for
|
||||||
|
// the provided IPNet mask.
|
||||||
|
func (fs *Filters) AddFilter(ipnet net.IPNet, action Action) {
|
||||||
|
fs.mu.Lock()
|
||||||
|
defer fs.mu.Unlock()
|
||||||
|
|
||||||
|
if _, f := fs.find(ipnet); f != nil {
|
||||||
|
f.action = action
|
||||||
|
} else {
|
||||||
|
fs.filters = append(fs.filters, &filterEntry{ipnet, action})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveLiteral removes the first filter associated with the supplied IPNet,
|
||||||
|
// returning whether something was removed or not. It makes no distinction
|
||||||
|
// between whether the rule is an accept or a deny.
|
||||||
|
//
|
||||||
|
// Deprecated: use RemoveLiteral() instead.
|
||||||
|
func (fs *Filters) Remove(ipnet *net.IPNet) (removed bool) {
|
||||||
|
return fs.RemoveLiteral(*ipnet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveLiteral removes the first filter associated with the supplied IPNet,
|
||||||
|
// returning whether something was removed or not. It makes no distinction
|
||||||
|
// between whether the rule is an accept or a deny.
|
||||||
|
func (fs *Filters) RemoveLiteral(ipnet net.IPNet) (removed bool) {
|
||||||
|
fs.mu.Lock()
|
||||||
|
defer fs.mu.Unlock()
|
||||||
|
|
||||||
|
if idx, _ := fs.find(ipnet); idx != -1 {
|
||||||
|
fs.filters = append(fs.filters[:idx], fs.filters[idx+1:]...)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddrBlocked parses a ma.Multiaddr and, if a valid netip is found, it applies the
|
||||||
|
// Filter set rules, returning true if the given address should be denied, and false if
|
||||||
|
// the given address is accepted.
|
||||||
|
//
|
||||||
|
// If a parsing error occurs, or no filter matches, the Filters'
|
||||||
|
// default is returned.
|
||||||
|
//
|
||||||
|
// TODO: currently, the last filter to match wins always, but it shouldn't be that way.
|
||||||
|
// Instead, the highest-specific last filter should win; that way more specific filters
|
||||||
|
// override more general ones.
|
||||||
|
func (fs *Filters) AddrBlocked(a Multiaddr) (deny bool) {
|
||||||
|
var (
|
||||||
|
netip net.IP
|
||||||
|
found bool
|
||||||
|
)
|
||||||
|
|
||||||
|
ForEach(a, func(c Component) bool {
|
||||||
|
switch c.Protocol().Code {
|
||||||
|
case P_IP6ZONE:
|
||||||
|
return true
|
||||||
|
case P_IP6, P_IP4:
|
||||||
|
found = true
|
||||||
|
netip = net.IP(c.RawValue())
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return fs.DefaultAction == ActionDeny
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.mu.RLock()
|
||||||
|
defer fs.mu.RUnlock()
|
||||||
|
|
||||||
|
action := fs.DefaultAction
|
||||||
|
for _, ft := range fs.filters {
|
||||||
|
if ft.f.Contains(netip) {
|
||||||
|
action = ft.action
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return action == ActionDeny
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filters returns the list of DENY net.IPNet masks. For backwards compatibility.
|
||||||
|
//
|
||||||
|
// A copy of the filters is made prior to returning, so the inner state is not exposed.
|
||||||
|
//
|
||||||
|
// Deprecated: Use FiltersForAction().
|
||||||
|
func (fs *Filters) Filters() (result []*net.IPNet) {
|
||||||
|
ffa := fs.FiltersForAction(ActionDeny)
|
||||||
|
for _, res := range ffa {
|
||||||
|
res := res // allocate a new copy
|
||||||
|
result = append(result, &res)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fs *Filters) ActionForFilter(ipnet net.IPNet) (action Action, ok bool) {
|
||||||
|
if _, f := fs.find(ipnet); f != nil {
|
||||||
|
return f.action, true
|
||||||
|
}
|
||||||
|
return ActionNone, false
|
||||||
|
}
|
||||||
|
|
||||||
|
// FiltersForAction returns the filters associated with the indicated action.
|
||||||
|
func (fs *Filters) FiltersForAction(action Action) (result []net.IPNet) {
|
||||||
|
fs.mu.RLock()
|
||||||
|
defer fs.mu.RUnlock()
|
||||||
|
|
||||||
|
for _, ff := range fs.filters {
|
||||||
|
if ff.action == action {
|
||||||
|
result = append(result, ff.f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
202
filter_test.go
Normal file
202
filter_test.go
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
package multiaddr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilterListing(t *testing.T) {
|
||||||
|
f := NewFilters()
|
||||||
|
expected := map[string]bool{
|
||||||
|
"1.2.3.0/24": true,
|
||||||
|
"4.3.2.1/32": true,
|
||||||
|
"fd00::/8": true,
|
||||||
|
"fc00::1/128": true,
|
||||||
|
}
|
||||||
|
for cidr := range expected {
|
||||||
|
_, ipnet, _ := net.ParseCIDR(cidr)
|
||||||
|
f.AddDialFilter(ipnet)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, filter := range f.Filters() {
|
||||||
|
cidr := filter.String()
|
||||||
|
if expected[cidr] {
|
||||||
|
delete(expected, cidr)
|
||||||
|
} else {
|
||||||
|
t.Errorf("unexected filter %s", cidr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for cidr := range expected {
|
||||||
|
t.Errorf("expected filter %s", cidr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterBlocking(t *testing.T) {
|
||||||
|
f := NewFilters()
|
||||||
|
|
||||||
|
_, ipnet, _ := net.ParseCIDR("0.1.2.3/24")
|
||||||
|
f.AddDialFilter(ipnet)
|
||||||
|
filters := f.Filters()
|
||||||
|
if len(filters) != 1 {
|
||||||
|
t.Fatal("Expected only 1 filter")
|
||||||
|
}
|
||||||
|
|
||||||
|
if a, ok := f.ActionForFilter(*ipnet); !ok || a != ActionDeny {
|
||||||
|
t.Fatal("Expected filter with DENY action")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !f.RemoveLiteral(*filters[0]) {
|
||||||
|
t.Error("expected true value from RemoveLiteral")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, cidr := range []string{
|
||||||
|
"1.2.3.0/24",
|
||||||
|
"4.3.2.1/32",
|
||||||
|
"fd00::/8",
|
||||||
|
"fc00::1/128",
|
||||||
|
} {
|
||||||
|
_, ipnet, _ := net.ParseCIDR(cidr)
|
||||||
|
f.AddDialFilter(ipnet)
|
||||||
|
}
|
||||||
|
|
||||||
|
// These addresses should all be blocked
|
||||||
|
for _, blocked := range []string{
|
||||||
|
"/ip4/1.2.3.4/tcp/123",
|
||||||
|
"/ip4/4.3.2.1/udp/123",
|
||||||
|
"/ip6/fd00::2/tcp/321",
|
||||||
|
"/ip6/fc00::1/udp/321",
|
||||||
|
} {
|
||||||
|
maddr, err := NewMultiaddr(blocked)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !f.AddrBlocked(maddr) {
|
||||||
|
t.Fatalf("expected %s to be blocked", blocked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// test that other net intervals are not blocked
|
||||||
|
for _, addr := range []string{
|
||||||
|
"/ip4/1.2.4.1/tcp/123",
|
||||||
|
"/ip4/4.3.2.2/udp/123",
|
||||||
|
"/ip6/fe00::1/tcp/321",
|
||||||
|
"/ip6/fc00::2/udp/321",
|
||||||
|
} {
|
||||||
|
maddr, err := NewMultiaddr(addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if f.AddrBlocked(maddr) {
|
||||||
|
t.Fatalf("expected %s to not be blocked", addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterWhitelisting(t *testing.T) {
|
||||||
|
f := NewFilters()
|
||||||
|
|
||||||
|
// Add default reject filter
|
||||||
|
f.DefaultAction = ActionDeny
|
||||||
|
|
||||||
|
// Add a whitelist
|
||||||
|
_, ipnet, _ := net.ParseCIDR("1.2.3.0/24")
|
||||||
|
f.AddFilter(*ipnet, ActionAccept)
|
||||||
|
|
||||||
|
if a, ok := f.ActionForFilter(*ipnet); !ok || a != ActionAccept {
|
||||||
|
t.Fatal("Expected filter with ACCEPT action")
|
||||||
|
}
|
||||||
|
|
||||||
|
// That /24 should now be allowed
|
||||||
|
for _, addr := range []string{
|
||||||
|
"/ip4/1.2.3.1/tcp/123",
|
||||||
|
"/ip4/1.2.3.254/tcp/123",
|
||||||
|
"/ip4/1.2.3.254/udp/321",
|
||||||
|
} {
|
||||||
|
maddr, err := NewMultiaddr(addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if f.AddrBlocked(maddr) {
|
||||||
|
t.Fatalf("expected %s to be whitelisted", addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No policy matches these maddrs, they should be blocked by default
|
||||||
|
for _, blocked := range []string{
|
||||||
|
"/ip4/1.2.4.4/tcp/123",
|
||||||
|
"/ip4/4.3.2.1/udp/123",
|
||||||
|
"/ip6/fd00::2/tcp/321",
|
||||||
|
"/ip6/fc00::1/udp/321",
|
||||||
|
} {
|
||||||
|
maddr, err := NewMultiaddr(blocked)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !f.AddrBlocked(maddr) {
|
||||||
|
t.Fatalf("expected %s to be blocked", blocked)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFiltersRemoveRules(t *testing.T) {
|
||||||
|
f := NewFilters()
|
||||||
|
|
||||||
|
ips := []string{
|
||||||
|
"/ip4/1.2.3.1/tcp/123",
|
||||||
|
"/ip4/1.2.3.254/tcp/123",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add default reject filter
|
||||||
|
f.DefaultAction = ActionDeny
|
||||||
|
|
||||||
|
// Add whitelisting
|
||||||
|
_, ipnet, _ := net.ParseCIDR("1.2.3.0/24")
|
||||||
|
f.AddFilter(*ipnet, ActionAccept)
|
||||||
|
|
||||||
|
if a, ok := f.ActionForFilter(*ipnet); !ok || a != ActionAccept {
|
||||||
|
t.Fatal("Expected filter with ACCEPT action")
|
||||||
|
}
|
||||||
|
|
||||||
|
// these are all whitelisted, should be OK
|
||||||
|
for _, addr := range ips {
|
||||||
|
maddr, err := NewMultiaddr(addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if f.AddrBlocked(maddr) {
|
||||||
|
t.Fatalf("expected %s to be whitelisted", addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test removing the filter. It'll remove multiple, so make a dupe &
|
||||||
|
// a complement
|
||||||
|
f.AddDialFilter(ipnet)
|
||||||
|
|
||||||
|
// Show that they all apply, these are now blacklisted & should fail
|
||||||
|
for _, addr := range ips {
|
||||||
|
maddr, err := NewMultiaddr(addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !f.AddrBlocked(maddr) {
|
||||||
|
t.Fatalf("expected %s to be blacklisted", addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove those rules
|
||||||
|
if !f.RemoveLiteral(*ipnet) {
|
||||||
|
t.Error("expected true value from RemoveLiteral")
|
||||||
|
}
|
||||||
|
|
||||||
|
// our default is reject, so the 1.2.3.0/24 should be rejected now,
|
||||||
|
// along with everything else
|
||||||
|
for _, addr := range ips {
|
||||||
|
maddr, err := NewMultiaddr(addr)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if !f.AddrBlocked(maddr) {
|
||||||
|
t.Fatalf("expected %s to be blocked", addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
6
go.mod
6
go.mod
@ -1,8 +1,8 @@
|
|||||||
module github.com/multiformats/go-multiaddr
|
module github.com/multiformats/go-multiaddr
|
||||||
|
|
||||||
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/multiformats/go-multihash v0.0.13
|
github.com/multiformats/go-multihash v0.0.13
|
||||||
github.com/multiformats/go-varint v0.0.2
|
github.com/multiformats/go-varint v0.0.5
|
||||||
)
|
)
|
||||||
|
|
||||||
go 1.13
|
|
||||||
|
|||||||
10
go.sum
10
go.sum
@ -2,20 +2,10 @@ github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0
|
|||||||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
|
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
|
||||||
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo=
|
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771 h1:MHkK1uRtFbVqvAgvWxafZe54+5uBxLluGylDiKgdhwo=
|
||||||
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||||
github.com/mr-tron/base58 v1.1.2 h1:ZEw4I2EgPKDJ2iEw0cNmLB3ROrEmkOtXIkaG7wZg+78=
|
|
||||||
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
|
||||||
github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
|
github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
|
||||||
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||||
github.com/multiformats/go-multihash v0.0.8 h1:wrYcW5yxSi3dU07n5jnuS5PrNwyHy0zRHGVoUugWvXg=
|
|
||||||
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
|
|
||||||
github.com/multiformats/go-multihash v0.0.10 h1:lMoNbh2Ssd9PUF74Nz008KGzGPlfeV6wH3rit5IIGCM=
|
|
||||||
github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
|
|
||||||
github.com/multiformats/go-multihash v0.0.13 h1:06x+mk/zj1FoMsgNejLpy6QTvJqlSt/BhLEy87zidlc=
|
github.com/multiformats/go-multihash v0.0.13 h1:06x+mk/zj1FoMsgNejLpy6QTvJqlSt/BhLEy87zidlc=
|
||||||
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
|
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
|
||||||
github.com/multiformats/go-varint v0.0.1 h1:TR/0rdQtnNxuN2IhiB639xC3tWM4IUi7DkTBVTdGW/M=
|
|
||||||
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
|
||||||
github.com/multiformats/go-varint v0.0.2 h1:6sUvyh2YHpJCb8RZ6eYzj6iJQ4+chWYmyIHxszqlPTA=
|
|
||||||
github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
|
||||||
github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg=
|
github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg=
|
||||||
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user