Compare commits
37 Commits
gx/v0.7.12
...
gx/v0.7.22
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd441bb43e | ||
|
|
10a4d040b4 | ||
|
|
d204c18f7a | ||
|
|
b41162260a | ||
|
|
9cb0b7bcae | ||
|
|
5b04f30433 | ||
|
|
078355866b | ||
|
|
1805dd530f | ||
|
|
2055d2e652 | ||
|
|
63d4b33fcf | ||
|
|
19c1c0e32e | ||
|
|
088f141a17 | ||
|
|
758714796c | ||
|
|
ed3563b69e | ||
|
|
db11d7248a | ||
|
|
68abb41a9b | ||
|
|
7333c60a00 | ||
|
|
f62e35b87a | ||
|
|
5652e6f751 | ||
|
|
fa428a337b | ||
|
|
e0f0e24c2d | ||
|
|
1aa1093d28 | ||
|
|
f4f9847100 | ||
|
|
83b0d39470 | ||
|
|
b7772ebfe3 | ||
|
|
e449699cc1 | ||
|
|
7d345d4817 | ||
|
|
3c03b9e581 | ||
|
|
f6990413f7 | ||
|
|
3f7f6c6a1d | ||
|
|
05eac5f7ca | ||
|
|
1f385a8224 | ||
|
|
b42583c8bf | ||
|
|
45ce89d41a | ||
|
|
a20203df14 | ||
|
|
d4ebfff511 | ||
|
|
e310d23e36 |
@@ -1 +1 @@
|
||||
0.7.12: QmYhQaCYEcaPPjxJX7YcPcVKkQfRy6sJ7B3XmGFk82XYdQ
|
||||
0.7.22: QmYVNvtQkeZ6AKSwDrjQTs432QtL6umrrK41EBq3cu7iSP
|
||||
|
||||
32
.travis.yml
32
.travis.yml
@@ -1,24 +1,24 @@
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
sudo: false
|
||||
|
||||
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.7
|
||||
|
||||
install: true
|
||||
|
||||
before_install:
|
||||
- make deps
|
||||
|
||||
- 'tip'
|
||||
|
||||
install:
|
||||
- go get github.com/whyrusleeping/gx
|
||||
- go get github.com/whyrusleeping/gx-go
|
||||
- gx install --global
|
||||
script:
|
||||
- go vet
|
||||
- $GOPATH/bin/goveralls -service="travis-ci"
|
||||
- gx test -v -race -coverprofile=coverage.txt -covermode=atomic .
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $GOPATH/src/gx
|
||||
directories:
|
||||
- $GOPATH/src/gx
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
email: false
|
||||
|
||||
|
||||
277
cid-fmt/main.go
Normal file
277
cid-fmt/main.go
Normal file
@@ -0,0 +1,277 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
c "github.com/ipfs/go-cid"
|
||||
|
||||
mb "github.com/multiformats/go-multibase"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s [-b multibase-code] [-v cid-version] <fmt-str> <cid> ...\n\n", os.Args[0])
|
||||
fmt.Fprintf(os.Stderr, "<fmt-str> is either 'prefix' or a printf style format string:\n%s", fmtRef)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
const fmtRef = `
|
||||
%% literal %
|
||||
%b multibase name
|
||||
%B multibase code
|
||||
%v version string
|
||||
%V version number
|
||||
%c codec name
|
||||
%C codec code
|
||||
%h multihash name
|
||||
%H multihash code
|
||||
%L hash digest length
|
||||
%m multihash encoded in base %b (with multibase prefix)
|
||||
%M multihash encoded in base %b without multibase prefix
|
||||
%d hash digest encoded in base %b (with multibase prefix)
|
||||
%D hash digest encoded in base %b without multibase prefix
|
||||
%s cid string encoded in base %b (1)
|
||||
%s cid string encoded in base %b without multibase prefix
|
||||
%P cid prefix: %v-%c-%h-%L
|
||||
|
||||
(1) For CID version 0 the multibase must be base58btc and no prefix is
|
||||
used. For Cid version 1 the multibase prefix is included.
|
||||
`
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
usage()
|
||||
}
|
||||
newBase := mb.Encoding(-1)
|
||||
var verConv func(cid *c.Cid) (*c.Cid, error)
|
||||
args := os.Args[1:]
|
||||
outer:
|
||||
for {
|
||||
switch args[0] {
|
||||
case "-b":
|
||||
if len(args) < 2 {
|
||||
usage()
|
||||
}
|
||||
if len(args[1]) != 1 {
|
||||
fmt.Fprintf(os.Stderr, "Error: Invalid multibase code: %s\n", args[1])
|
||||
os.Exit(2)
|
||||
}
|
||||
newBase = mb.Encoding(args[1][0])
|
||||
args = args[2:]
|
||||
case "-v":
|
||||
if len(args) < 2 {
|
||||
usage()
|
||||
}
|
||||
switch args[1] {
|
||||
case "0":
|
||||
verConv = toCidV0
|
||||
case "1":
|
||||
verConv = toCidV1
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Error: Invalid cid version: %s\n", args[1])
|
||||
os.Exit(2)
|
||||
}
|
||||
args = args[2:]
|
||||
default:
|
||||
break outer
|
||||
}
|
||||
}
|
||||
if len(args) < 2 {
|
||||
usage()
|
||||
}
|
||||
fmtStr := args[0]
|
||||
switch fmtStr {
|
||||
case "prefix":
|
||||
fmtStr = "%P"
|
||||
default:
|
||||
if strings.IndexByte(fmtStr, '%') == -1 {
|
||||
fmt.Fprintf(os.Stderr, "Error: Invalid format string: %s\n", fmtStr)
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
for _, cidStr := range args[1:] {
|
||||
base, cid, err := decode(cidStr)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stdout, "!INVALID_CID!\n")
|
||||
errorMsg("%s: %v", cidStr, err)
|
||||
// Don't abort on a bad cid
|
||||
continue
|
||||
}
|
||||
if newBase != -1 {
|
||||
base = newBase
|
||||
}
|
||||
if verConv != nil {
|
||||
cid, err = verConv(cid)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stdout, "!ERROR!\n")
|
||||
errorMsg("%s: %v", cidStr, err)
|
||||
// Don't abort on a bad conversion
|
||||
continue
|
||||
}
|
||||
}
|
||||
str, err := fmtCid(fmtStr, base, cid)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
||||
// An error here means a bad format string, no point in continuing
|
||||
os.Exit(2)
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, "%s\n", str)
|
||||
}
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
var exitCode = 0
|
||||
|
||||
func errorMsg(fmtStr string, a ...interface{}) {
|
||||
fmt.Fprintf(os.Stderr, "Error: ")
|
||||
fmt.Fprintf(os.Stderr, fmtStr, a...)
|
||||
fmt.Fprintf(os.Stderr, "\n")
|
||||
exitCode = 1
|
||||
}
|
||||
|
||||
func decode(v string) (mb.Encoding, *c.Cid, error) {
|
||||
if len(v) < 2 {
|
||||
return 0, nil, c.ErrCidTooShort
|
||||
}
|
||||
|
||||
if len(v) == 46 && v[:2] == "Qm" {
|
||||
hash, err := mh.FromB58String(v)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
return mb.Base58BTC, c.NewCidV0(hash), nil
|
||||
}
|
||||
|
||||
base, data, err := mb.Decode(v)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
cid, err := c.Cast(data)
|
||||
|
||||
return base, cid, err
|
||||
}
|
||||
|
||||
const ERR_STR = "!ERROR!"
|
||||
|
||||
func fmtCid(fmtStr string, base mb.Encoding, cid *c.Cid) (string, error) {
|
||||
p := cid.Prefix()
|
||||
out := new(bytes.Buffer)
|
||||
var err error
|
||||
for i := 0; i < len(fmtStr); i++ {
|
||||
if fmtStr[i] != '%' {
|
||||
out.WriteByte(fmtStr[i])
|
||||
continue
|
||||
}
|
||||
i++
|
||||
if i >= len(fmtStr) {
|
||||
return "", fmt.Errorf("premature end of format string")
|
||||
}
|
||||
switch fmtStr[i] {
|
||||
case '%':
|
||||
out.WriteByte('%')
|
||||
case 'b': // base name
|
||||
out.WriteString(baseToString(base))
|
||||
case 'B': // base code
|
||||
out.WriteByte(byte(base))
|
||||
case 'v': // version string
|
||||
fmt.Fprintf(out, "cidv%d", p.Version)
|
||||
case 'V': // version num
|
||||
fmt.Fprintf(out, "%d", p.Version)
|
||||
case 'c': // codec name
|
||||
out.WriteString(codecToString(p.Codec))
|
||||
case 'C': // codec code
|
||||
fmt.Fprintf(out, "%d", p.Codec)
|
||||
case 'h': // hash fun name
|
||||
out.WriteString(hashToString(p.MhType))
|
||||
case 'H': // hash fun code
|
||||
fmt.Fprintf(out, "%d", p.MhType)
|
||||
case 'L': // hash length
|
||||
fmt.Fprintf(out, "%d", p.MhLength)
|
||||
case 'm', 'M': // multihash encoded in base %b
|
||||
out.WriteString(encode(base, cid.Hash(), fmtStr[i] == 'M'))
|
||||
case 'd', 'D': // hash digest encoded in base %b
|
||||
dec, err := mh.Decode(cid.Hash())
|
||||
if err != nil {
|
||||
out.WriteString(ERR_STR)
|
||||
errorMsg("%v", err)
|
||||
continue
|
||||
}
|
||||
out.WriteString(encode(base, dec.Digest, fmtStr[i] == 'D'))
|
||||
case 's': // cid string encoded in base %b
|
||||
str, err := cid.StringOfBase(base)
|
||||
if err != nil {
|
||||
out.WriteString(ERR_STR)
|
||||
errorMsg("%v", err)
|
||||
continue
|
||||
}
|
||||
out.WriteString(str)
|
||||
case 'S': // cid string without base prefix
|
||||
out.WriteString(encode(base, cid.Bytes(), true))
|
||||
case 'P': // prefix
|
||||
fmt.Fprintf(out, "cidv%d-%s-%s-%d",
|
||||
p.Version,
|
||||
codecToString(p.Codec),
|
||||
hashToString(p.MhType),
|
||||
p.MhLength,
|
||||
)
|
||||
default:
|
||||
return "", fmt.Errorf("unrecognized specifier in format string: %c", fmtStr[i])
|
||||
}
|
||||
|
||||
}
|
||||
return out.String(), err
|
||||
}
|
||||
|
||||
func baseToString(base mb.Encoding) string {
|
||||
// FIXME: Use lookup tables when they are added to go-multibase
|
||||
switch base {
|
||||
case mb.Base58BTC:
|
||||
return "base58btc"
|
||||
default:
|
||||
return fmt.Sprintf("base?%c", base)
|
||||
}
|
||||
}
|
||||
|
||||
func codecToString(num uint64) string {
|
||||
name, ok := c.CodecToStr[num]
|
||||
if !ok {
|
||||
return fmt.Sprintf("codec?%d", num)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func hashToString(num uint64) string {
|
||||
name, ok := mh.Codes[num]
|
||||
if !ok {
|
||||
return fmt.Sprintf("hash?%d", num)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func encode(base mb.Encoding, data []byte, strip bool) string {
|
||||
str, err := mb.Encode(base, data)
|
||||
if err != nil {
|
||||
errorMsg("%v", err)
|
||||
return ERR_STR
|
||||
}
|
||||
if strip {
|
||||
return str[1:]
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
func toCidV0(cid *c.Cid) (*c.Cid, error) {
|
||||
if cid.Type() != c.DagProtobuf {
|
||||
return nil, fmt.Errorf("can't convert non-protobuf nodes to cidv0")
|
||||
}
|
||||
return c.NewCidV0(cid.Hash()), nil
|
||||
}
|
||||
|
||||
func toCidV1(cid *c.Cid) (*c.Cid, error) {
|
||||
return c.NewCidV1(cid.Type(), cid.Hash()), nil
|
||||
}
|
||||
109
cid-fmt/main_test.go
Normal file
109
cid-fmt/main_test.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
mb "github.com/multiformats/go-multibase"
|
||||
)
|
||||
|
||||
func TestFmt(t *testing.T) {
|
||||
cids := map[string]string{
|
||||
"cidv0": "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn",
|
||||
"cidv1": "zdj7WfLr9DhLrb1hsoSi4fSdjjxuZmeqgEtBPWxMLtPbDNbFD",
|
||||
}
|
||||
tests := []struct {
|
||||
cidId string
|
||||
newBase mb.Encoding
|
||||
fmtStr string
|
||||
result string
|
||||
}{
|
||||
{"cidv0", -1, "%P", "cidv0-protobuf-sha2-256-32"},
|
||||
{"cidv0", -1, "%b-%v-%c-%h-%L", "base58btc-cidv0-protobuf-sha2-256-32"},
|
||||
{"cidv0", -1, "%s", "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"},
|
||||
{"cidv0", -1, "%S", "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"},
|
||||
{"cidv0", -1, "ver#%V/#%C/#%H/%L", "ver#0/#112/#18/32"},
|
||||
{"cidv0", -1, "%m", "zQmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"},
|
||||
{"cidv0", -1, "%M", "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"},
|
||||
{"cidv0", -1, "%d", "z72gdmFAgRzYHkJzKiL8MgMMRW3BTSCGyDHroPxJbxMJn"},
|
||||
{"cidv0", -1, "%D", "72gdmFAgRzYHkJzKiL8MgMMRW3BTSCGyDHroPxJbxMJn"},
|
||||
{"cidv0", 'B', "%S", "CIQFTFEEHEDF6KLBT32BFAGLXEZL4UWFNWM4LFTLMXQBCERZ6CMLX3Y"},
|
||||
{"cidv0", 'B', "%B%S", "BCIQFTFEEHEDF6KLBT32BFAGLXEZL4UWFNWM4LFTLMXQBCERZ6CMLX3Y"},
|
||||
{"cidv1", -1, "%P", "cidv1-protobuf-sha2-256-32"},
|
||||
{"cidv1", -1, "%b-%v-%c-%h-%L", "base58btc-cidv1-protobuf-sha2-256-32"},
|
||||
{"cidv1", -1, "%s", "zdj7WfLr9DhLrb1hsoSi4fSdjjxuZmeqgEtBPWxMLtPbDNbFD"},
|
||||
{"cidv1", -1, "%S", "dj7WfLr9DhLrb1hsoSi4fSdjjxuZmeqgEtBPWxMLtPbDNbFD"},
|
||||
{"cidv1", -1, "ver#%V/#%C/#%H/%L", "ver#1/#112/#18/32"},
|
||||
{"cidv1", -1, "%m", "zQmYFbmndVP7QqAVWyKhpmMuQHMaD88pkK57RgYVimmoh5H"},
|
||||
{"cidv1", -1, "%M", "QmYFbmndVP7QqAVWyKhpmMuQHMaD88pkK57RgYVimmoh5H"},
|
||||
{"cidv1", -1, "%d", "zAux4gVVsLRMXtsZ9fd3tFEZN4jGYB6kP37fgoZNTc11H"},
|
||||
{"cidv1", -1, "%D", "Aux4gVVsLRMXtsZ9fd3tFEZN4jGYB6kP37fgoZNTc11H"},
|
||||
{"cidv1", 'B', "%s", "BAFYBEIETJGSRL3EQPQPCABV3G6IUBYTSIFVQ24XRRHD3JUETSKLTGQ7DJA"},
|
||||
{"cidv1", 'B', "%S", "AFYBEIETJGSRL3EQPQPCABV3G6IUBYTSIFVQ24XRRHD3JUETSKLTGQ7DJA"},
|
||||
{"cidv1", 'B', "%B%S", "BAFYBEIETJGSRL3EQPQPCABV3G6IUBYTSIFVQ24XRRHD3JUETSKLTGQ7DJA"},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
name := fmt.Sprintf("%s/%s", tc.cidId, tc.fmtStr)
|
||||
if tc.newBase != -1 {
|
||||
name = fmt.Sprintf("%s/%c", name, tc.newBase)
|
||||
}
|
||||
cidStr := cids[tc.cidId]
|
||||
t.Run(name, func(t *testing.T) {
|
||||
testFmt(t, cidStr, tc.newBase, tc.fmtStr, tc.result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testFmt(t *testing.T, cidStr string, newBase mb.Encoding, fmtStr string, result string) {
|
||||
base, cid, err := decode(cidStr)
|
||||
if newBase != -1 {
|
||||
base = newBase
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
str, err := fmtCid(fmtStr, base, cid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if str != result {
|
||||
t.Error(fmt.Sprintf("expected: %s; but got: %s", result, str))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCidConv(t *testing.T) {
|
||||
cidv0 := "QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn"
|
||||
cidv1 := "zdj7WbTaiJT1fgatdet9Ei9iDB5hdCxkbVyhyh8YTUnXMiwYi"
|
||||
_, cid, err := decode(cidv0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cid, err = toCidV1(cid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if cid.String() != cidv1 {
|
||||
t.Fatal("conversion failure")
|
||||
}
|
||||
cid, err = toCidV0(cid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cidStr := cid.String()
|
||||
if cidStr != cidv0 {
|
||||
t.Error(fmt.Sprintf("conversion failure, expected: %s; but got: %s", cidv0, cidStr))
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadCidConv(t *testing.T) {
|
||||
// this cid is a raw leaf and should not be able to convert to cidv0
|
||||
cidv1 := "zb2rhhzX7uSKrtQ2ZZXFAabKiKFYZrJqKY2KE1cJ8yre2GSWZ"
|
||||
_, cid, err := decode(cidv1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cid, err = toCidV0(cid)
|
||||
if err == nil {
|
||||
t.Fatal("expected failure")
|
||||
}
|
||||
}
|
||||
88
cid.go
88
cid.go
@@ -47,6 +47,10 @@ var (
|
||||
// ErrCidTooShort means that the cid passed to decode was not long
|
||||
// enough to be a valid Cid
|
||||
ErrCidTooShort = errors.New("cid too short")
|
||||
|
||||
// ErrInvalidEncoding means that selected encoding is not supported
|
||||
// by this Cid version
|
||||
ErrInvalidEncoding = errors.New("invalid base encoding")
|
||||
)
|
||||
|
||||
// These are multicodec-packed content types. The should match
|
||||
@@ -58,6 +62,8 @@ const (
|
||||
DagProtobuf = 0x70
|
||||
DagCBOR = 0x71
|
||||
|
||||
GitRaw = 0x78
|
||||
|
||||
EthBlock = 0x90
|
||||
EthBlockList = 0x91
|
||||
EthTxTrie = 0x92
|
||||
@@ -73,6 +79,49 @@ const (
|
||||
ZcashTx = 0xc1
|
||||
)
|
||||
|
||||
// Codecs maps the name of a codec to its type
|
||||
var Codecs = map[string]uint64{
|
||||
"v0": DagProtobuf,
|
||||
"raw": Raw,
|
||||
"protobuf": DagProtobuf,
|
||||
"cbor": DagCBOR,
|
||||
"git-raw": GitRaw,
|
||||
"eth-block": EthBlock,
|
||||
"eth-block-list": EthBlockList,
|
||||
"eth-tx-trie": EthTxTrie,
|
||||
"eth-tx": EthTx,
|
||||
"eth-tx-receipt-trie": EthTxReceiptTrie,
|
||||
"eth-tx-receipt": EthTxReceipt,
|
||||
"eth-state-trie": EthStateTrie,
|
||||
"eth-account-snapshot": EthAccountSnapshot,
|
||||
"eth-storage-trie": EthStorageTrie,
|
||||
"bitcoin-block": BitcoinBlock,
|
||||
"bitcoin-tx": BitcoinTx,
|
||||
"zcash-block": ZcashBlock,
|
||||
"zcash-tx": ZcashTx,
|
||||
}
|
||||
|
||||
// CodecToStr maps the numeric codec to its name
|
||||
var CodecToStr = map[uint64]string{
|
||||
Raw: "raw",
|
||||
DagProtobuf: "protobuf",
|
||||
DagCBOR: "cbor",
|
||||
GitRaw: "git-raw",
|
||||
EthBlock: "eth-block",
|
||||
EthBlockList: "eth-block-list",
|
||||
EthTxTrie: "eth-tx-trie",
|
||||
EthTx: "eth-tx",
|
||||
EthTxReceiptTrie: "eth-tx-receipt-trie",
|
||||
EthTxReceipt: "eth-tx-receipt",
|
||||
EthStateTrie: "eth-state-trie",
|
||||
EthAccountSnapshot: "eth-account-snapshot",
|
||||
EthStorageTrie: "eth-storage-trie",
|
||||
BitcoinBlock: "bitcoin-block",
|
||||
BitcoinTx: "bitcoin-tx",
|
||||
ZcashBlock: "zcash-block",
|
||||
ZcashTx: "zcash-tx",
|
||||
}
|
||||
|
||||
// NewCidV0 returns a Cid-wrapped multihash.
|
||||
// They exist to allow IPFS to work with Cids while keeping
|
||||
// compatibility with the plain-multihash format used used in IPFS.
|
||||
@@ -95,6 +144,27 @@ func NewCidV1(codecType uint64, mhash mh.Multihash) *Cid {
|
||||
}
|
||||
}
|
||||
|
||||
// NewPrefixV0 returns a CIDv0 prefix with the specified multihash type.
|
||||
func NewPrefixV0(mhType uint64) Prefix {
|
||||
return Prefix{
|
||||
MhType: mhType,
|
||||
MhLength: mh.DefaultLengths[mhType],
|
||||
Version: 0,
|
||||
Codec: DagProtobuf,
|
||||
}
|
||||
}
|
||||
|
||||
// NewPrefixV1 returns a CIDv1 prefix with the specified codec and multihash
|
||||
// type.
|
||||
func NewPrefixV1(codecType uint64, mhType uint64) Prefix {
|
||||
return Prefix{
|
||||
MhType: mhType,
|
||||
MhLength: mh.DefaultLengths[mhType],
|
||||
Version: 1,
|
||||
Codec: codecType,
|
||||
}
|
||||
}
|
||||
|
||||
// Cid represents a self-describing content adressed
|
||||
// identifier. It is formed by a Version, a Codec (which indicates
|
||||
// a multicodec-packed content type) and a Multihash.
|
||||
@@ -245,6 +315,22 @@ func (c *Cid) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
// String returns the string representation of a Cid
|
||||
// encoded is selected base
|
||||
func (c *Cid) StringOfBase(base mbase.Encoding) (string, error) {
|
||||
switch c.version {
|
||||
case 0:
|
||||
if base != mbase.Base58BTC {
|
||||
return "", ErrInvalidEncoding
|
||||
}
|
||||
return c.hash.B58String(), nil
|
||||
case 1:
|
||||
return mbase.Encode(base, c.bytesV1())
|
||||
default:
|
||||
panic("not possible to reach this point")
|
||||
}
|
||||
}
|
||||
|
||||
// Hash returns the multihash contained by a Cid.
|
||||
func (c *Cid) Hash() mh.Multihash {
|
||||
return c.hash
|
||||
@@ -324,7 +410,7 @@ func (c *Cid) UnmarshalJSON(b []byte) error {
|
||||
//
|
||||
// Note that this formatting comes from the IPLD specification
|
||||
// (https://github.com/ipld/specs/tree/master/ipld)
|
||||
func (c *Cid) MarshalJSON() ([]byte, error) {
|
||||
func (c Cid) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf("{\"/\":\"%s\"}", c.String())), nil
|
||||
}
|
||||
|
||||
|
||||
185
cid_test.go
185
cid_test.go
@@ -8,9 +8,33 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
mbase "github.com/multiformats/go-multibase"
|
||||
mh "github.com/multiformats/go-multihash"
|
||||
)
|
||||
|
||||
// Copying the "silly test" idea from
|
||||
// https://github.com/multiformats/go-multihash/blob/7aa9f26a231c6f34f4e9fad52bf580fd36627285/multihash_test.go#L13
|
||||
// Makes it so changing the table accidentally has to happen twice.
|
||||
var tCodecs = map[uint64]string{
|
||||
Raw: "raw",
|
||||
DagProtobuf: "protobuf",
|
||||
DagCBOR: "cbor",
|
||||
GitRaw: "git-raw",
|
||||
EthBlock: "eth-block",
|
||||
EthBlockList: "eth-block-list",
|
||||
EthTxTrie: "eth-tx-trie",
|
||||
EthTx: "eth-tx",
|
||||
EthTxReceiptTrie: "eth-tx-receipt-trie",
|
||||
EthTxReceipt: "eth-tx-receipt",
|
||||
EthStateTrie: "eth-state-trie",
|
||||
EthAccountSnapshot: "eth-account-snapshot",
|
||||
EthStorageTrie: "eth-storage-trie",
|
||||
BitcoinBlock: "bitcoin-block",
|
||||
BitcoinTx: "bitcoin-tx",
|
||||
ZcashBlock: "zcash-block",
|
||||
ZcashTx: "zcash-tx",
|
||||
}
|
||||
|
||||
func assertEqual(t *testing.T, a, b *Cid) {
|
||||
if a.codec != b.codec {
|
||||
t.Fatal("mismatch on type")
|
||||
@@ -25,6 +49,26 @@ func assertEqual(t *testing.T, a, b *Cid) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTable(t *testing.T) {
|
||||
if len(tCodecs) != len(Codecs)-1 {
|
||||
t.Errorf("Item count mismatch in the Table of Codec. Should be %d, got %d", len(tCodecs)+1, len(Codecs))
|
||||
}
|
||||
|
||||
for k, v := range tCodecs {
|
||||
if Codecs[v] != k {
|
||||
t.Errorf("Table mismatch: 0x%x %s", k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The table returns cid.DagProtobuf for "v0"
|
||||
// so we test it apart
|
||||
func TestTableForV0(t *testing.T) {
|
||||
if Codecs["v0"] != DagProtobuf {
|
||||
t.Error("Table mismatch: Codecs[\"v0\"] should resolve to DagProtobuf (0x70)")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBasicMarshaling(t *testing.T) {
|
||||
h, err := mh.Sum([]byte("TEST"), mh.SHA3, 4)
|
||||
if err != nil {
|
||||
@@ -55,6 +99,60 @@ func TestBasicMarshaling(t *testing.T) {
|
||||
assertEqual(t, cid, out2)
|
||||
}
|
||||
|
||||
func TestBasesMarshaling(t *testing.T) {
|
||||
h, err := mh.Sum([]byte("TEST"), mh.SHA3, 4)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cid := &Cid{
|
||||
codec: 7,
|
||||
version: 1,
|
||||
hash: h,
|
||||
}
|
||||
|
||||
data := cid.Bytes()
|
||||
|
||||
out, err := Cast(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assertEqual(t, cid, out)
|
||||
|
||||
testBases := []mbase.Encoding{
|
||||
mbase.Base16,
|
||||
mbase.Base32,
|
||||
mbase.Base32hex,
|
||||
mbase.Base32pad,
|
||||
mbase.Base32hexPad,
|
||||
mbase.Base58BTC,
|
||||
mbase.Base58Flickr,
|
||||
mbase.Base64pad,
|
||||
mbase.Base64urlPad,
|
||||
mbase.Base64url,
|
||||
mbase.Base64,
|
||||
}
|
||||
|
||||
for _, b := range testBases {
|
||||
s, err := cid.StringOfBase(b)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if s[0] != byte(b) {
|
||||
t.Fatal("Invalid multibase header")
|
||||
}
|
||||
|
||||
out2, err := Decode(s)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
assertEqual(t, cid, out2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEmptyString(t *testing.T) {
|
||||
_, err := Decode("")
|
||||
if err == nil {
|
||||
@@ -91,6 +189,64 @@ func TestV0ErrorCases(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewPrefixV1(t *testing.T) {
|
||||
data := []byte("this is some test content")
|
||||
|
||||
// Construct c1
|
||||
prefix := NewPrefixV1(DagCBOR, mh.SHA2_256)
|
||||
c1, err := prefix.Sum(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if c1.Prefix() != prefix {
|
||||
t.Fatal("prefix not preserved")
|
||||
}
|
||||
|
||||
// Construct c2
|
||||
hash, err := mh.Sum(data, mh.SHA2_256, -1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c2 := NewCidV1(DagCBOR, hash)
|
||||
|
||||
if !c1.Equals(c2) {
|
||||
t.Fatal("cids mismatch")
|
||||
}
|
||||
if c1.Prefix() != c2.Prefix() {
|
||||
t.Fatal("prefixes mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewPrefixV0(t *testing.T) {
|
||||
data := []byte("this is some test content")
|
||||
|
||||
// Construct c1
|
||||
prefix := NewPrefixV0(mh.SHA2_256)
|
||||
c1, err := prefix.Sum(data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if c1.Prefix() != prefix {
|
||||
t.Fatal("prefix not preserved")
|
||||
}
|
||||
|
||||
// Construct c2
|
||||
hash, err := mh.Sum(data, mh.SHA2_256, -1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c2 := NewCidV0(hash)
|
||||
|
||||
if !c1.Equals(c2) {
|
||||
t.Fatal("cids mismatch")
|
||||
}
|
||||
if c1.Prefix() != c2.Prefix() {
|
||||
t.Fatal("prefixes mismatch")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrefixRoundtrip(t *testing.T) {
|
||||
data := []byte("this is some test content")
|
||||
hash, _ := mh.Sum(data, mh.SHA2_256, -1)
|
||||
@@ -227,3 +383,32 @@ func TestFromJson(t *testing.T) {
|
||||
t.Fatal("json parsing failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestJsonRoundTrip(t *testing.T) {
|
||||
exp, err := Decode("zb2rhhFAEMepUBbGyP1k8tGfz7BSciKXP6GHuUeUsJBaK6cqG")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Verify it works for a *Cid.
|
||||
enc, err := json.Marshal(exp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var actual Cid
|
||||
err = json.Unmarshal(enc, &actual)
|
||||
if !exp.Equals(&actual) {
|
||||
t.Fatal("cids not equal for *Cid")
|
||||
}
|
||||
|
||||
// Verify it works for a Cid.
|
||||
enc, err = json.Marshal(*exp)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var actual2 Cid
|
||||
err = json.Unmarshal(enc, &actual2)
|
||||
if !exp.Equals(&actual2) {
|
||||
t.Fatal("cids not equal for Cid")
|
||||
}
|
||||
}
|
||||
|
||||
3
codecov.yml
Normal file
3
codecov.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
coverage:
|
||||
range: "50...100"
|
||||
comment: off
|
||||
10
package.json
10
package.json
@@ -9,15 +9,15 @@
|
||||
"gxDependencies": [
|
||||
{
|
||||
"author": "whyrusleeping",
|
||||
"hash": "QmVGtdTZdTFaLsaj2RwdVG8jcjNNcp1DE914DKZ2kHmXHw",
|
||||
"hash": "QmPnFwZ2JXKnXgMw8CdBPxn7FWh6LLdjUjxV1fKHuJnkr8",
|
||||
"name": "go-multihash",
|
||||
"version": "1.0.4"
|
||||
"version": "1.0.8"
|
||||
},
|
||||
{
|
||||
"author": "whyrusleeping",
|
||||
"hash": "QmcxkxTVuURV2Ptse8TvkqH5BQDwV62X1x19JqqvbBzwUM",
|
||||
"hash": "QmexBtiTTEwwn42Yi6ouKt6VqzpA6wjJgiW1oh9VfaRrup",
|
||||
"name": "go-multibase",
|
||||
"version": "0.2.3"
|
||||
"version": "0.2.6"
|
||||
}
|
||||
],
|
||||
"gxVersion": "0.8.0",
|
||||
@@ -25,6 +25,6 @@
|
||||
"license": "MIT",
|
||||
"name": "go-cid",
|
||||
"releaseCmd": "git commit -a -m \"gx publish $VERSION\"",
|
||||
"version": "0.7.12"
|
||||
"version": "0.7.22"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user