From 5d044d874ac9961a3ccb2548e78956af7cfde334 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Thu, 17 Aug 2023 12:32:25 +0800 Subject: [PATCH 01/18] feat: ceramic stream_id --- ceramic/streamid.go | 100 ++++++++++++++++++++++++++++++++++++++ ceramic/streamid_test.go | 100 ++++++++++++++++++++++++++++++++++++++ ceramic/streamid_utils.go | 22 +++++++++ go.mod | 14 ++++++ go.sum | 65 ++++++++++++++++++++++++- 5 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 ceramic/streamid.go create mode 100644 ceramic/streamid_test.go create mode 100644 ceramic/streamid_utils.go diff --git a/ceramic/streamid.go b/ceramic/streamid.go new file mode 100644 index 0000000..7770a9d --- /dev/null +++ b/ceramic/streamid.go @@ -0,0 +1,100 @@ +package ceramic + +import ( + "bytes" + "encoding/binary" + "fmt" + + "github.com/ipfs/go-cid" + "github.com/multiformats/go-multibase" + "github.com/multiformats/go-multicodec" +) + +type StreamIdType uint64 + +// https://github.com/ceramicnetwork/CIPs/blob/main/CIPs/cip-59.md +const ( + StreamIdTypeTile StreamIdType = iota + StreamIdTypeCaip10Link + StreamIdTypeModel + StreamIdTypeModelInstanceDocument + StreamIdTypeUnloadable + StreamIdTypeEventId + + StreamIDCodec uint64 = 0xce + + StreamIDEncoding = multibase.Base36 +) + +type StreamID struct { + Type StreamIdType + Cid cid.Cid + Log cid.Cid +} + +var ( + streamIdEncoder = multibase.MustNewEncoder(StreamIDEncoding) +) + +func (id StreamID) String() string { + var buf bytes.Buffer + buf.Write(binary.AppendUvarint(nil, StreamIDCodec)) + buf.Write(binary.AppendUvarint(nil, uint64(id.Type))) + buf.Write(id.Cid.Bytes()) + if id.Log.ByteLen() != 0 { + buf.Write(id.Log.Bytes()) + } + return streamIdEncoder.Encode(buf.Bytes()) +} + +func NewStreamID(t StreamIdType, cidStr ...string) (id StreamID, err error) { + if len(cidStr) != 1 && len(cidStr) != 2 { + err = fmt.Errorf("unexpect cid length, could only 1 or 2 (genesis cid and log cid)") + } + id.Type = t + + return +} + +func ParseStreamID(str string) (id StreamID, err error) { + var ( + buf []byte + encoding multibase.Encoding + streamCodec uint64 + streamType uint64 + ) + + if encoding, buf, err = multibase.Decode(str); err != nil { + return + } + if encoding != StreamIDEncoding { + err = fmt.Errorf("unexpected encoding id %c with input %s", encoding, str) + return + } + // check + streamCodec, buf, _, err = GetUVarInt(buf) + if err != nil { + return + } + if multicodec.Code(streamCodec) != multicodec.Streamid { + err = fmt.Errorf("unexpected multicodec %x != 0xce", buf[0]) + return + } + + // check + streamType, buf, _, err = GetUVarInt(buf) + if err != nil { + return + } + id.Type = StreamIdType(streamType) + var nr int + if nr, id.Cid, err = cid.CidFromBytes(buf); err != nil { + return + } + if len(buf) != nr { + if _, id.Log, err = cid.CidFromBytes(buf[nr:]); err != nil { + return + } + } + return +} diff --git a/ceramic/streamid_test.go b/ceramic/streamid_test.go new file mode 100644 index 0000000..9b50aae --- /dev/null +++ b/ceramic/streamid_test.go @@ -0,0 +1,100 @@ +package ceramic_test + +import ( + "reflect" + "testing" + + "github.com/dataverse-os/dapp-backend/ceramic" + "github.com/ipfs/go-cid" +) + +func TestStreamID_String(t *testing.T) { + type fields struct { + Type ceramic.StreamIdType + Cid cid.Cid + Log cid.Cid + } + tests := []struct { + name string + fields fields + want string + }{ + { + name: "stream_id", + fields: fields{ + Type: ceramic.StreamIdTypeModelInstanceDocument, + Cid: cid.MustParse("bagcqceragiwmxdtelb45wjl6calr45bh4rpcipbmh3t3skrkjvv3foihfmrq"), + }, + want: "kjzl6kcym7w8y64sx1g97dy5v3xmm49mnx0p9mofs44t6y0y7wp2ko8z7w9azhf", + }, + { + name: "commit_id", + fields: fields{ + Type: ceramic.StreamIdTypeTile, + Cid: cid.MustParse("bagcqcerakszw2vsovxznyp5gfnpdj4cqm2xiv76yd24wkjewhhykovorwo6a"), + Log: cid.MustParse("bagjqcgzaday6dzalvmy5ady2m5a5legq5zrbsnlxfc2bfxej532ds7htpova"), + }, + want: "k1dpgaqe3i64kjqcp801r3sn7ysi5i0k7nxvs7j351s7kewfzr3l7mdxnj7szwo4kr9mn2qki5nnj0cv836ythy1t1gya9s25cn1nexst3jxi5o3h6qprfyju", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + id := ceramic.StreamID{ + Type: tt.fields.Type, + Cid: tt.fields.Cid, + Log: tt.fields.Log, + } + if got := id.String(); got != tt.want { + t.Errorf("StreamID.String() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestParseStreamID(t *testing.T) { + type args struct { + str string + } + tests := []struct { + name string + args args + wantId ceramic.StreamID + wantErr bool + }{ + { + name: "stream_id", + args: args{ + str: "kjzl6kcym7w8y64sx1g97dy5v3xmm49mnx0p9mofs44t6y0y7wp2ko8z7w9azhf", + }, + wantId: ceramic.StreamID{ + Type: ceramic.StreamIdTypeModelInstanceDocument, + Cid: cid.MustParse("bagcqceragiwmxdtelb45wjl6calr45bh4rpcipbmh3t3skrkjvv3foihfmrq"), + }, + wantErr: false, + }, + { + name: "commit_id", + args: args{ + str: "k1dpgaqe3i64kjqcp801r3sn7ysi5i0k7nxvs7j351s7kewfzr3l7mdxnj7szwo4kr9mn2qki5nnj0cv836ythy1t1gya9s25cn1nexst3jxi5o3h6qprfyju", + }, + wantId: ceramic.StreamID{ + Type: ceramic.StreamIdTypeTile, + Cid: cid.MustParse("bagcqcerakszw2vsovxznyp5gfnpdj4cqm2xiv76yd24wkjewhhykovorwo6a"), + Log: cid.MustParse("bagjqcgzaday6dzalvmy5ady2m5a5legq5zrbsnlxfc2bfxej532ds7htpova"), + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotId, err := ceramic.ParseStreamID(tt.args.str) + if (err != nil) != tt.wantErr { + t.Errorf("ParseStreamID() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotId, tt.wantId) { + t.Errorf("ParseStreamID() = %v, want %v", gotId, tt.wantId) + } + }) + } +} diff --git a/ceramic/streamid_utils.go b/ceramic/streamid_utils.go new file mode 100644 index 0000000..6e7a6e5 --- /dev/null +++ b/ceramic/streamid_utils.go @@ -0,0 +1,22 @@ +package ceramic + +import ( + "encoding/binary" + "fmt" +) + +// GetUVarInt returns the uint, rest of the buffer, bytes consumed, and error +// https://github.com/multiformats/unsigned-varint +func GetUVarInt(input []byte) (uint64, []byte, int, error) { + code, idx := binary.Uvarint(input) + if idx <= 0 { + return 0, input, idx, fmt.Errorf("unable to unpack unsigned var int %v", input) + } + return code, input[idx:], idx, nil +} + +func PutUVarInt(code uint64) []byte { + buf := make([]byte, 10) + n := binary.PutUvarint(buf, uint64(code)) + return buf[:n] +} diff --git a/go.mod b/go.mod index 9505ae4..fcc5211 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,11 @@ require ( github.com/gin-gonic/gin v1.9.1 github.com/google/uuid v1.3.0 github.com/graphql-go/graphql v0.8.1 + github.com/hasura/go-graphql-client v0.10.0 + github.com/ipfs/go-cid v0.4.1 + github.com/lib/pq v1.10.9 + github.com/multiformats/go-multibase v0.2.0 + github.com/multiformats/go-multicodec v0.9.0 github.com/pkg/errors v0.9.1 github.com/samber/lo v1.38.1 github.com/spf13/cobra v1.7.0 @@ -41,11 +46,19 @@ require ( github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.16.7 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/mattn/go-isatty v0.0.19 // indirect + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect + github.com/minio/sha256-simd v1.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/mr-tron/base58 v1.2.0 // indirect + github.com/multiformats/go-base32 v0.0.3 // indirect + github.com/multiformats/go-base36 v0.1.0 // indirect + github.com/multiformats/go-multihash v0.0.15 // indirect + github.com/multiformats/go-varint v0.0.6 // indirect github.com/pelletier/go-toml/v2 v2.0.9 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tidwall/match v1.1.1 // indirect @@ -60,4 +73,5 @@ require ( golang.org/x/text v0.11.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gorm.io/driver/mysql v1.4.7 // indirect + nhooyr.io/websocket v1.8.7 // indirect ) diff --git a/go.sum b/go.sum index 300d5f7..60f324d 100644 --- a/go.sum +++ b/go.sum @@ -44,24 +44,34 @@ github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0 github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= @@ -70,21 +80,32 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= +github.com/graph-gophers/graphql-transport-ws v0.0.2 h1:DbmSkbIGzj8SvHei6n8Mh9eLQin8PtA8xY9eCzjRpvo= github.com/graphql-go/graphql v0.8.1 h1:p7/Ou/WpmulocJeEx7wjQy611rtXGQaAcXGqanuMMgc= github.com/graphql-go/graphql v0.8.1/go.mod h1:nKiHzRM0qopJEwCITUuIsxk9PlVlwIiiI8pnJEhordQ= +github.com/hasura/go-graphql-client v0.10.0 h1:eQm/ap/rqxMG6yAGe6J+FkXu1VqJ9p21E63vz0A7zLQ= +github.com/hasura/go-graphql-client v0.10.0/go.mod h1:z9UPkMmCBMuJjvBEtdE6F+oTR2r15AcjirVNq/8P+Ig= github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= +github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= @@ -99,10 +120,14 @@ github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -115,9 +140,13 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -125,11 +154,30 @@ github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/Qd github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= +github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= +github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4= +github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= +github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg= +github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= +github.com/multiformats/go-multihash v0.0.15 h1:hWOPdrNqDjwHDx82vsYGSDZNyktOJJ2dzZJzFkOV1jM= +github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJzmCl4jb1alC0OvHiHg= +github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= +github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= 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= @@ -161,6 +209,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -181,7 +230,9 @@ github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= @@ -193,6 +244,7 @@ golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc= golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= @@ -202,6 +254,7 @@ golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xpp golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -215,7 +268,10 @@ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -225,16 +281,19 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= @@ -252,6 +311,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -268,4 +329,6 @@ gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 h1:9qNbmu21nNThCNnF5i2R3kw2aL27U8ZwbzccNjOmW0g= gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= +nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= From f3465b7cd2dcb3ddf865e2128672561bcc8e71bb Mon Sep 17 00:00:00 2001 From: FDKevin Date: Thu, 17 Aug 2023 12:47:12 +0800 Subject: [PATCH 02/18] chore: bump version --- js-scripts/package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/js-scripts/package.json b/js-scripts/package.json index bcd1a30..bb9d828 100644 --- a/js-scripts/package.json +++ b/js-scripts/package.json @@ -12,18 +12,18 @@ "author": "", "license": "ISC", "devDependencies": { - "@ceramicnetwork/http-client": "^2.23.0", + "@ceramicnetwork/http-client": "^2.28.0", "@composedb/devtools": "^0.4.4", "@composedb/types": "^0.4.4", - "@types/node": "^18.16.19", + "@types/node": "^18.17.5", "esbuild": "^0.17.19", "typescript": "^4.9.5" }, "type": "module", "dependencies": { - "dids": "^4.0.3", - "key-did-provider-ed25519": "^3.0.1", + "dids": "^4.0.4", + "key-did-provider-ed25519": "^3.0.2", "key-did-resolver": "^3.0.0", - "uint8arrays": "^4.0.4" + "uint8arrays": "^4.0.6" } } \ No newline at end of file From 30e6853733dd36ad6b5812fc737c1c547467a651 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Thu, 17 Aug 2023 13:29:05 +0800 Subject: [PATCH 03/18] chore: add cartonne --- js-scripts/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/js-scripts/package.json b/js-scripts/package.json index bb9d828..f6d3ea6 100644 --- a/js-scripts/package.json +++ b/js-scripts/package.json @@ -21,6 +21,7 @@ }, "type": "module", "dependencies": { + "cartonne": "^2.2.0", "dids": "^4.0.4", "key-did-provider-ed25519": "^3.0.2", "key-did-resolver": "^3.0.0", From 4124109feadd8958149d15e5dd943c21969eee5c Mon Sep 17 00:00:00 2001 From: FDKevin Date: Thu, 17 Aug 2023 13:52:05 +0800 Subject: [PATCH 04/18] chore: add dag-jose --- js-scripts/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/js-scripts/package.json b/js-scripts/package.json index f6d3ea6..bdc2902 100644 --- a/js-scripts/package.json +++ b/js-scripts/package.json @@ -22,6 +22,7 @@ "type": "module", "dependencies": { "cartonne": "^2.2.0", + "dag-jose": "^4.0.0", "dids": "^4.0.4", "key-did-provider-ed25519": "^3.0.2", "key-did-resolver": "^3.0.0", From cb33f0ad7fcdc36e42a3837cfe0206f9f6cc2183 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Thu, 17 Aug 2023 14:07:12 +0800 Subject: [PATCH 05/18] update --- ceramic/streamid.go | 16 +++++++++------- ceramic/streamid_utils.go | 22 ---------------------- 2 files changed, 9 insertions(+), 29 deletions(-) delete mode 100644 ceramic/streamid_utils.go diff --git a/ceramic/streamid.go b/ceramic/streamid.go index 7770a9d..a87de45 100644 --- a/ceramic/streamid.go +++ b/ceramic/streamid.go @@ -21,8 +21,6 @@ const ( StreamIdTypeUnloadable StreamIdTypeEventId - StreamIDCodec uint64 = 0xce - StreamIDEncoding = multibase.Base36 ) @@ -38,7 +36,7 @@ var ( func (id StreamID) String() string { var buf bytes.Buffer - buf.Write(binary.AppendUvarint(nil, StreamIDCodec)) + buf.Write(binary.AppendUvarint(nil, uint64(multicodec.Streamid))) buf.Write(binary.AppendUvarint(nil, uint64(id.Type))) buf.Write(id.Cid.Bytes()) if id.Log.ByteLen() != 0 { @@ -62,6 +60,7 @@ func ParseStreamID(str string) (id StreamID, err error) { encoding multibase.Encoding streamCodec uint64 streamType uint64 + idx int ) if encoding, buf, err = multibase.Decode(str); err != nil { @@ -72,21 +71,24 @@ func ParseStreamID(str string) (id StreamID, err error) { return } // check - streamCodec, buf, _, err = GetUVarInt(buf) - if err != nil { + if streamCodec, idx = binary.Uvarint(buf); idx <= 0 { + err = fmt.Errorf("unable to unpack stream codec %v", buf) return } if multicodec.Code(streamCodec) != multicodec.Streamid { err = fmt.Errorf("unexpected multicodec %x != 0xce", buf[0]) return } + buf = buf[idx:] // check - streamType, buf, _, err = GetUVarInt(buf) - if err != nil { + if streamType, idx = binary.Uvarint(buf); idx <= 0 { + err = fmt.Errorf("unable to unpack stream type %v", buf) return } id.Type = StreamIdType(streamType) + buf = buf[idx:] + var nr int if nr, id.Cid, err = cid.CidFromBytes(buf); err != nil { return diff --git a/ceramic/streamid_utils.go b/ceramic/streamid_utils.go deleted file mode 100644 index 6e7a6e5..0000000 --- a/ceramic/streamid_utils.go +++ /dev/null @@ -1,22 +0,0 @@ -package ceramic - -import ( - "encoding/binary" - "fmt" -) - -// GetUVarInt returns the uint, rest of the buffer, bytes consumed, and error -// https://github.com/multiformats/unsigned-varint -func GetUVarInt(input []byte) (uint64, []byte, int, error) { - code, idx := binary.Uvarint(input) - if idx <= 0 { - return 0, input, idx, fmt.Errorf("unable to unpack unsigned var int %v", input) - } - return code, input[idx:], idx, nil -} - -func PutUVarInt(code uint64) []byte { - buf := make([]byte, 10) - n := binary.PutUvarint(buf, uint64(code)) - return buf[:n] -} From c789474872a0137c1f6cc908ecb14e60025e6e76 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Fri, 25 Aug 2023 18:31:31 +0800 Subject: [PATCH 06/18] feat(wnfs): ceramic commits content hash recorder --- .github/workflows/docker.yml | 15 +++- .github/workflows/golangci-lint.yml | 2 + .github/workflows/prerun-docker.yml | 3 +- ceramic/stream.go | 91 +++++++++++++++++++++ ceramic/streamid.go | 121 +++++++++++++++++++++++----- ceramic/streamid_test.go | 51 ++++++++---- go.mod | 3 +- go.sum | 64 ++++++++++----- internal/dapp/stream_binding.go | 7 +- internal/routers/ceramic_proxy.go | 48 +++++++++++ internal/routers/handlers_dapp.go | 14 ---- internal/routers/routers.go | 20 ----- internal/wnfs/db.go | 28 +++++++ internal/wnfs/model.go | 62 ++++++++++++++ internal/wnfs/policy.go | 9 +++ internal/wnfs/proof.go | 117 +++++++++++++++++++++++++++ pkg/dapp-table/getdapp.go | 35 ++++++++ pkg/dapp-table/getdapp_test.go | 41 ++++++++++ 18 files changed, 629 insertions(+), 102 deletions(-) create mode 100644 ceramic/stream.go create mode 100644 internal/routers/ceramic_proxy.go create mode 100644 internal/wnfs/db.go create mode 100644 internal/wnfs/model.go create mode 100644 internal/wnfs/policy.go create mode 100644 internal/wnfs/proof.go create mode 100644 pkg/dapp-table/getdapp.go create mode 100644 pkg/dapp-table/getdapp_test.go diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index af308a2..4cb5940 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -16,6 +16,7 @@ env: permissions: id-token: write # This is required for requesting the JWT contents: read # This is required for actions/checkout + packages: write jobs: build: @@ -36,12 +37,21 @@ jobs: username: dataverseos password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Docker metaw + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ github.token }} + + - name: Docker meta id: meta uses: docker/metadata-action@v4 with: # list of Docker images to use as base name for tags - images: dataverseos/dapp-backend + images: | + dataverseos/dapp-backend + ghcr.io/dataverse-os/dapp-backend # generate Docker tags based on the following events/attributes tags: | type=schedule @@ -59,7 +69,6 @@ jobs: uses: docker/build-push-action@v3 with: context: . - push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 3389bf5..49ae7c6 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -37,3 +37,5 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v3 + with: + args: --timeout=30m \ No newline at end of file diff --git a/.github/workflows/prerun-docker.yml b/.github/workflows/prerun-docker.yml index bb83489..cbb99f1 100644 --- a/.github/workflows/prerun-docker.yml +++ b/.github/workflows/prerun-docker.yml @@ -55,5 +55,4 @@ jobs: context: ./prerun push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - platforms: ${{ matrix.PLATFORM }} \ No newline at end of file + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/ceramic/stream.go b/ceramic/stream.go new file mode 100644 index 0000000..7806827 --- /dev/null +++ b/ceramic/stream.go @@ -0,0 +1,91 @@ +package ceramic + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "fmt" + "net/http" + + "github.com/ipfs/go-cid" +) + +type Stream struct { + StreamId StreamId `json:"streamId"` + State StreamState `json:"state"` +} + +type StreamState struct { + Type StreamType `json:"type"` + Content json.RawMessage `json:"content"` + Metadata json.RawMessage `json:"metadata"` + Signature int `json:"signature"` + AnchorStatus string `json:"anchorStatus"` + Log []StreamLog `json:"log"` + AnchorProof *AnchorProof `json:"anchorProof,omitempty"` + DocType string `json:"docType"` +} + +type StreamLog struct { + Cid string `json:"cid"` + Type CommitType `json:"type"` + ExpirationTime *uint64 `json:"expirationTime,omitempty"` + Timestamp uint64 `json:"timestamp"` +} + +type AnchorProof struct { + Root string `json:"root"` + TxHash string `json:"txHash"` + TxType string `json:"txType"` + ChainId string `json:"chainId"` +} + +func (state StreamState) StreamId() StreamId { + return StreamId{ + Type: state.Type, + Cid: cid.MustParse(state.Log[0].Cid), + } +} + +func (state StreamState) CommitIds() (commitIds []StreamId) { + streamId := state.StreamId() + commitIds = append(commitIds, streamId.Genesis()) + for _, v := range state.Log[1:] { + commitIds = append(commitIds, streamId.With(v.Cid)) + } + return +} + +func (state StreamState) ContentHash() (sum [32]byte, err error) { + // var data any + // if err = json.Unmarshal(state.Content, &data); err != nil { + // return + // } + // var buf bytes.Buffer + // if err = json.NewEncoder(&buf).Encode(data); err != nil { + // return + // } + + // sum = sha256.Sum256(buf.Bytes()) + + sum = sha256.Sum256(state.Content) + hex.EncodeToString(sum[0:]) + return +} + +func GetStreamId(ctx context.Context, streamId StreamId) (stream Stream, err error) { + url := fmt.Sprintf("https://dataverseceramicdaemon.com/api/v0/streams/%s", streamId) + var req *http.Request + var resp *http.Response + if req, err = http.NewRequestWithContext(ctx, http.MethodGet, url, nil); err != nil { + return + } + if resp, err = http.DefaultClient.Do(req); err != nil { + return + } + if err = json.NewDecoder(resp.Body).Decode(&stream); err != nil { + return + } + return +} diff --git a/ceramic/streamid.go b/ceramic/streamid.go index a87de45..aba40f2 100644 --- a/ceramic/streamid.go +++ b/ceramic/streamid.go @@ -2,7 +2,11 @@ package ceramic import ( "bytes" + "context" + "database/sql" + "database/sql/driver" "encoding/binary" + "encoding/json" "fmt" "github.com/ipfs/go-cid" @@ -10,42 +14,71 @@ import ( "github.com/multiformats/go-multicodec" ) -type StreamIdType uint64 +type ( + StreamType uint64 + CommitType uint64 +) // https://github.com/ceramicnetwork/CIPs/blob/main/CIPs/cip-59.md const ( - StreamIdTypeTile StreamIdType = iota - StreamIdTypeCaip10Link - StreamIdTypeModel - StreamIdTypeModelInstanceDocument - StreamIdTypeUnloadable - StreamIdTypeEventId - - StreamIDEncoding = multibase.Base36 + StreamTypeTile StreamType = iota + StreamTypeCaip10Link + StreamTypeModel + StreamTypeModelInstanceDocument + StreamTypeUnloadable + StreamTypeEventId ) -type StreamID struct { - Type StreamIdType - Cid cid.Cid - Log cid.Cid -} +const ( + CommitTypeGenesis CommitType = iota + CommitTypeSigned + CommitTypeAnchor +) + +const ( + StreamIdEncoding = multibase.Base36 +) var ( - streamIdEncoder = multibase.MustNewEncoder(StreamIDEncoding) + streamIdEncoder = multibase.MustNewEncoder(StreamIdEncoding) ) -func (id StreamID) String() string { +type StreamId struct { + Type StreamType + Cid cid.Cid + Log cid.Cid + GenesisLog bool +} + +func (id StreamId) String() string { var buf bytes.Buffer buf.Write(binary.AppendUvarint(nil, uint64(multicodec.Streamid))) buf.Write(binary.AppendUvarint(nil, uint64(id.Type))) buf.Write(id.Cid.Bytes()) if id.Log.ByteLen() != 0 { buf.Write(id.Log.Bytes()) + } else if id.GenesisLog { + buf.Write([]byte{0}) } return streamIdEncoder.Encode(buf.Bytes()) } -func NewStreamID(t StreamIdType, cidStr ...string) (id StreamID, err error) { +func (id StreamId) Genesis() StreamId { + id.GenesisLog = true + return id +} + +func (id StreamId) With(str string) StreamId { + id.GenesisLog = false + id.Log = cid.MustParse(str) + return id +} + +func (id StreamId) GetStream(ctx context.Context) (stream Stream, err error) { + return GetStreamId(ctx, id) +} + +func NewStreamId(t StreamType, cidStr ...string) (id StreamId, err error) { if len(cidStr) != 1 && len(cidStr) != 2 { err = fmt.Errorf("unexpect cid length, could only 1 or 2 (genesis cid and log cid)") } @@ -54,7 +87,7 @@ func NewStreamID(t StreamIdType, cidStr ...string) (id StreamID, err error) { return } -func ParseStreamID(str string) (id StreamID, err error) { +func ParseStreamID(str string) (id StreamId, err error) { var ( buf []byte encoding multibase.Encoding @@ -66,7 +99,7 @@ func ParseStreamID(str string) (id StreamID, err error) { if encoding, buf, err = multibase.Decode(str); err != nil { return } - if encoding != StreamIDEncoding { + if encoding != StreamIdEncoding { err = fmt.Errorf("unexpected encoding id %c with input %s", encoding, str) return } @@ -86,17 +119,61 @@ func ParseStreamID(str string) (id StreamID, err error) { err = fmt.Errorf("unable to unpack stream type %v", buf) return } - id.Type = StreamIdType(streamType) + id.Type = StreamType(streamType) buf = buf[idx:] var nr int if nr, id.Cid, err = cid.CidFromBytes(buf); err != nil { return } - if len(buf) != nr { - if _, id.Log, err = cid.CidFromBytes(buf[nr:]); err != nil { + buf = buf[nr:] + if len(buf) != 0 { + if len(buf) == 1 && buf[0] == 0 { + id.GenesisLog = true + } else if _, id.Log, err = cid.CidFromBytes(buf); err != nil { return } } return } + +var _ json.Marshaler = (*StreamId)(nil) + +func (id *StreamId) MarshalJSON() ([]byte, error) { + return json.Marshal(id.String()) +} + +var _ json.Unmarshaler = (*StreamId)(nil) + +func (id *StreamId) UnmarshalJSON(src []byte) (err error) { + var str string + if err = json.Unmarshal(src, &str); err != nil { + return + } + if *id, err = ParseStreamID(str); err != nil { + return + } + return +} + +func (StreamId) GormDataType() string { + return "text" +} + +var _ sql.Scanner = (*StreamId)(nil) + +func (id *StreamId) Scan(src any) (err error) { + str, ok := src.(string) + if !ok { + err = fmt.Errorf("cannot parse %s to string", src) + return + } + *id, err = ParseStreamID(str) + return +} + +var _ driver.Valuer = (*StreamId)(nil) + +func (id *StreamId) Value() (driver.Value, error) { + return id.String, nil +} diff --git a/ceramic/streamid_test.go b/ceramic/streamid_test.go index 9b50aae..0975c90 100644 --- a/ceramic/streamid_test.go +++ b/ceramic/streamid_test.go @@ -10,9 +10,10 @@ import ( func TestStreamID_String(t *testing.T) { type fields struct { - Type ceramic.StreamIdType - Cid cid.Cid - Log cid.Cid + Type ceramic.StreamType + Cid cid.Cid + Log cid.Cid + GenesisLog bool } tests := []struct { name string @@ -22,7 +23,7 @@ func TestStreamID_String(t *testing.T) { { name: "stream_id", fields: fields{ - Type: ceramic.StreamIdTypeModelInstanceDocument, + Type: ceramic.StreamTypeModelInstanceDocument, Cid: cid.MustParse("bagcqceragiwmxdtelb45wjl6calr45bh4rpcipbmh3t3skrkjvv3foihfmrq"), }, want: "kjzl6kcym7w8y64sx1g97dy5v3xmm49mnx0p9mofs44t6y0y7wp2ko8z7w9azhf", @@ -30,19 +31,29 @@ func TestStreamID_String(t *testing.T) { { name: "commit_id", fields: fields{ - Type: ceramic.StreamIdTypeTile, + Type: ceramic.StreamTypeTile, Cid: cid.MustParse("bagcqcerakszw2vsovxznyp5gfnpdj4cqm2xiv76yd24wkjewhhykovorwo6a"), Log: cid.MustParse("bagjqcgzaday6dzalvmy5ady2m5a5legq5zrbsnlxfc2bfxej532ds7htpova"), }, want: "k1dpgaqe3i64kjqcp801r3sn7ysi5i0k7nxvs7j351s7kewfzr3l7mdxnj7szwo4kr9mn2qki5nnj0cv836ythy1t1gya9s25cn1nexst3jxi5o3h6qprfyju", }, + { + name: "commit_id_genesis", + fields: fields{ + Type: ceramic.StreamTypeModelInstanceDocument, + Cid: cid.MustParse("bagcqceragiwmxdtelb45wjl6calr45bh4rpcipbmh3t3skrkjvv3foihfmrq"), + GenesisLog: true, + }, + want: "k3y52mos6605bmzm5myblgj6xp7z4tach62szoh9s7xe7ldyrc8iab0fug5e64buo", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - id := ceramic.StreamID{ - Type: tt.fields.Type, - Cid: tt.fields.Cid, - Log: tt.fields.Log, + id := ceramic.StreamId{ + Type: tt.fields.Type, + Cid: tt.fields.Cid, + Log: tt.fields.Log, + GenesisLog: tt.fields.GenesisLog, } if got := id.String(); got != tt.want { t.Errorf("StreamID.String() = %v, want %v", got, tt.want) @@ -58,7 +69,7 @@ func TestParseStreamID(t *testing.T) { tests := []struct { name string args args - wantId ceramic.StreamID + wantId ceramic.StreamId wantErr bool }{ { @@ -66,19 +77,31 @@ func TestParseStreamID(t *testing.T) { args: args{ str: "kjzl6kcym7w8y64sx1g97dy5v3xmm49mnx0p9mofs44t6y0y7wp2ko8z7w9azhf", }, - wantId: ceramic.StreamID{ - Type: ceramic.StreamIdTypeModelInstanceDocument, + wantId: ceramic.StreamId{ + Type: ceramic.StreamTypeModelInstanceDocument, Cid: cid.MustParse("bagcqceragiwmxdtelb45wjl6calr45bh4rpcipbmh3t3skrkjvv3foihfmrq"), }, wantErr: false, }, + { + name: "commit_id_genesis", + args: args{ + str: "k3y52mos6605bmzm5myblgj6xp7z4tach62szoh9s7xe7ldyrc8iab0fug5e64buo", + }, + wantId: ceramic.StreamId{ + Type: ceramic.StreamTypeModelInstanceDocument, + Cid: cid.MustParse("bagcqceragiwmxdtelb45wjl6calr45bh4rpcipbmh3t3skrkjvv3foihfmrq"), + GenesisLog: true, + }, + wantErr: false, + }, { name: "commit_id", args: args{ str: "k1dpgaqe3i64kjqcp801r3sn7ysi5i0k7nxvs7j351s7kewfzr3l7mdxnj7szwo4kr9mn2qki5nnj0cv836ythy1t1gya9s25cn1nexst3jxi5o3h6qprfyju", }, - wantId: ceramic.StreamID{ - Type: ceramic.StreamIdTypeTile, + wantId: ceramic.StreamId{ + Type: ceramic.StreamTypeTile, Cid: cid.MustParse("bagcqcerakszw2vsovxznyp5gfnpdj4cqm2xiv76yd24wkjewhhykovorwo6a"), Log: cid.MustParse("bagjqcgzaday6dzalvmy5ady2m5a5legq5zrbsnlxfc2bfxej532ds7htpova"), }, diff --git a/go.mod b/go.mod index fcc5211..1165832 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,9 @@ module github.com/dataverse-os/dapp-backend -go 1.20 +go 1.21 require ( github.com/ethereum/go-ethereum v1.12.0 - github.com/gin-contrib/cors v1.4.0 github.com/gin-gonic/gin v1.9.1 github.com/google/uuid v1.3.0 github.com/graphql-go/graphql v0.8.1 diff --git a/go.sum b/go.sum index 60f324d..2a98f5e 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,12 @@ github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= +github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= +github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= @@ -18,13 +22,18 @@ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1 github.com/bytedance/sonic v1.9.2 h1:GDaNjuWSGu09guE9Oql0MSTNhNCLlWwO8y/xM5BzcbM= github.com/bytedance/sonic v1.9.2/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/errors v1.9.1/go.mod h1:2sxOtL2WIc096WSZqZ5h8fa17rdDq9HZOZLBCor4mBk= github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b/go.mod h1:Vz9DsVWQQhf3vs21MhPMZpMGSht7O/2vFW2xusFUVOs= github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= +github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -32,6 +41,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs 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/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2zljOa0= @@ -40,61 +50,68 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= -github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g= -github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= +github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= +github.com/graph-gophers/graphql-go v1.5.0/go.mod h1:YtmJZDLbF1YYNrlNAuiO5zAStUWc3XZT07iGsVqe1Os= github.com/graph-gophers/graphql-transport-ws v0.0.2 h1:DbmSkbIGzj8SvHei6n8Mh9eLQin8PtA8xY9eCzjRpvo= +github.com/graph-gophers/graphql-transport-ws v0.0.2/go.mod h1:5BVKvFzOd2BalVIBFfnfmHjpJi/MZ5rOj8G55mXvZ8g= github.com/graphql-go/graphql v0.8.1 h1:p7/Ou/WpmulocJeEx7wjQy611rtXGQaAcXGqanuMMgc= github.com/graphql-go/graphql v0.8.1/go.mod h1:nKiHzRM0qopJEwCITUuIsxk9PlVlwIiiI8pnJEhordQ= github.com/hasura/go-graphql-client v0.10.0 h1:eQm/ap/rqxMG6yAGe6J+FkXu1VqJ9p21E63vz0A7zLQ= @@ -135,25 +152,29 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= +github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g= github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g= @@ -179,28 +200,32 @@ github.com/multiformats/go-multihash v0.0.15/go.mod h1:D6aZrWNLFTV/ynMpKsNtB40mJ github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY= github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= 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/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.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/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= +github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= +github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -210,7 +235,6 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -219,6 +243,7 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -227,13 +252,13 @@ github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhso github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= +github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -245,7 +270,6 @@ golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= @@ -273,8 +297,6 @@ golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -288,7 +310,6 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= @@ -300,7 +321,6 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -313,9 +333,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/datatypes v1.2.0 h1:5YT+eokWdIxhJgWHdrb2zYUimyk0+TaFth+7a0ybzco= @@ -325,7 +343,9 @@ gorm.io/driver/mysql v1.4.7/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8o gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A= gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU= +gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= +gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11 h1:9qNbmu21nNThCNnF5i2R3kw2aL27U8ZwbzccNjOmW0g= gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= diff --git a/internal/dapp/stream_binding.go b/internal/dapp/stream_binding.go index d67eede..d0af7bc 100644 --- a/internal/dapp/stream_binding.go +++ b/internal/dapp/stream_binding.go @@ -16,9 +16,10 @@ type StreamFileBinding struct { } type StreamContent struct { - Content datatypes.JSON `json:"content,omitempty"` - File datatypes.JSON `json:"file,omitempty"` - FileID string `json:"fileId,omitempty"` + Content datatypes.JSON `json:"content,omitempty"` + File datatypes.JSON `json:"file,omitempty"` + FileID string `json:"fileId,omitempty"` + Verified bool `json:"verified,omitempty"` } func ListStreamBindingFiles(ctx context.Context, modelID, indexFileModelID string, pkh *string) ( diff --git a/internal/routers/ceramic_proxy.go b/internal/routers/ceramic_proxy.go new file mode 100644 index 0000000..241c22f --- /dev/null +++ b/internal/routers/ceramic_proxy.go @@ -0,0 +1,48 @@ +package routers + +import ( + "bytes" + "net/http/httputil" + "strings" + + "github.com/dataverse-os/dapp-backend/internal/dapp" + "github.com/dataverse-os/dapp-backend/internal/wnfs" + "github.com/gin-gonic/gin" +) + +func CeramicProxy(ctx *gin.Context) { + proxy := &httputil.ReverseProxy{ + Rewrite: func(r *httputil.ProxyRequest) { + r.Out.Header = r.In.Header + r.Out.Host = dapp.CeramicSession.URL.Host + r.Out.URL.Host = dapp.CeramicSession.URL.Host + r.Out.URL.Scheme = dapp.CeramicSession.URL.Scheme + }, + } + res := bodyLogWriter{ + ResponseWriter: ctx.Writer, + body: new(bytes.Buffer), + } + proxy.ServeHTTP(res, ctx.Request) + for k := range wnfs.StreamResponsePath { + if strings.HasPrefix(ctx.Request.URL.Path, k) { + wnfs.AppendToVerifyGroup(res.body) + } + } + ctx.Abort() +} + +type bodyLogWriter struct { + gin.ResponseWriter + body *bytes.Buffer +} + +func (w bodyLogWriter) Write(b []byte) (int, error) { + w.body.Write(b) + return w.ResponseWriter.Write(b) +} + +func (w bodyLogWriter) WriteString(s string) (int, error) { + w.body.WriteString(s) + return w.ResponseWriter.WriteString(s) +} diff --git a/internal/routers/handlers_dapp.go b/internal/routers/handlers_dapp.go index 21caaf7..0af8f51 100644 --- a/internal/routers/handlers_dapp.go +++ b/internal/routers/handlers_dapp.go @@ -2,7 +2,6 @@ package routers import ( "net/http" - "net/http/httputil" "github.com/dataverse-os/dapp-backend/internal/dapp" "github.com/dataverse-os/dapp-backend/verify" @@ -68,16 +67,3 @@ func (r yamlRender) Render(w http.ResponseWriter) error { _, err = w.Write(bytes) return err } - -func CeramicProxy(ctx *gin.Context) { - proxy := &httputil.ReverseProxy{ - Rewrite: func(r *httputil.ProxyRequest) { - r.Out.Header = r.In.Header - r.Out.Host = dapp.CeramicSession.URL.Host - r.Out.URL.Host = dapp.CeramicSession.URL.Host - r.Out.URL.Scheme = dapp.CeramicSession.URL.Scheme - }, - } - proxy.ServeHTTP(ctx.Writer, ctx.Request) - ctx.Abort() -} diff --git a/internal/routers/routers.go b/internal/routers/routers.go index f887d3b..fb8899c 100644 --- a/internal/routers/routers.go +++ b/internal/routers/routers.go @@ -6,14 +6,11 @@ import ( "fmt" "io" "log" - "net/http" "os" - "time" "github.com/dataverse-os/dapp-backend/internal/dapp" "github.com/dataverse-os/dapp-backend/verify" "github.com/ethereum/go-ethereum/common" - "github.com/gin-contrib/cors" "github.com/gin-gonic/gin" ) @@ -23,23 +20,6 @@ var ( func InitRouter() { router = gin.Default() - router.Use( - cors.New(cors.Config{ - AllowOrigins: []string{"*"}, - AllowMethods: []string{ - http.MethodGet, http.MethodPost, http.MethodPut, - http.MethodDelete, http.MethodOptions, http.MethodPatch, - http.MethodHead, - }, - AllowHeaders: []string{"Origin"}, - ExposeHeaders: []string{"Content-Length"}, - AllowCredentials: true, - AllowOriginFunc: func(origin string) bool { - return true - }, - MaxAge: 12 * time.Hour, - }), - ) router.Any("/api/*path", CeramicProxy) d := router.Group("/dataverse") { diff --git a/internal/wnfs/db.go b/internal/wnfs/db.go new file mode 100644 index 0000000..6959161 --- /dev/null +++ b/internal/wnfs/db.go @@ -0,0 +1,28 @@ +package wnfs + +import ( + "log" + "os" + + "gorm.io/driver/postgres" + "gorm.io/gorm" + "gorm.io/gorm/schema" +) + +var db *gorm.DB + +func init() { + var err error + if db, err = gorm.Open(postgres.Open(os.Getenv("WNFS_POSTGRES_DSN")), &gorm.Config{ + NamingStrategy: schema.NamingStrategy{ + TablePrefix: "wnfs.", + SingularTable: false, + }, + }); err != nil { + log.Fatalln("failed init wnfs postgres connection:", err) + } + + db.AutoMigrate( + &CommitProof{}, + ) +} diff --git a/internal/wnfs/model.go b/internal/wnfs/model.go new file mode 100644 index 0000000..7afb1c4 --- /dev/null +++ b/internal/wnfs/model.go @@ -0,0 +1,62 @@ +package wnfs + +import ( + "context" + + dapptable "github.com/dataverse-os/dapp-backend/pkg/dapp-table" + "github.com/google/uuid" + "github.com/lib/pq" + "github.com/samber/lo" +) + +type DappModel struct { + ModelID string `gorm:"primary-key"` + AppID uuid.UUID `gorm:"type:uuid;not null"` + Encryptable pq.StringArray + ModelName string + Version int +} + +func LookupDappModel(ctx context.Context, modelId string) (data DappModel, err error) { + if err = db.Where(&DappModel{ModelID: modelId}).First(&data).Error; err == nil { + return + } + var dapp dapptable.Dapp + if dapp, err = dapptable.GetDappByModelID(ctx, modelId); err != nil { + return + } + models := make([]DappModel, 0) + for _, v := range dapp.Models { + for _, vv := range v.Streams { + models = append(models, DappModel{ + ModelID: modelId, + AppID: uuid.MustParse(dapp.Id), + Encryptable: vv.Encryptable, + ModelName: v.ModelName, + Version: vv.Version, + }) + } + } + + // lookup models not in database + modelsInDB := make([]DappModel, 0) + if err = db.Where("model_id in (?)", lo.Map(models, func(item DappModel, _ int) string { + return item.ModelID + })).Find(&modelsInDB).Error; err != nil { + return + } + // filter models already in database + modelsShouldInsert := lo.Filter(models, func(item DappModel, index int) bool { + return lo.ContainsBy(modelsInDB, func(itemInDB DappModel) bool { + return itemInDB.ModelID != item.ModelID + }) + }) + if err = db.Create(&modelsShouldInsert).Error; err != nil { + return + } + + data = lo.Filter(models, func(item DappModel, _ int) bool { + return item.ModelID == modelId + })[0] + return +} diff --git a/internal/wnfs/policy.go b/internal/wnfs/policy.go new file mode 100644 index 0000000..c1d9bd7 --- /dev/null +++ b/internal/wnfs/policy.go @@ -0,0 +1,9 @@ +package wnfs + +import ( + "encoding/json" +) + +func CheckPolicy(streamContents []json.RawMessage) (err error) { + return +} diff --git a/internal/wnfs/proof.go b/internal/wnfs/proof.go new file mode 100644 index 0000000..7dda14f --- /dev/null +++ b/internal/wnfs/proof.go @@ -0,0 +1,117 @@ +package wnfs + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "log" + + "github.com/dataverse-os/dapp-backend/ceramic" + "github.com/ethereum/go-ethereum/common" + "golang.org/x/sync/errgroup" +) + +var VerifyGroup *errgroup.Group + +func init() { + VerifyGroup = new(errgroup.Group) + VerifyGroup.SetLimit(1) +} + +var StreamResponsePath = map[string]struct{}{ + "/api/v0/streams": {}, + "/api/v0/commits": {}, +} + +func AppendToVerifyGroup(buf *bytes.Buffer) { + VerifyGroup.Go(func() (err error) { + if err = StoreAndVerifyContentHashFromReader(context.Background(), buf); err != nil { + log.Println(err) + } + return + }) +} + +type CommitProofStatus uint64 + +const ( + CommitProofStatusUnverified CommitProofStatus = iota + CommitProofStatusLegal + CommitProofStatusIllegal +) + +type CommitProof struct { + CommitId ceramic.StreamId `json:"commitId" gorm:"primaryKey"` + StreamId ceramic.StreamId `json:"streamId"` + Cid string `json:"cid"` + Hash common.Hash `json:"hash"` + Content json.RawMessage `json:"content" gorm:"type:jsonb"` + Status CommitProofStatus `json:"status"` +} + +func StoreAndVerifyContentHashFromReader(ctx context.Context, buf *bytes.Buffer) (err error) { + var stream ceramic.Stream + if err = json.Unmarshal(buf.Bytes(), &stream); err != nil { + return + } + if err = StoreAndVerifyContentHash(ctx, stream); err != nil { + return + } + return +} + +func StoreAndVerifyContentHash(ctx context.Context, stream ceramic.Stream) (err error) { + var ( + commit ceramic.Stream + commitProofs = make([]CommitProof, len(stream.State.Log)) + commitProofsInDB []CommitProof + commitProofsInDBMap = make(map[ceramic.StreamId]CommitProof) + commitIds = stream.State.CommitIds() + ) + + defer func() { + if err != nil { + fmt.Printf("wnfs check %s with %d commits\n", stream.StreamId, len(commitProofs)) + } + }() + + if err = db.WithContext(ctx).Where(&CommitProof{ + StreamId: stream.StreamId, + }).Find(&commitProofsInDB).Error; err != nil { + return + } + for _, proof := range commitProofsInDB { + commitProofsInDBMap[proof.CommitId] = proof + } + for i, v := range stream.State.Log { + if proof, exists := commitProofsInDBMap[commitIds[i]]; exists { + commitProofs[i] = proof + continue + } + commitProofs[i] = CommitProof{ + CommitId: commitIds[i], + StreamId: stream.StreamId, + Cid: v.Cid, + } + if commit, err = commitIds[i].GetStream(ctx); err != nil { + return + } + commitProofs[i].Content = commit.State.Content + if commitProofs[i].Hash, err = commit.State.ContentHash(); err != nil { + return + } + } + shouldInsert := make([]CommitProof, 0) + for _, proof := range commitProofs { + if _, exists := commitProofsInDBMap[proof.CommitId]; !exists { + shouldInsert = append(shouldInsert, proof) + } + } + if len(shouldInsert) != 0 { + if err = db.Create(shouldInsert).Error; err != nil { + return + } + } + return +} diff --git a/pkg/dapp-table/getdapp.go b/pkg/dapp-table/getdapp.go new file mode 100644 index 0000000..63eb052 --- /dev/null +++ b/pkg/dapp-table/getdapp.go @@ -0,0 +1,35 @@ +package dapptable + +import ( + "context" + + "github.com/hasura/go-graphql-client" +) + +type getDappByModelIDQuery struct { + GetDapp Dapp `graphql:"getDapp(modelId: $modelId)"` +} + +type Dapp struct { + Id string + Models []struct { + ModelName string + Streams []struct { + ModelId string + Encryptable []string + Version int + } + } +} + +func GetDappByModelID(ctx context.Context, modelId string) (dapp Dapp, err error) { + client := graphql.NewClient("https://gateway.dataverse.art/v1/dapp-table/graphql", nil) + var query getDappByModelIDQuery + if err = client.Query(ctx, &query, map[string]any{ + "modelId": modelId, + }); err != nil { + return + } + dapp = query.GetDapp + return +} diff --git a/pkg/dapp-table/getdapp_test.go b/pkg/dapp-table/getdapp_test.go new file mode 100644 index 0000000..7c2c3a9 --- /dev/null +++ b/pkg/dapp-table/getdapp_test.go @@ -0,0 +1,41 @@ +package dapptable + +import ( + "context" + "reflect" + "testing" +) + +func TestGetDappByModelID(t *testing.T) { + type args struct { + ctx context.Context + modelId string + } + tests := []struct { + name string + args args + wantDapp Dapp + wantErr bool + }{ + { + name: "common", + args: args{ + ctx: context.Background(), + modelId: "kjzl6hvfrbw6c5m98besslbjufnwxk9t1uzebyu1gevzr17tq65sbe3vv8oq53b", + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotDappBytes, err := GetDappByModelID(tt.args.ctx, tt.args.modelId) + if (err != nil) != tt.wantErr { + t.Errorf("GetDappByModelID() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotDappBytes, tt.wantDapp) { + t.Errorf("GetDappByModelID() = %v, want %v", gotDappBytes, tt.wantDapp) + } + }) + } +} From e0b30968cdda8bedee8e0b636713837c355450e0 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Fri, 25 Aug 2023 18:46:10 +0800 Subject: [PATCH 07/18] fix(ci): lint error & push container --- .github/workflows/docker.yml | 1 + internal/wnfs/db.go | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 4cb5940..452ec6e 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -69,6 +69,7 @@ jobs: uses: docker/build-push-action@v3 with: context: . + push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/internal/wnfs/db.go b/internal/wnfs/db.go index 6959161..4e4e24b 100644 --- a/internal/wnfs/db.go +++ b/internal/wnfs/db.go @@ -22,7 +22,9 @@ func init() { log.Fatalln("failed init wnfs postgres connection:", err) } - db.AutoMigrate( + if err = db.AutoMigrate( &CommitProof{}, - ) + ); err != nil { + log.Fatalln("failed init wnfs model:", err) + } } From 56a8a156b01fbca951c9130cc9996df3af9fa045 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Fri, 25 Aug 2023 18:50:22 +0800 Subject: [PATCH 08/18] feat(ci): push container to ghcr only --- .github/workflows/docker.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 452ec6e..782fd86 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -30,13 +30,6 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - - name: Login to DockerHub - if: github.event_name != 'pull_request' - uses: docker/login-action@v2 - with: - username: dataverseos - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Login to GitHub Container Registry uses: docker/login-action@v2 with: @@ -50,7 +43,6 @@ jobs: with: # list of Docker images to use as base name for tags images: | - dataverseos/dapp-backend ghcr.io/dataverse-os/dapp-backend # generate Docker tags based on the following events/attributes tags: | From 056ee0abe4bb4afc381db781cc52080e60fc4cdf Mon Sep 17 00:00:00 2001 From: FDKevin Date: Fri, 25 Aug 2023 18:53:21 +0800 Subject: [PATCH 09/18] fix(ci): packages permissions --- .github/workflows/docker.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 782fd86..6769317 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -23,6 +23,8 @@ jobs: name: Build for multi-platform if: github.repository_owner == 'dataverse-os' runs-on: ubuntu-latest + permissions: + packages: write steps: - name: checkout uses: actions/checkout@v3 From 89096e49e9ac0663e3b71cfa6256829a3e7f20ac Mon Sep 17 00:00:00 2001 From: FDKevin Date: Mon, 28 Aug 2023 16:02:06 +0800 Subject: [PATCH 10/18] fix(ceramic): with costom backend --- ceramic/stream.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ceramic/stream.go b/ceramic/stream.go index 7806827..a21cf18 100644 --- a/ceramic/stream.go +++ b/ceramic/stream.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "net/http" + "os" "github.com/ipfs/go-cid" ) @@ -75,7 +76,7 @@ func (state StreamState) ContentHash() (sum [32]byte, err error) { } func GetStreamId(ctx context.Context, streamId StreamId) (stream Stream, err error) { - url := fmt.Sprintf("https://dataverseceramicdaemon.com/api/v0/streams/%s", streamId) + url := fmt.Sprintf("%s/api/v0/streams/%s", os.Getenv("CERAMIC_URL"), streamId) var req *http.Request var resp *http.Response if req, err = http.NewRequestWithContext(ctx, http.MethodGet, url, nil); err != nil { From cbe1bc00edb51c35e26d3cad30f6e6f75d072231 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Mon, 28 Aug 2023 17:39:34 +0800 Subject: [PATCH 11/18] feat(wnfs): handle collection --- ceramic/collection.go | 8 ++++ internal/routers/ceramic_proxy.go | 7 +++- internal/wnfs/proof.go | 63 +++++++++++++++++++------------ 3 files changed, 53 insertions(+), 25 deletions(-) create mode 100644 ceramic/collection.go diff --git a/ceramic/collection.go b/ceramic/collection.go new file mode 100644 index 0000000..7afa1b0 --- /dev/null +++ b/ceramic/collection.go @@ -0,0 +1,8 @@ +package ceramic + +type Collection struct { + Edges []struct { + Cursor string `json:"cursor"` + Node StreamState `json:"node"` + } `json:"edges"` +} diff --git a/internal/routers/ceramic_proxy.go b/internal/routers/ceramic_proxy.go index 241c22f..dada361 100644 --- a/internal/routers/ceramic_proxy.go +++ b/internal/routers/ceramic_proxy.go @@ -26,7 +26,12 @@ func CeramicProxy(ctx *gin.Context) { proxy.ServeHTTP(res, ctx.Request) for k := range wnfs.StreamResponsePath { if strings.HasPrefix(ctx.Request.URL.Path, k) { - wnfs.AppendToVerifyGroup(res.body) + wnfs.AppendToStreamVerifyGroup(res.body) + } + } + for k := range wnfs.CollectionResponsePath { + if strings.HasPrefix(ctx.Request.URL.Path, k) { + wnfs.AppendToCollectionVerifyGroup(res.body) } } ctx.Abort() diff --git a/internal/wnfs/proof.go b/internal/wnfs/proof.go index 7dda14f..3e9c314 100644 --- a/internal/wnfs/proof.go +++ b/internal/wnfs/proof.go @@ -5,7 +5,6 @@ import ( "context" "encoding/json" "fmt" - "log" "github.com/dataverse-os/dapp-backend/ceramic" "github.com/ethereum/go-ethereum/common" @@ -20,19 +19,45 @@ func init() { } var StreamResponsePath = map[string]struct{}{ - "/api/v0/streams": {}, - "/api/v0/commits": {}, + "/api/v0/streams/": {}, + "/api/v0/commits/": {}, } -func AppendToVerifyGroup(buf *bytes.Buffer) { +var CollectionResponsePath = map[string]struct{}{ + "/api/v0/collection": {}, +} + +func AppendToStreamVerifyGroup(buf *bytes.Buffer) { + var stream ceramic.Stream + if err := json.Unmarshal(buf.Bytes(), &stream); err != nil { + fmt.Println(err) + return + } VerifyGroup.Go(func() (err error) { - if err = StoreAndVerifyContentHashFromReader(context.Background(), buf); err != nil { - log.Println(err) + if err = StoreAndVerifyContentHash(context.Background(), stream.State); err != nil { + return } return }) } +func AppendToCollectionVerifyGroup(buf *bytes.Buffer) { + var collection ceramic.Collection + if err := json.Unmarshal(buf.Bytes(), &collection); err != nil { + fmt.Println(err) + return + } + for _, v := range collection.Edges { + state := v.Node + VerifyGroup.Go(func() (err error) { + if err = StoreAndVerifyContentHash(context.Background(), state); err != nil { + return + } + return + }) + } +} + type CommitProofStatus uint64 const ( @@ -50,48 +75,38 @@ type CommitProof struct { Status CommitProofStatus `json:"status"` } -func StoreAndVerifyContentHashFromReader(ctx context.Context, buf *bytes.Buffer) (err error) { - var stream ceramic.Stream - if err = json.Unmarshal(buf.Bytes(), &stream); err != nil { - return - } - if err = StoreAndVerifyContentHash(ctx, stream); err != nil { - return - } - return -} - -func StoreAndVerifyContentHash(ctx context.Context, stream ceramic.Stream) (err error) { +func StoreAndVerifyContentHash(ctx context.Context, streamState ceramic.StreamState) (err error) { var ( + streamId = streamState.StreamId() commit ceramic.Stream - commitProofs = make([]CommitProof, len(stream.State.Log)) + commitProofs = make([]CommitProof, len(streamState.Log)) commitProofsInDB []CommitProof commitProofsInDBMap = make(map[ceramic.StreamId]CommitProof) - commitIds = stream.State.CommitIds() + commitIds = streamState.CommitIds() ) defer func() { if err != nil { - fmt.Printf("wnfs check %s with %d commits\n", stream.StreamId, len(commitProofs)) + fmt.Printf("wnfs check %s with %d commits\n", streamState.StreamId(), len(commitProofs)) } }() if err = db.WithContext(ctx).Where(&CommitProof{ - StreamId: stream.StreamId, + StreamId: streamId, }).Find(&commitProofsInDB).Error; err != nil { return } for _, proof := range commitProofsInDB { commitProofsInDBMap[proof.CommitId] = proof } - for i, v := range stream.State.Log { + for i, v := range streamState.Log { if proof, exists := commitProofsInDBMap[commitIds[i]]; exists { commitProofs[i] = proof continue } commitProofs[i] = CommitProof{ CommitId: commitIds[i], - StreamId: stream.StreamId, + StreamId: streamId, Cid: v.Cid, } if commit, err = commitIds[i].GetStream(ctx); err != nil { From f9619c6c1bd06017c9dfcc91c762e9e287e1256e Mon Sep 17 00:00:00 2001 From: FDKevin Date: Mon, 28 Aug 2023 17:53:36 +0800 Subject: [PATCH 12/18] feat(wnfs): asynchronous processing --- internal/routers/ceramic_proxy.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/routers/ceramic_proxy.go b/internal/routers/ceramic_proxy.go index dada361..46375c6 100644 --- a/internal/routers/ceramic_proxy.go +++ b/internal/routers/ceramic_proxy.go @@ -26,12 +26,12 @@ func CeramicProxy(ctx *gin.Context) { proxy.ServeHTTP(res, ctx.Request) for k := range wnfs.StreamResponsePath { if strings.HasPrefix(ctx.Request.URL.Path, k) { - wnfs.AppendToStreamVerifyGroup(res.body) + go wnfs.AppendToStreamVerifyGroup(res.body) } } for k := range wnfs.CollectionResponsePath { if strings.HasPrefix(ctx.Request.URL.Path, k) { - wnfs.AppendToCollectionVerifyGroup(res.body) + go wnfs.AppendToCollectionVerifyGroup(res.body) } } ctx.Abort() From 160b4a8786fcec15b2d72d214111d8c076d90ff6 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Mon, 28 Aug 2023 18:27:02 +0800 Subject: [PATCH 13/18] fix(test): getdapp --- pkg/dapp-table/getdapp_test.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/pkg/dapp-table/getdapp_test.go b/pkg/dapp-table/getdapp_test.go index 7c2c3a9..76628e0 100644 --- a/pkg/dapp-table/getdapp_test.go +++ b/pkg/dapp-table/getdapp_test.go @@ -2,7 +2,6 @@ package dapptable import ( "context" - "reflect" "testing" ) @@ -12,10 +11,9 @@ func TestGetDappByModelID(t *testing.T) { modelId string } tests := []struct { - name string - args args - wantDapp Dapp - wantErr bool + name string + args args + wantErr bool }{ { name: "common", @@ -28,13 +26,21 @@ func TestGetDappByModelID(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotDappBytes, err := GetDappByModelID(tt.args.ctx, tt.args.modelId) + gotDapp, err := GetDappByModelID(tt.args.ctx, tt.args.modelId) if (err != nil) != tt.wantErr { t.Errorf("GetDappByModelID() error = %v, wantErr %v", err, tt.wantErr) return } - if !reflect.DeepEqual(gotDappBytes, tt.wantDapp) { - t.Errorf("GetDappByModelID() = %v, want %v", gotDappBytes, tt.wantDapp) + isRightDapp := false + for _, app := range gotDapp.Models { + for _, model := range app.Streams { + if model.ModelId == tt.args.modelId { + isRightDapp = true + } + } + } + if !isRightDapp { + t.Errorf("GetDappByModelID().Models = %v, want contain %v", gotDapp.Models, tt.args.modelId) } }) } From 717e284e9d61c5e06a969fc57bed0f1f950be3f2 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Mon, 28 Aug 2023 18:27:25 +0800 Subject: [PATCH 14/18] feat(wnfs): save timestamp logindex --- internal/wnfs/proof.go | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/internal/wnfs/proof.go b/internal/wnfs/proof.go index 3e9c314..7de23c4 100644 --- a/internal/wnfs/proof.go +++ b/internal/wnfs/proof.go @@ -5,6 +5,8 @@ import ( "context" "encoding/json" "fmt" + "log" + "time" "github.com/dataverse-os/dapp-backend/ceramic" "github.com/ethereum/go-ethereum/common" @@ -30,7 +32,7 @@ var CollectionResponsePath = map[string]struct{}{ func AppendToStreamVerifyGroup(buf *bytes.Buffer) { var stream ceramic.Stream if err := json.Unmarshal(buf.Bytes(), &stream); err != nil { - fmt.Println(err) + log.Println(err) return } VerifyGroup.Go(func() (err error) { @@ -44,7 +46,7 @@ func AppendToStreamVerifyGroup(buf *bytes.Buffer) { func AppendToCollectionVerifyGroup(buf *bytes.Buffer) { var collection ceramic.Collection if err := json.Unmarshal(buf.Bytes(), &collection); err != nil { - fmt.Println(err) + log.Println(err) return } for _, v := range collection.Edges { @@ -67,12 +69,14 @@ const ( ) type CommitProof struct { - CommitId ceramic.StreamId `json:"commitId" gorm:"primaryKey"` - StreamId ceramic.StreamId `json:"streamId"` - Cid string `json:"cid"` - Hash common.Hash `json:"hash"` - Content json.RawMessage `json:"content" gorm:"type:jsonb"` - Status CommitProofStatus `json:"status"` + CommitId ceramic.StreamId `json:"commitId" gorm:"primaryKey"` + Timestamp time.Time `json:"timestamp"` + StreamId ceramic.StreamId `json:"streamId"` + LogIndex uint64 `json:"logIndex"` + Cid string `json:"cid"` + Hash common.Hash `json:"hash"` + Content json.RawMessage `json:"content" gorm:"type:jsonb"` + Status CommitProofStatus `json:"status"` } func StoreAndVerifyContentHash(ctx context.Context, streamState ceramic.StreamState) (err error) { @@ -105,9 +109,11 @@ func StoreAndVerifyContentHash(ctx context.Context, streamState ceramic.StreamSt continue } commitProofs[i] = CommitProof{ - CommitId: commitIds[i], - StreamId: streamId, - Cid: v.Cid, + CommitId: commitIds[i], + Timestamp: time.Unix(int64(v.Timestamp), 0), + StreamId: streamId, + LogIndex: uint64(i), + Cid: v.Cid, } if commit, err = commitIds[i].GetStream(ctx); err != nil { return From c184259636b158f4b8622665ceeb87da7b802568 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Mon, 28 Aug 2023 18:59:42 +0800 Subject: [PATCH 15/18] feat(wnfs): check http status ok --- internal/routers/ceramic_proxy.go | 15 ++++-------- internal/wnfs/proof.go | 39 ++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/internal/routers/ceramic_proxy.go b/internal/routers/ceramic_proxy.go index 46375c6..56aa750 100644 --- a/internal/routers/ceramic_proxy.go +++ b/internal/routers/ceramic_proxy.go @@ -3,7 +3,6 @@ package routers import ( "bytes" "net/http/httputil" - "strings" "github.com/dataverse-os/dapp-backend/internal/dapp" "github.com/dataverse-os/dapp-backend/internal/wnfs" @@ -24,15 +23,11 @@ func CeramicProxy(ctx *gin.Context) { body: new(bytes.Buffer), } proxy.ServeHTTP(res, ctx.Request) - for k := range wnfs.StreamResponsePath { - if strings.HasPrefix(ctx.Request.URL.Path, k) { - go wnfs.AppendToStreamVerifyGroup(res.body) - } - } - for k := range wnfs.CollectionResponsePath { - if strings.HasPrefix(ctx.Request.URL.Path, k) { - go wnfs.AppendToCollectionVerifyGroup(res.body) - } + switch { + case wnfs.IsGetStreamRequest(ctx): + go wnfs.HandleStreamVerify(res.body) + case wnfs.IsGetCollectionRequest(ctx): + go wnfs.HandleCollectionVerify(res.body) } ctx.Abort() } diff --git a/internal/wnfs/proof.go b/internal/wnfs/proof.go index 7de23c4..4e0724a 100644 --- a/internal/wnfs/proof.go +++ b/internal/wnfs/proof.go @@ -6,10 +6,13 @@ import ( "encoding/json" "fmt" "log" + "net/http" + "strings" "time" "github.com/dataverse-os/dapp-backend/ceramic" "github.com/ethereum/go-ethereum/common" + "github.com/gin-gonic/gin" "golang.org/x/sync/errgroup" ) @@ -20,16 +23,24 @@ func init() { VerifyGroup.SetLimit(1) } +func IsGetStreamRequest(ctx *gin.Context) bool { + if ctx.Writer.Status() != http.StatusOK { + return false + } + for k := range StreamResponsePath { + if strings.HasPrefix(ctx.Request.URL.Path, k) { + return true + } + } + return false +} + var StreamResponsePath = map[string]struct{}{ "/api/v0/streams/": {}, "/api/v0/commits/": {}, } -var CollectionResponsePath = map[string]struct{}{ - "/api/v0/collection": {}, -} - -func AppendToStreamVerifyGroup(buf *bytes.Buffer) { +func HandleStreamVerify(buf *bytes.Buffer) { var stream ceramic.Stream if err := json.Unmarshal(buf.Bytes(), &stream); err != nil { log.Println(err) @@ -43,7 +54,23 @@ func AppendToStreamVerifyGroup(buf *bytes.Buffer) { }) } -func AppendToCollectionVerifyGroup(buf *bytes.Buffer) { +func IsGetCollectionRequest(ctx *gin.Context) bool { + if ctx.Writer.Status() != http.StatusOK { + return false + } + for k := range CollectionResponsePath { + if strings.HasPrefix(ctx.Request.URL.Path, k) { + return true + } + } + return false +} + +var CollectionResponsePath = map[string]struct{}{ + "/api/v0/collection": {}, +} + +func HandleCollectionVerify(buf *bytes.Buffer) { var collection ceramic.Collection if err := json.Unmarshal(buf.Bytes(), &collection); err != nil { log.Println(err) From 4203d1eee6995dff876e7618deba1b1ca442466d Mon Sep 17 00:00:00 2001 From: FDKevin Date: Tue, 29 Aug 2023 18:52:01 +0800 Subject: [PATCH 16/18] feat(wnfs): impl ipfs dagJWS decode commit log --- ceramic/ipfs.go | 136 +++++++++++++++++++ ceramic/ipfs_test.go | 108 +++++++++++++++ go.mod | 37 +++++ go.sum | 312 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 581 insertions(+), 12 deletions(-) create mode 100644 ceramic/ipfs.go create mode 100644 ceramic/ipfs_test.go diff --git a/ceramic/ipfs.go b/ceramic/ipfs.go new file mode 100644 index 0000000..2df01f8 --- /dev/null +++ b/ceramic/ipfs.go @@ -0,0 +1,136 @@ +package ceramic + +import ( + "context" + "encoding/base64" + "encoding/json" + "fmt" + "io" + + "github.com/ceramicnetwork/go-dag-jose/dagjose" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ipfs/boxo/coreiface/path" + "github.com/ipfs/go-cid" + "github.com/ipfs/kubo/client/rpc" + "github.com/ipld/go-ipld-prime/datamodel" + cidlink "github.com/ipld/go-ipld-prime/linking/cid" + "github.com/ipld/go-ipld-prime/node/basicnode" + "github.com/ipld/go-ipld-prime/schema" +) + +type Commit struct { + Link cid.Cid + Payload cid.Cid + Signatures []Signature +} + +type Signature struct { + Header any + Protected json.RawMessage + Signature []byte +} + +func (sig Signature) String() string { + return fmt.Sprintf("header: %s\n", sig.Header) + + fmt.Sprintf("protected: %s\n", string(sig.Protected)) + + fmt.Sprintf("signature: %s", hexutil.Encode(sig.Signature)) +} + +func ConvertFrom(dagJws dagjose.DecodedJWS) (commit Commit, err error) { + payloadData, err := decodeBase64Url(dagJws.FieldPayload()) + if err != nil { + fmt.Println(err) + } + if commit.Payload, err = cid.Cast(payloadData); err != nil { + return + } + if link := dagJws.FieldLink(); link.Exists() { + if link, ok := link.Must().Link().(cidlink.Link); ok { + commit.Link = link.Cid + } + } + signatureIter := dagJws.FieldSignatures().Must().Iterator() + for !signatureIter.Done() { + _, item := signatureIter.Next() + sig := Signature{} + if protected := item.FieldProtected(); protected.Exists() { + if sig.Protected, err = decodeBase64Url(protected.Must()); err != nil { + return + } + } + if sig.Signature, err = decodeBase64Url(item.FieldSignature()); err != nil { + return + } + + commit.Signatures = append(commit.Signatures, sig) + } + return +} + +func LoadDagJWS(ctx context.Context, node *rpc.HttpApi, logCid cid.Cid) (dagJws dagjose.DecodedJWS, err error) { + var blockReader io.Reader + if blockReader, err = node.Block().Get(ctx, path.IpfsPath(logCid)); err != nil { + return + } + return BuildDagJWSFromReader(blockReader) +} + +func BuildDagJWSFromReader(reader io.Reader) (dagJws dagjose.DecodedJWS, err error) { + builder := dagjose.Type.DecodedJWS.NewBuilder() + cfg := dagjose.DecodeOptions{ + AddLink: true, + } + if err = cfg.DecodeJWS(builder, reader); err != nil { + return + } + var ok bool + if dagJws, ok = builder.Build().(dagjose.DecodedJWS); !ok { + err = fmt.Errorf("cannot asset %s as dagjose.DecodedJWS", builder.Build()) + } + return +} + +func BuildPayloadFromReader(reader io.Reader) { + builder := basicnode.Prototype.Map.NewBuilder() + _ = builder +} + +//nolint:unused +func lookupIgnoreAbsent(key string, n datamodel.Node) (datamodel.Node, error) { + value, err := n.LookupByString(key) + if err != nil { + if _, notFoundErr := err.(datamodel.ErrNotExists); !notFoundErr { + return nil, err + } + } + if value == datamodel.Absent { + value = nil + } + return value, nil +} + +//nolint:unused +func lookupIgnoreNoSuchField(key string, n datamodel.Node) (datamodel.Node, error) { + value, err := lookupIgnoreAbsent(key, n) + if err != nil { + if _, noSuchFieldErr := err.(schema.ErrNoSuchField); !noSuchFieldErr { + return nil, err + } + } + return value, nil +} + +func decodeBase64Url(field dagjose.Base64Url) (data []byte, err error) { + str, err := field.AsString() + if err != nil { + fmt.Println(err) + } + data, err = base64.RawURLEncoding.DecodeString(str) + return +} + +//nolint:unused +func decodeBase64UrlString(field dagjose.Base64Url) (string, error) { + data, err := decodeBase64Url(field) + return string(data), err +} diff --git a/ceramic/ipfs_test.go b/ceramic/ipfs_test.go new file mode 100644 index 0000000..9686f5e --- /dev/null +++ b/ceramic/ipfs_test.go @@ -0,0 +1,108 @@ +package ceramic + +import ( + "bytes" + "encoding/base64" + "reflect" + "testing" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ipfs/go-cid" +) + +func TestBuildDagJWSFromReader(t *testing.T) { + type args struct { + base64Encoded string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "common", + args: args{ + base64Encoded: "omdwYXlsb2FkWCQBcRIgGtqDmUTOFzN1JfGKAS9bP1KGrprc6FzbjWjnGQv9yjlqc2lnbmF0dXJlc4GiaXByb3RlY3RlZFjMeyJhbGciOiJFZERTQSIsImNhcCI6ImlwZnM6Ly9iYWZ5cmVpZm5qdno3NDZ1azJrcWhpdHpqN2I1b3hhNmRjcDR3N2J1ZzJhbnhqbHNlYXhiM2R0bG9qeSIsImtpZCI6ImRpZDprZXk6ejZNa3UxOUdnY2gxTlliUmlOREZQVGFwcmQ0aUZKVlVncThTTnpNNnNSTEZESk45I3o2TWt1MTlHZ2NoMU5ZYlJpTkRGUFRhcHJkNGlGSlZVZ3E4U056TTZzUkxGREpOOSJ9aXNpZ25hdHVyZVhAoy7KX9UhdAIpYq2cvN8Kjv+Ka3ps6GzjYHt6afsu8qYYI7pS4k9/Ln013MBMnUTe7eM0/+YuAKnnOmsO8a5ECw==", + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + buf, _ := base64.StdEncoding.DecodeString(tt.args.base64Encoded) + _, err := BuildDagJWSFromReader(bytes.NewBuffer(buf)) + if (err != nil) != tt.wantErr { + t.Errorf("BuildDagJWSFromReader() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } +} + +func TestBuildPayloadFromReader(t *testing.T) { + type args struct { + base64Encoded string + } + tests := []struct { + name string + args args + }{ + { + name: "common", + args: args{ + base64Encoded: "omRkYXRhpmdvcHRpb25zeQomZXlKbWIyeGtaWEpPWVcxbElqb2lWVzUwYVhSc1pXUWlMQ0ptYjJ4a1pYSkVaWE5qY21sd2RHbHZiaUk2SWlJc0ltVnVZM0o1Y0hSbFpGTjViVzFsZEhKcFkwdGxlU0k2SW1NM1pUWm1ORGs0T0RVeVpXWXlaV000TVRRd1l6WmhZamN3WkRkallXVTRZbVF3WmpNNU5HUTROemhqTURNNE9UTmpaR1JpTVdVNVlqbGhNekExTVRKaFpHRXlaRFV5TnpjelpUSm1OV001WXpCa01UVTBNak5pTWpOaE1tUXdaV1JrWkdVNVlUY3pZak0wWTJKbE1tTTNNRFJrTWpJMk1UWTBNekZoTkRBM1pEVXpNekl4WkRWaE5EbGpaR1JpTlRjMlkySTJPR05sWVRjd01tRTJObVptTm1abU5HUTRPR05rT1dabFpqTTBaamMxTVROaE56WmtaamhtTnpBNFptWmtNREJpWldJM1lqQXdObUk0WkRZME9UVXdOemxrWlRoaVpUQXpaR1kzTURVMU5qUm1OREJqTTJKallXRTFNV1UyTUdFM01EQmlPR016WW1abFl6RXdNREF3TURBd01EQXdNREF3TURJd05EaGhOalpsWVRkaE5URTVObUk0TW1Fell6VTRZbVJrWkdJMk1UQTBNV0l3WXpZNE16Z3dNREJrWkdZMFpUaGlaalEzTm1FNFpXSXpOV0UxWlRjeU1XUm1NbVpoTXpsak5qRmpORFl5WVRGa056VmxZMk5sTWpBME1tUmpOemcxSWl3aVpHVmpjbmx3ZEdsdmJrTnZibVJwZEdsdmJuTWlPaUpYTTNOcFdUSTVkV1JJU21oWk0xSkNXa2RTZVZwWVRucEphbTlwU1dsM2FXTXpVbWhpYlZKb1kyMVNSR0l5TlRCamJVWnFaRVpTTldOSFZXbFBhVWxwVEVOS2FtRkhSbkJpYVVrMlNXMVdNR0ZIVm5sYVdGWjBTV2wzYVdKWFZqQmhSemxyU1dwdmFVbHBkMmxqUjBaNVdWY3hiR1JIVm5samVVazJWM2xKTm1SWVRteGphMFpyV2toS2JHTXpUV2xZVTNkcFkyMVdNR1JZU25WV2JVWnpaRmRXVlZwWVRqQkphbkEzU1cxT2RtSllRbWhqYlVZd1lqTkphVTlwU1RsSmFYZHBaRzFHYzJSWFZXbFBhVWwzWlVSTmVFMXRWa0pQUkZWNVRucEpNbEpVVGtKUFYxa3lUWHBPUWsxRVRUTk9NazEzV2xkRk5FOUVTWGRQUkZwclRtcFpNazVxV1dsbVdEQnpaWGxLZG1OSFZubFpXRkoyWTJsSk5rbHRSblZhUTBvNVRFaHphVmt5T1hWa1NFcG9XVE5TUWxwSFVubGFXRTU2U1dwdmFVbHBkMmxqTTFKb1ltMVNhR050VWtSaU1qVXdZMjFHYW1SR1VqVmpSMVZwVDJsS1ZGTldaRVpKYVhkcFdUSm9hR0ZYTkdsUGFVcHNaRWRvYkdOdFZqRmlVMGx6U1cweGJHUkhhSFphUTBrMlNXbEpjMGx1UW1oamJVWjBXbGhTYkdOdVRXbFBiSE5wVDI1S2JHTXlPVEZqYlU1c1kzbEtaRXhEU25sYVdGSXhZMjAxVjFsWGVERmFWbEpzWXpOUmFVOXVjMmxaTWpsMFkwZEdlVmxZVW5aamFVazJTVzFPZG1KdVVtaGhWelY2U1dsM2FXUnRSbk5rVjFWcFQybEthbHBZU21oaVYyeHFUMms0ZGt0cU9YUmlNbEpzWWtReGNtRnVjSE5PYldneVdtNUthV1I2V21wT1dFWnJaVzVrY0U5WFZucGxTRm93VFZoWk1XSllVakJPTWpsclRqSm9hVTFxYXpCT2VsbDVUa2N4ZFU1SVZYZGpiVEY0VFZoS2IwOVhSblZoYlU1MVpVaG5hV1pZTUhObGVVcDJZMGRXZVZsWVVuWmphVWsyU1cxR2RWcERTamxNU0hOcFdUSTVkV1JJU21oWk0xSkNXa2RTZVZwWVRucEphbTlwU1dsM2FXTXpVbWhpYlZKb1kyMVNSR0l5TlRCamJVWnFaRVpTTldOSFZXbFBhVXBVVTFaa1JrbHBkMmxaTW1ob1lWYzBhVTlwU214a1IyaHNZMjFXTVdKVFNYTkpiVEZzWkVkb2RscERTVFpKYVVselNXNUNhR050Um5SYVdGSnNZMjVOYVU5c2MybFBia3BzWXpJNU1XTnRUbXhqZVVwa1RFTktlVnBZVWpGamJUVlhXVmQ0TVZwV1VteGpNMUZwVDI1emFWa3lPWFJqUjBaNVdWaFNkbU5wU1RaSmJVNTJZbTVTYUdGWE5YcEphWGRwWkcxR2MyUlhWV2xQYVVwcVdsaEthR0pYYkdwUGFUaDJTMm81ZEdJeVVteGlSREZ5WVc1d2MwNXRhREphYmtwcFpIcGFhazV0Um10T00yeHJZbXBDYjJGVVVqSmtSMFowWlVSS01rNXFTWGRoUjFKdVpGUmFjMkpJUlRCUFYyZDVUMGhLYlZwRVdtcGpla0Y1V25wT2FtSlhORFZsYlVWcFpsZ3djMlY1U25aalIxWjVXVmhTZG1OcFNUWkpiVVoxV2tOS09VeEljMmxaTWpsMVpFaEthRmt6VWtKYVIxSjVXbGhPZWtscWIybEphWGRwWXpOU2FHSnRVbWhqYlZKRVlqSTFNR050Um1wa1JsSTFZMGRWYVU5cFNsUlRWbVJHU1dsM2FWa3lhR2hoVnpScFQybEtiR1JIYUd4amJWWXhZbE5KYzBsdE1XeGtSMmgyV2tOSk5rbHBTWE5KYmtKb1kyMUdkRnBZVW14amJrMXBUMnh6YVU5dVNteGpNamt4WTIxT2JHTjVTbVJNUTBwNVdsaFNNV050TlZkWlYzZ3hXbFpTYkdNelVXbFBibk5wV1RJNWRHTkhSbmxaV0ZKMlkybEpOa2x0VG5aaWJsSm9ZVmMxZWtscGQybGtiVVp6WkZkVmFVOXBTbXBhV0Vwb1lsZHNhazlwT0haTGFqbDBZakpTYkdKRU1YSmhibkJ6VG0xb01scHVTbWxrZWxwcVRucFplbVJYU210aFJ6a3paVzFHZGsxSE1EQmxXRUUwVGtkT05HVnRTbTFpYlhodlRrZG9hMkZVVm1oaVNFWjJUa2hzZVZwWFNuUlpla0o0WTBkd2EyRlVWV2xtV0RGa0lpd2laVzVqY25sd2RHVmtJam9pUVVSWWNXYzNXbGRLVkVwNVNYUllaakZpTTJ0T01YcFliVFJCTVZoQlJVdzRXRXRUZVRWdFdYRnRaMlJ1UzI5RVprTmlWM2RoVFhkNWQwWlRlVWRtTmxaVlZGaHJlWEZ6ZW1sNFVrSkhMV3d6T0d4cFRWVmZOREp3WldJME0yWjBZa2RTYjJOblRXRk1NblZMTWpadFVYSXpNVlJDY0dSWlFWbDRSbGxWVnpVaWZRaWNyZWF0ZWRBdHgYMjAyMy0wNi0xMVQxMToyNDoyMy4wMjlaaXVwZGF0ZWRBdHgYMjAyMy0wNi0xMVQxMToyNDoyMy4wMjlaamFwcFZlcnNpb25lMC4yLjBqZm9sZGVyVHlwZQFwY29udGVudEZvbGRlcklkc4FkdGVtcGZoZWFkZXKjZW1vZGVsWCjOAQIBhQESIBzfRtp3sMC9cDyAKBAj8zq/N2Xd5IJPzEEoVKyvyJM1ZnVuaXF1ZUwrbXEamTAna5uAMqJrY29udHJvbGxlcnOBeDtkaWQ6cGtoOmVpcDE1NToxOjB4MzEyZUE4NTI3MjZFM0E5ZjYzM0EwMzc3YzBlYTg4MjA4NmQ2NjY2Ng==", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + buf, _ := base64.StdEncoding.DecodeString(tt.args.base64Encoded) + BuildPayloadFromReader(bytes.NewBuffer(buf)) + }) + } +} + +func TestConvertFrom(t *testing.T) { + type args struct { + base64Encoded string + } + tests := []struct { + name string + args args + wantCommit Commit + wantErr bool + }{ + { + name: "common", + args: args{ + base64Encoded: "omdwYXlsb2FkWCQBcRIgGtqDmUTOFzN1JfGKAS9bP1KGrprc6FzbjWjnGQv9yjlqc2lnbmF0dXJlc4GiaXByb3RlY3RlZFjMeyJhbGciOiJFZERTQSIsImNhcCI6ImlwZnM6Ly9iYWZ5cmVpZm5qdno3NDZ1azJrcWhpdHpqN2I1b3hhNmRjcDR3N2J1ZzJhbnhqbHNlYXhiM2R0bG9qeSIsImtpZCI6ImRpZDprZXk6ejZNa3UxOUdnY2gxTlliUmlOREZQVGFwcmQ0aUZKVlVncThTTnpNNnNSTEZESk45I3o2TWt1MTlHZ2NoMU5ZYlJpTkRGUFRhcHJkNGlGSlZVZ3E4U056TTZzUkxGREpOOSJ9aXNpZ25hdHVyZVhAoy7KX9UhdAIpYq2cvN8Kjv+Ka3ps6GzjYHt6afsu8qYYI7pS4k9/Ln013MBMnUTe7eM0/+YuAKnnOmsO8a5ECw==", + }, + wantCommit: Commit{ + Link: cid.MustParse("bafyreia23kbzsrgoc4zxkjprrias6wz7kkdk5gw45bonxdli44mqx7okhe"), + Payload: cid.MustParse("bafyreia23kbzsrgoc4zxkjprrias6wz7kkdk5gw45bonxdli44mqx7okhe"), + Signatures: []Signature{ + { + Header: nil, + Protected: []byte(`{"alg":"EdDSA","cap":"ipfs://bafyreifnjvz746uk2kqhitzj7b5oxa6dcp4w7bug2anxjlseaxb3dtlojy","kid":"did:key:z6Mku19Ggch1NYbRiNDFPTaprd4iFJVUgq8SNzM6sRLFDJN9#z6Mku19Ggch1NYbRiNDFPTaprd4iFJVUgq8SNzM6sRLFDJN9"}`), + Signature: hexutil.MustDecode("0xa32eca5fd52174022962ad9cbcdf0a8eff8a6b7a6ce86ce3607b7a69fb2ef2a61823ba52e24f7f2e7d35dcc04c9d44deede334ffe62e00a9e73a6b0ef1ae440b"), + }, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + buf, _ := base64.StdEncoding.DecodeString(tt.args.base64Encoded) + dagJws, _ := BuildDagJWSFromReader(bytes.NewBuffer(buf)) + gotCommit, err := ConvertFrom(dagJws) + if (err != nil) != tt.wantErr { + t.Errorf("ConvertFrom() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(gotCommit, tt.wantCommit) { + t.Errorf("ConvertFrom() = %v\nwant %v", gotCommit, tt.wantCommit) + } + }) + } +} diff --git a/go.mod b/go.mod index 2ce3b02..809b2ac 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,16 @@ module github.com/dataverse-os/dapp-backend go 1.21 require ( + github.com/ceramicnetwork/go-dag-jose v0.1.0 github.com/ethereum/go-ethereum v1.12.2 github.com/gin-gonic/gin v1.9.1 github.com/google/uuid v1.3.1 github.com/graphql-go/graphql v0.8.1 github.com/hasura/go-graphql-client v0.10.0 + github.com/ipfs/boxo v0.11.0 github.com/ipfs/go-cid v0.4.1 + github.com/ipfs/kubo v0.22.0 + github.com/ipld/go-ipld-prime v0.21.0 github.com/lib/pq v1.10.9 github.com/multiformats/go-multibase v0.2.0 github.com/multiformats/go-multicodec v0.9.0 @@ -29,42 +33,74 @@ require ( github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/bytedance/sonic v1.9.2 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.14.1 // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.2 // indirect github.com/holiman/uint256 v1.2.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/ipfs/bbloom v0.0.4 // indirect + github.com/ipfs/go-block-format v0.1.2 // indirect + github.com/ipfs/go-datastore v0.6.0 // indirect + github.com/ipfs/go-ipfs-cmds v0.9.0 // indirect + github.com/ipfs/go-ipfs-util v0.0.3 // indirect + github.com/ipfs/go-ipld-format v0.5.0 // indirect + github.com/ipfs/go-ipld-legacy v0.2.1 // indirect + github.com/ipfs/go-log v1.0.5 // indirect + github.com/ipfs/go-log/v2 v2.5.1 // indirect + github.com/ipfs/go-metrics-interface v0.0.1 // indirect + github.com/ipld/go-codec-dagpb v1.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.4.3 // indirect + github.com/jbenet/goprocess v0.1.4 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.16.7 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/leodido/go-urn v1.2.4 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/libp2p/go-libp2p v0.29.2 // indirect + github.com/libp2p/go-libp2p-record v0.2.0 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/minio/sha256-simd v1.0.1 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.1.0 // indirect github.com/multiformats/go-base36 v0.2.0 // indirect + github.com/multiformats/go-multiaddr v0.11.0 // indirect github.com/multiformats/go-multihash v0.2.3 // indirect + github.com/multiformats/go-multistream v0.4.1 // indirect github.com/multiformats/go-varint v0.0.7 // indirect + github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pelletier/go-toml/v2 v2.0.9 // indirect + github.com/polydawn/refmt v0.89.0 // indirect + github.com/rs/cors v1.7.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect + go.opentelemetry.io/otel v1.16.0 // indirect + go.opentelemetry.io/otel/metric v1.16.0 // indirect + go.opentelemetry.io/otel/trace v1.16.0 // indirect + go.uber.org/atomic v1.11.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.24.0 // indirect golang.org/x/arch v0.4.0 // indirect golang.org/x/crypto v0.12.0 // indirect golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect @@ -72,6 +108,7 @@ require ( golang.org/x/sys v0.11.0 // indirect golang.org/x/text v0.12.0 // indirect google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/square/go-jose.v2 v2.5.1 // indirect gorm.io/driver/mysql v1.5.1 // indirect lukechampine.com/blake3 v1.2.1 // indirect nhooyr.io/websocket v1.8.7 // indirect diff --git a/go.sum b/go.sum index beece7b..5313e4d 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8= @@ -5,6 +6,9 @@ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrU github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= +github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= @@ -21,6 +25,9 @@ github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46f github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.9.2 h1:GDaNjuWSGu09guE9Oql0MSTNhNCLlWwO8y/xM5BzcbM= github.com/bytedance/sonic v1.9.2/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/ceramicnetwork/go-dag-jose v0.1.0 h1:yJ/HVlfKpnD3LdYP03AHyTvbm3BpPiz2oZiOeReJRdU= +github.com/ceramicnetwork/go-dag-jose v0.1.0/go.mod h1:qYA1nYt0X8u4XoMAVoOV3upUVKtrxy/I670Dg5F0wjI= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= @@ -34,17 +41,34 @@ github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoG github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811/go.mod h1:Nb5lgvnQ2+oGlE/EyZy4+2/CxRh9KfvCXnag1vtpxVM= github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/cockroachdb/redact v1.1.3/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= +github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU= +github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/ethereum/go-ethereum v1.12.2 h1:eGHJ4ij7oyVqUQn48LBz3B7pvQ8sV0wGJiIE6gDq/6Y= github.com/ethereum/go-ethereum v1.12.2/go.mod h1:1cRAEV+rp/xX0zraSCBnu9Py3HQ+geRMj3HdR+k0wfI= +github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A= +github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg= +github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ= +github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag= +github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk= +github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= +github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= @@ -55,6 +79,11 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -74,6 +103,9 @@ github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrt github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= @@ -90,21 +122,32 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0kt github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= +github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8 h1:n6vlPhxsA+BW/XsS5+uqi7GyzaLa5MH7qlSLBZtRdiA= +github.com/google/pprof v0.0.0-20230705174524-200ffdc848b8/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4= +github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= @@ -114,21 +157,76 @@ github.com/graph-gophers/graphql-transport-ws v0.0.2 h1:DbmSkbIGzj8SvHei6n8Mh9eL github.com/graph-gophers/graphql-transport-ws v0.0.2/go.mod h1:5BVKvFzOd2BalVIBFfnfmHjpJi/MZ5rOj8G55mXvZ8g= github.com/graphql-go/graphql v0.8.1 h1:p7/Ou/WpmulocJeEx7wjQy611rtXGQaAcXGqanuMMgc= github.com/graphql-go/graphql v0.8.1/go.mod h1:nKiHzRM0qopJEwCITUuIsxk9PlVlwIiiI8pnJEhordQ= +github.com/hashicorp/golang-lru/v2 v2.0.2 h1:Dwmkdr5Nc/oBiXgJS3CDHNhJtIHkuZ3DZF5twqnfBdU= +github.com/hashicorp/golang-lru/v2 v2.0.2/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hasura/go-graphql-client v0.10.0 h1:eQm/ap/rqxMG6yAGe6J+FkXu1VqJ9p21E63vz0A7zLQ= github.com/hasura/go-graphql-client v0.10.0/go.mod h1:z9UPkMmCBMuJjvBEtdE6F+oTR2r15AcjirVNq/8P+Ig= github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY= +github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= +github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= +github.com/ipfs/boxo v0.11.0 h1:urMxhZ3xoF4HssJVD3+0ssGT9pptEfHfbL8DYdoWFlg= +github.com/ipfs/boxo v0.11.0/go.mod h1:8IfDmp+FzFGcF4zjAgHMVPpwYw4AjN9ePEzDfkaYJ1w= +github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo= +github.com/ipfs/go-block-format v0.1.2/go.mod h1:mACVcrxarQKstUU3Yf/RdwbC4DzPV6++rO2a3d+a/KE= +github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= +github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= +github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk= +github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8= +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-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ= +github.com/ipfs/go-ipfs-blocksutil v0.0.1/go.mod h1:Yq4M86uIOmxmGPUHv/uI7uKqZNtLb449gwKqXjIsnRk= +github.com/ipfs/go-ipfs-cmds v0.9.0 h1:K0VcXg1l1k6aY6sHnoxYcyimyJQbcV1ueXuWgThmK9Q= +github.com/ipfs/go-ipfs-cmds v0.9.0/go.mod h1:SBFHK8WNwC416QWH9Vz1Ql42SSMAOqKpaHUMBu3jpLo= +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-pq v0.0.3 h1:YpoHVJB+jzK15mr/xsWC574tyDLkezVrDNeaalQBsTE= +github.com/ipfs/go-ipfs-pq v0.0.3/go.mod h1:btNw5hsHBpRcSSgZtiNm/SLj5gYIZ18AKtv3kERkRb4= +github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0= +github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs= +github.com/ipfs/go-ipld-cbor v0.0.6 h1:pYuWHyvSpIsOOLw4Jy7NbBkCyzLDcl64Bf/LZW7eBQ0= +github.com/ipfs/go-ipld-cbor v0.0.6/go.mod h1:ssdxxaLJPXH7OjF5V4NSjBbcfh+evoR4ukuru0oPXMA= +github.com/ipfs/go-ipld-format v0.5.0 h1:WyEle9K96MSrvr47zZHKKcDxJ/vlpET6PSiQsAFO+Ds= +github.com/ipfs/go-ipld-format v0.5.0/go.mod h1:ImdZqJQaEouMjCvqCe0ORUS+uoBmf7Hf+EO/jh+nk3M= +github.com/ipfs/go-ipld-legacy v0.2.1 h1:mDFtrBpmU7b//LzLSypVrXsD8QxkEWxu5qVxN99/+tk= +github.com/ipfs/go-ipld-legacy v0.2.1/go.mod h1:782MOUghNzMO2DER0FlBR94mllfdCJCkTtDtPM51otM= +github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8= +github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo= +github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g= +github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY= +github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI= +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-peertaskqueue v0.8.1 h1:YhxAs1+wxb5jk7RvS0LHdyiILpNmRIRnZVztekOF0pg= +github.com/ipfs/go-peertaskqueue v0.8.1/go.mod h1:Oxxd3eaK279FxeydSPPVGHzbwVeHjatZ2GA8XD+KbPU= +github.com/ipfs/kubo v0.22.0 h1:HxYkvtFqlF+qQMTxHW+xBhrIWykWm+WbEuQpw1d67mM= +github.com/ipfs/kubo v0.22.0/go.mod h1:Sn3hp55POjH9Ni0lEd/+smXpkZ0J1gKlm0Fx+E1LE60= +github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc= +github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s= +github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0= +github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E= +github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= +github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= +github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= +github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= +github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= @@ -138,15 +236,26 @@ github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlT github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +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/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/koron/go-ssdp v0.0.4 h1:1IDwrghSKYM7yLf7XCzbByg2sJ/JcNOZRXS2jczTwz0= +github.com/koron/go-ssdp v0.0.4/go.mod h1:oDXq+E5IL5q0U8uSBcoAXzTzInwy5lEgC91HoKtbmZk= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= @@ -156,7 +265,26 @@ github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c= +github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= +github.com/libp2p/go-libp2p v0.29.2 h1:uPw/c8hOxoLP/KhFnzlc5Ejqf+OmAL1dwIsqE31WBtY= +github.com/libp2p/go-libp2p v0.29.2/go.mod h1:OU7nSq0aEZMsV2wY8nXn1+XNNt9q2UiR8LjW3Kmp2UE= +github.com/libp2p/go-libp2p-asn-util v0.3.0 h1:gMDcMyYiZKkocGXDQ5nsUQyquC9+H+iLEQHwOCZ7s8s= +github.com/libp2p/go-libp2p-asn-util v0.3.0/go.mod h1:B1mcOrKUE35Xq/ASTmQ4tN3LNzVVaMNmq2NACuqyB9w= +github.com/libp2p/go-libp2p-record v0.2.0 h1:oiNUOCWno2BFuxt3my4i1frNrt7PerzB3queqa1NkQ0= +github.com/libp2p/go-libp2p-record v0.2.0/go.mod h1:I+3zMkvvg5m2OcSdoL0KPljyJyvNDFGKX7QdlpYUcwk= +github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= +github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= +github.com/libp2p/go-msgio v0.3.0/go.mod h1:nyRM819GmVaF9LX3l03RMh10QdOroF++NBbxAb0mmDM= +github.com/libp2p/go-nat v0.2.0 h1:Tyz+bUFAYqGyJ/ppPPymMGbIgNRH+WqC5QrT5fKrrGk= +github.com/libp2p/go-nat v0.2.0/go.mod h1:3MJr+GRpRkyT65EpVPBstXLvOlAPzUVlG6Pwg9ohLJk= +github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU= +github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= @@ -167,54 +295,115 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= +github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= +github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +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/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= +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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI= +github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0= github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= +github.com/multiformats/go-multiaddr v0.11.0 h1:XqGyJ8ufbCE0HmTDwx2kPdsrQ36AGPZNZX6s6xfJH10= +github.com/multiformats/go-multiaddr v0.11.0/go.mod h1:gWUm0QLR4thQ6+ZF6SXUw8YjtwQSPapICM+NmCkxHSM= +github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= +github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= +github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= +github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g= github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk= +github.com/multiformats/go-multicodec v0.3.0/go.mod h1:qGGaQmioCDh+TeFOnxrbU0DaIPw8yFgAZgFG0V7p1qQ= github.com/multiformats/go-multicodec v0.9.0 h1:pb/dlPnzee/Sxv/j4PmkDRxCOi3hXTz3IbPKOXWJkmg= github.com/multiformats/go-multicodec v0.9.0/go.mod h1:L3QTQvMIaVBkXOXXtVmYE+LI16i14xuaojr/H7Ai54k= +github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.1.0/go.mod h1:RJlXsxt6vHGaia+S8We0ErjhojtKzPP2AH4+kYM7k84= github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U= github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM= +github.com/multiformats/go-multistream v0.4.1 h1:rFy0Iiyn3YT0asivDUIR05leAdwZq3de4741sbiSdfo= +github.com/multiformats/go-multistream v0.4.1/go.mod h1:Mz5eykRVAjJWckE2U78c6xqdtyNUEhKSM0Lwar2p77Q= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= 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.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.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/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= -github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= -github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= -github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= -github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI= -github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y= -github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI= -github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= +github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= +github.com/polydawn/refmt v0.89.0 h1:ADJTApkvkeBZsN0tBTx8QjpD9JkmxbKp0cxfr9qszm4= +github.com/polydawn/refmt v0.89.0/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk= +github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= +github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= +github.com/quic-go/qtls-go1-19 v0.3.3 h1:wznEHvJwd+2X3PqftRha0SUKmGsnb6dfArMhy9PeJVE= +github.com/quic-go/qtls-go1-19 v0.3.3/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +github.com/quic-go/qtls-go1-20 v0.2.3 h1:m575dovXn1y2ATOb1XrRFcrv0F+EQmlowTkoraNkDPI= +github.com/quic-go/qtls-go1-20 v0.2.3/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= +github.com/quic-go/quic-go v0.36.4 h1:CXn/ZLN5Vntlk53fjR+kUMC8Jt7flfQe+I5Ty5A+k0o= +github.com/quic-go/quic-go v0.36.4/go.mod h1:qxQumdeKw5GmWs1OsTZZnOxzSI+RJWuhf1O8FN35L2o= +github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU= +github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= +github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= +github.com/smartystreets/goconvey v1.7.2/go.mod h1:Vw0tHAZW6lzCRk3xgdin6fKYcG+G3Pg9vgXWeJpQFMM= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= @@ -252,47 +441,142 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= +github.com/warpfork/go-testmark v0.9.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0= +github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s= +github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y= +github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= +github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= +github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= +github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa h1:EyA027ZAkuaCLoxVX4r1TZMPy1d31fM6hbfQ4OU4I5o= +github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ= +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/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= +go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= +go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= +go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= +go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= +go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc= golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= +golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/datatypes v1.2.0 h1:5YT+eokWdIxhJgWHdrb2zYUimyk0+TaFth+7a0ybzco= @@ -308,8 +592,12 @@ gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHD gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +pgregory.net/rapid v0.4.7 h1:MTNRktPuv5FNqOO151TM9mDTa+XHcX6ypYeISDVD14g= +pgregory.net/rapid v0.4.7/go.mod h1:UYpPVyjFHzYBGHIxLFoupi8vwk6rXNzRY9OMvVxFIOU= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= From 1610cc7007674589b5e0c738cf111587525ccce9 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Thu, 31 Aug 2023 17:57:23 +0800 Subject: [PATCH 17/18] feat(ceramic): ipfs commit impl --- ceramic/commit_utils.go | 30 +++++ ceramic/commits.go | 233 +++++++++++++++++++++++++++++++++++ ceramic/commits_test.go | 136 ++++++++++++++++++++ ceramic/dagjose.go | 83 +++++++++++++ ceramic/dagjose_test.go | 36 ++++++ ceramic/httpapi.go | 27 ++++ ceramic/ipfs.go | 138 ++++++--------------- ceramic/ipfs_pubsub.go | 118 ++++++++++++++++++ ceramic/ipfs_pubsub_utils.go | 12 ++ ceramic/ipfs_test.go | 107 ---------------- ceramic/stream.go | 20 --- ceramic/streamid.go | 52 +++++--- 12 files changed, 747 insertions(+), 245 deletions(-) create mode 100644 ceramic/commit_utils.go create mode 100644 ceramic/commits.go create mode 100644 ceramic/commits_test.go create mode 100644 ceramic/dagjose.go create mode 100644 ceramic/dagjose_test.go create mode 100644 ceramic/httpapi.go create mode 100644 ceramic/ipfs_pubsub.go create mode 100644 ceramic/ipfs_pubsub_utils.go diff --git a/ceramic/commit_utils.go b/ceramic/commit_utils.go new file mode 100644 index 0000000..65507e4 --- /dev/null +++ b/ceramic/commit_utils.go @@ -0,0 +1,30 @@ +package ceramic + +import ( + "io" + + "github.com/ipfs/go-cid" + "github.com/ipld/go-ipld-prime/codec/dagcbor" + "github.com/ipld/go-ipld-prime/datamodel" + cidlink "github.com/ipld/go-ipld-prime/linking/cid" + "github.com/ipld/go-ipld-prime/node/basicnode" + "github.com/samber/lo" +) + +func MustParseLink(nd datamodel.Node, key string) cid.Cid { + link := lo.Must(lo.Must(nd.LookupByString(key)).AsLink()).(cidlink.Link) + return link.Cid +} + +func DecodeDagCborNodeDataFromReader(reader io.Reader) (nd datamodel.Node, err error) { + builder := basicnode.Prototype.Map.NewBuilder() + if err = dagcbor.Decode(builder, reader); err != nil { + return + } + nd = builder.Build() + return +} + +func ContainField(nd datamodel.Node, key string) bool { + return lo.T2(nd.LookupByString(key)).A.IsNull() +} diff --git a/ceramic/commits.go b/ceramic/commits.go new file mode 100644 index 0000000..4baadd0 --- /dev/null +++ b/ceramic/commits.go @@ -0,0 +1,233 @@ +package ceramic + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + + "github.com/ceramicnetwork/go-dag-jose/dagjose" + "github.com/ipfs/boxo/coreiface/path" + "github.com/ipfs/go-cid" + "github.com/ipld/go-ipld-prime/datamodel" + cidlink "github.com/ipld/go-ipld-prime/linking/cid" + "github.com/samber/lo" +) + +type NodeDataDecoder interface { + DecodeFromNodeData(nd datamodel.Node) (err error) +} + +var CommitTypeDelecters = []CommitTypeDelecter{ + &AnchorCommit{}, +} + +type CommitWithPayload interface { + LoadPayload() (payload CommitPayload, err error) +} + +type CommitPayload interface { + NodeDataDecoder + DelectType(nd datamodel.Node) bool + ApplyToStream(state *StreamState) (err error) +} + +type CommitTypeDelecter interface { + DelectType(nd datamodel.Node) bool +} + +type CommitHeader struct { + Model StreamId // raw as StreamID encoded as byte array + Controllers []string + Unique []byte +} + +func (header *CommitHeader) DecodeFromNodeData(nd datamodel.Node) (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("recovered in %s", r) + return + } + }() + header.Model = lo.Must(CastStreamID( + lo.Must(lo.Must(nd.LookupByString("model")).AsBytes()), + )) + header.Unique = lo.Must(lo.Must(nd.LookupByString("unique")).AsBytes()) + iter := lo.Must(nd.LookupByString("controllers")).ListIterator() + for !iter.Done() { + _, n, _ := iter.Next() + header.Controllers = append(header.Controllers, lo.Must(n.AsString())) + } + return +} + +var _ CommitPayload = (*GenesisCommitPayload)(nil) + +type GenesisCommitPayload struct { + Header CommitHeader + Data json.RawMessage +} + +func (commit *GenesisCommitPayload) ApplyToStream(state *StreamState) (err error) { + state.Content = commit.Data + return +} + +func (*GenesisCommitPayload) DelectType(nd datamodel.Node) bool { + return ContainField(nd, "header") && !ContainField(nd, "id") +} + +func (commit *GenesisCommitPayload) DecodeFromNodeData(nd datamodel.Node) (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("recovered in %s", r) + return + } + }() + var buf bytes.Buffer + if err = dagjsonEncodeOption.Encode(lo.Must(nd.LookupByString("data")), &buf); err != nil { + return + } + commit.Data = buf.Bytes() + if headerNode, e := nd.LookupByString("header"); e == nil && !headerNode.IsNull() { + if err = commit.Header.DecodeFromNodeData(headerNode); err != nil { + return + } + } + return +} + +var _ CommitPayload = (*DataCommitPayload)(nil) + +type DataCommitPayload struct { + ID cid.Cid // link to init event + Prev cid.Cid + Header *CommitHeader + Data json.RawMessage +} + +func (commit *DataCommitPayload) DecodeFromNodeData(nd datamodel.Node) (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("recovered in %s", r) + return + } + }() + commit.ID = MustParseLink(nd, "id") + commit.Prev = MustParseLink(nd, "prev") + + var buf bytes.Buffer + if err = dagjsonEncodeOption.Encode(lo.Must(nd.LookupByString("data")), &buf); err != nil { + return + } + commit.Data = buf.Bytes() + return +} + +func (DataCommitPayload) DelectType(nd datamodel.Node) bool { + return ContainField(nd, "prev") && !ContainField(nd, "proof") +} + +func (commit *DataCommitPayload) ApplyToStream(state *StreamState) (err error) { + //TODO + return +} + +var _ NodeDataDecoder = (*AnchorCommit)(nil) + +type AnchorCommit struct { + ID cid.Cid // link to init event + Prev cid.Cid + Proof cid.Cid + Path string +} + +func (*AnchorCommit) ApplyToStream(state *StreamState) (err error) { + return +} + +func (*AnchorCommit) DelectType(nd datamodel.Node) bool { + return ContainField(nd, "proof") +} + +func (commit *AnchorCommit) DecodeFromNodeData(nd datamodel.Node) (err error) { + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("recovered in %s", r) + return + } + }() + commit.ID = MustParseLink(nd, "id") + commit.Prev = MustParseLink(nd, "prev") + commit.Proof = MustParseLink(nd, "proof") + commit.Path = lo.Must(lo.Must(nd.LookupByString("path")).AsString()) + return +} + +var _ NodeDataDecoder = (*SignedCommit)(nil) + +type SignedCommit struct { + linkedCommit CommitPayload + Link cid.Cid + Payload cid.Cid + Signatures []Signature +} + +func (commit *SignedCommit) GetPayload() CommitPayload { + return commit.linkedCommit +} + +func (commit *SignedCommit) LoadPayload(ctx context.Context, impl IpfsImpl) (err error) { + var ( + blkReader io.Reader + nd datamodel.Node + ) + if blkReader, err = impl.node.Block().Get(ctx, path.IpfsPath(commit.Payload)); err != nil { + return + } + if nd, err = DecodeDagCborNodeDataFromReader(blkReader); err != nil { + return + } + if ContainField(nd, "prev") { + commit.linkedCommit = &DataCommitPayload{} + } else { + commit.linkedCommit = &GenesisCommitPayload{} + } + if err = commit.DecodeFromNodeData(nd); err != nil { + return + } + return +} + +func (commit *SignedCommit) DecodeFromNodeData(nd datamodel.Node) (err error) { + dagJws := nd.(dagjose.DecodedJWS) + payloadData, err := decodeBase64Url(dagJws.FieldPayload()) + if err != nil { + return + } + if commit.Payload, err = cid.Cast(payloadData); err != nil { + return + } + if link := dagJws.FieldLink(); link.Exists() { + if link, ok := link.Must().Link().(cidlink.Link); ok { + commit.Link = link.Cid + } + } + signatureIter := dagJws.FieldSignatures().Must().Iterator() + for !signatureIter.Done() { + _, item := signatureIter.Next() + sig := Signature{} + if protected := item.FieldProtected(); protected.Exists() { + if sig.Protected, err = decodeBase64Url(protected.Must()); err != nil { + return + } + } + if sig.Signature, err = decodeBase64Url(item.FieldSignature()); err != nil { + return + } + + commit.Signatures = append(commit.Signatures, sig) + } + return +} diff --git a/ceramic/commits_test.go b/ceramic/commits_test.go new file mode 100644 index 0000000..0a52d5b --- /dev/null +++ b/ceramic/commits_test.go @@ -0,0 +1,136 @@ +package ceramic_test + +import ( + "bytes" + "encoding/base64" + "reflect" + "testing" + + "github.com/dataverse-os/dapp-backend/ceramic" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ipfs/go-cid" + "github.com/samber/lo" +) + +func TestGenesisCommit_DecodeFromBlockReader(t *testing.T) { + type args struct { + base64Encoded string + } + tests := []struct { + name string + wantCommit *ceramic.GenesisCommitPayload + args args + wantErr bool + }{ + { + name: "common", + args: args{base64Encoded: "omRkYXRhpmdvcHRpb25zeQomZXlKbWIyeGtaWEpPWVcxbElqb2lWVzUwYVhSc1pXUWlMQ0ptYjJ4a1pYSkVaWE5qY21sd2RHbHZiaUk2SWlJc0ltVnVZM0o1Y0hSbFpGTjViVzFsZEhKcFkwdGxlU0k2SW1NM1pUWm1ORGs0T0RVeVpXWXlaV000TVRRd1l6WmhZamN3WkRkallXVTRZbVF3WmpNNU5HUTROemhqTURNNE9UTmpaR1JpTVdVNVlqbGhNekExTVRKaFpHRXlaRFV5TnpjelpUSm1OV001WXpCa01UVTBNak5pTWpOaE1tUXdaV1JrWkdVNVlUY3pZak0wWTJKbE1tTTNNRFJrTWpJMk1UWTBNekZoTkRBM1pEVXpNekl4WkRWaE5EbGpaR1JpTlRjMlkySTJPR05sWVRjd01tRTJObVptTm1abU5HUTRPR05rT1dabFpqTTBaamMxTVROaE56WmtaamhtTnpBNFptWmtNREJpWldJM1lqQXdObUk0WkRZME9UVXdOemxrWlRoaVpUQXpaR1kzTURVMU5qUm1OREJqTTJKallXRTFNV1UyTUdFM01EQmlPR016WW1abFl6RXdNREF3TURBd01EQXdNREF3TURJd05EaGhOalpsWVRkaE5URTVObUk0TW1Fell6VTRZbVJrWkdJMk1UQTBNV0l3WXpZNE16Z3dNREJrWkdZMFpUaGlaalEzTm1FNFpXSXpOV0UxWlRjeU1XUm1NbVpoTXpsak5qRmpORFl5WVRGa056VmxZMk5sTWpBME1tUmpOemcxSWl3aVpHVmpjbmx3ZEdsdmJrTnZibVJwZEdsdmJuTWlPaUpYTTNOcFdUSTVkV1JJU21oWk0xSkNXa2RTZVZwWVRucEphbTlwU1dsM2FXTXpVbWhpYlZKb1kyMVNSR0l5TlRCamJVWnFaRVpTTldOSFZXbFBhVWxwVEVOS2FtRkhSbkJpYVVrMlNXMVdNR0ZIVm5sYVdGWjBTV2wzYVdKWFZqQmhSemxyU1dwdmFVbHBkMmxqUjBaNVdWY3hiR1JIVm5samVVazJWM2xKTm1SWVRteGphMFpyV2toS2JHTXpUV2xZVTNkcFkyMVdNR1JZU25WV2JVWnpaRmRXVlZwWVRqQkphbkEzU1cxT2RtSllRbWhqYlVZd1lqTkphVTlwU1RsSmFYZHBaRzFHYzJSWFZXbFBhVWwzWlVSTmVFMXRWa0pQUkZWNVRucEpNbEpVVGtKUFYxa3lUWHBPUWsxRVRUTk9NazEzV2xkRk5FOUVTWGRQUkZwclRtcFpNazVxV1dsbVdEQnpaWGxLZG1OSFZubFpXRkoyWTJsSk5rbHRSblZhUTBvNVRFaHphVmt5T1hWa1NFcG9XVE5TUWxwSFVubGFXRTU2U1dwdmFVbHBkMmxqTTFKb1ltMVNhR050VWtSaU1qVXdZMjFHYW1SR1VqVmpSMVZwVDJsS1ZGTldaRVpKYVhkcFdUSm9hR0ZYTkdsUGFVcHNaRWRvYkdOdFZqRmlVMGx6U1cweGJHUkhhSFphUTBrMlNXbEpjMGx1UW1oamJVWjBXbGhTYkdOdVRXbFBiSE5wVDI1S2JHTXlPVEZqYlU1c1kzbEtaRXhEU25sYVdGSXhZMjAxVjFsWGVERmFWbEpzWXpOUmFVOXVjMmxaTWpsMFkwZEdlVmxZVW5aamFVazJTVzFPZG1KdVVtaGhWelY2U1dsM2FXUnRSbk5rVjFWcFQybEthbHBZU21oaVYyeHFUMms0ZGt0cU9YUmlNbEpzWWtReGNtRnVjSE5PYldneVdtNUthV1I2V21wT1dFWnJaVzVrY0U5WFZucGxTRm93VFZoWk1XSllVakJPTWpsclRqSm9hVTFxYXpCT2VsbDVUa2N4ZFU1SVZYZGpiVEY0VFZoS2IwOVhSblZoYlU1MVpVaG5hV1pZTUhObGVVcDJZMGRXZVZsWVVuWmphVWsyU1cxR2RWcERTamxNU0hOcFdUSTVkV1JJU21oWk0xSkNXa2RTZVZwWVRucEphbTlwU1dsM2FXTXpVbWhpYlZKb1kyMVNSR0l5TlRCamJVWnFaRVpTTldOSFZXbFBhVXBVVTFaa1JrbHBkMmxaTW1ob1lWYzBhVTlwU214a1IyaHNZMjFXTVdKVFNYTkpiVEZzWkVkb2RscERTVFpKYVVselNXNUNhR050Um5SYVdGSnNZMjVOYVU5c2MybFBia3BzWXpJNU1XTnRUbXhqZVVwa1RFTktlVnBZVWpGamJUVlhXVmQ0TVZwV1VteGpNMUZwVDI1emFWa3lPWFJqUjBaNVdWaFNkbU5wU1RaSmJVNTJZbTVTYUdGWE5YcEphWGRwWkcxR2MyUlhWV2xQYVVwcVdsaEthR0pYYkdwUGFUaDJTMm81ZEdJeVVteGlSREZ5WVc1d2MwNXRhREphYmtwcFpIcGFhazV0Um10T00yeHJZbXBDYjJGVVVqSmtSMFowWlVSS01rNXFTWGRoUjFKdVpGUmFjMkpJUlRCUFYyZDVUMGhLYlZwRVdtcGpla0Y1V25wT2FtSlhORFZsYlVWcFpsZ3djMlY1U25aalIxWjVXVmhTZG1OcFNUWkpiVVoxV2tOS09VeEljMmxaTWpsMVpFaEthRmt6VWtKYVIxSjVXbGhPZWtscWIybEphWGRwWXpOU2FHSnRVbWhqYlZKRVlqSTFNR050Um1wa1JsSTFZMGRWYVU5cFNsUlRWbVJHU1dsM2FWa3lhR2hoVnpScFQybEtiR1JIYUd4amJWWXhZbE5KYzBsdE1XeGtSMmgyV2tOSk5rbHBTWE5KYmtKb1kyMUdkRnBZVW14amJrMXBUMnh6YVU5dVNteGpNamt4WTIxT2JHTjVTbVJNUTBwNVdsaFNNV050TlZkWlYzZ3hXbFpTYkdNelVXbFBibk5wV1RJNWRHTkhSbmxaV0ZKMlkybEpOa2x0VG5aaWJsSm9ZVmMxZWtscGQybGtiVVp6WkZkVmFVOXBTbXBhV0Vwb1lsZHNhazlwT0haTGFqbDBZakpTYkdKRU1YSmhibkJ6VG0xb01scHVTbWxrZWxwcVRucFplbVJYU210aFJ6a3paVzFHZGsxSE1EQmxXRUUwVGtkT05HVnRTbTFpYlhodlRrZG9hMkZVVm1oaVNFWjJUa2hzZVZwWFNuUlpla0o0WTBkd2EyRlVWV2xtV0RGa0lpd2laVzVqY25sd2RHVmtJam9pUVVSWWNXYzNXbGRLVkVwNVNYUllaakZpTTJ0T01YcFliVFJCTVZoQlJVdzRXRXRUZVRWdFdYRnRaMlJ1UzI5RVprTmlWM2RoVFhkNWQwWlRlVWRtTmxaVlZGaHJlWEZ6ZW1sNFVrSkhMV3d6T0d4cFRWVmZOREp3WldJME0yWjBZa2RTYjJOblRXRk1NblZMTWpadFVYSXpNVlJDY0dSWlFWbDRSbGxWVnpVaWZRaWNyZWF0ZWRBdHgYMjAyMy0wNi0xMVQxMToyNDoyMy4wMjlaaXVwZGF0ZWRBdHgYMjAyMy0wNi0xMVQxMToyNDoyMy4wMjlaamFwcFZlcnNpb25lMC4yLjBqZm9sZGVyVHlwZQFwY29udGVudEZvbGRlcklkc4FkdGVtcGZoZWFkZXKjZW1vZGVsWCjOAQIBhQESIBzfRtp3sMC9cDyAKBAj8zq/N2Xd5IJPzEEoVKyvyJM1ZnVuaXF1ZUwrbXEamTAna5uAMqJrY29udHJvbGxlcnOBeDtkaWQ6cGtoOmVpcDE1NToxOjB4MzEyZUE4NTI3MjZFM0E5ZjYzM0EwMzc3YzBlYTg4MjA4NmQ2NjY2Ng=="}, + wantCommit: &ceramic.GenesisCommitPayload{ + Header: ceramic.CommitHeader{ + Model: ceramic.MustParseStreamID("kjzl6hvfrbw6c5qdzwi9esxvt1v5mtt7od7hb2947624mn4u0rmq1rh9anjcnxx"), + Controllers: []string{ + "did:pkh:eip155:1:0x312eA852726E3A9f633A0377c0ea882086d66666", + }, + Unique: []byte{43, 109, 113, 26, 153, 48, 39, 107, 155, 128, 50, 162}, + }, + Data: []byte(`{"options":"eyJmb2xkZXJOYW1lIjoiVW50aXRsZWQiLCJmb2xkZXJEZXNjcmlwdGlvbiI6IiIsImVuY3J5cHRlZFN5bW1ldHJpY0tleSI6ImM3ZTZmNDk4ODUyZWYyZWM4MTQwYzZhYjcwZDdjYWU4YmQwZjM5NGQ4NzhjMDM4OTNjZGRiMWU5YjlhMzA1MTJhZGEyZDUyNzczZTJmNWM5YzBkMTU0MjNiMjNhMmQwZWRkZGU5YTczYjM0Y2JlMmM3MDRkMjI2MTY0MzFhNDA3ZDUzMzIxZDVhNDljZGRiNTc2Y2I2OGNlYTcwMmE2NmZmNmZmNGQ4OGNkOWZlZjM0Zjc1MTNhNzZkZjhmNzA4ZmZkMDBiZWI3YjAwNmI4ZDY0OTUwNzlkZThiZTAzZGY3MDU1NjRmNDBjM2JjYWE1MWU2MGE3MDBiOGMzYmZlYzEwMDAwMDAwMDAwMDAwMDIwNDhhNjZlYTdhNTE5NmI4MmEzYzU4YmRkZGI2MTA0MWIwYzY4MzgwMDBkZGY0ZThiZjQ3NmE4ZWIzNWE1ZTcyMWRmMmZhMzljNjFjNDYyYTFkNzVlY2NlMjA0MmRjNzg1IiwiZGVjcnlwdGlvbkNvbmRpdGlvbnMiOiJXM3NpWTI5dWRISmhZM1JCWkdSeVpYTnpJam9pSWl3aWMzUmhibVJoY21SRGIyNTBjbUZqZEZSNWNHVWlPaUlpTENKamFHRnBiaUk2SW1WMGFHVnlaWFZ0SWl3aWJXVjBhRzlrSWpvaUlpd2ljR0Z5WVcxbGRHVnljeUk2V3lJNmRYTmxja0ZrWkhKbGMzTWlYU3dpY21WMGRYSnVWbUZzZFdWVVpYTjBJanA3SW1OdmJYQmhjbUYwYjNJaU9pSTlJaXdpZG1Gc2RXVWlPaUl3ZURNeE1tVkJPRFV5TnpJMlJUTkJPV1kyTXpOQk1ETTNOMk13WldFNE9ESXdPRFprTmpZMk5qWWlmWDBzZXlKdmNHVnlZWFJ2Y2lJNkltRnVaQ0o5TEhzaVkyOXVkSEpoWTNSQlpHUnlaWE56SWpvaUlpd2ljM1JoYm1SaGNtUkRiMjUwY21GamRGUjVjR1VpT2lKVFNWZEZJaXdpWTJoaGFXNGlPaUpsZEdobGNtVjFiU0lzSW0xbGRHaHZaQ0k2SWlJc0luQmhjbUZ0WlhSbGNuTWlPbHNpT25KbGMyOTFjbU5sY3lKZExDSnlaWFIxY201V1lXeDFaVlJsYzNRaU9uc2lZMjl0Y0dGeVlYUnZjaUk2SW1OdmJuUmhhVzV6SWl3aWRtRnNkV1VpT2lKalpYSmhiV2xqT2k4dktqOXRiMlJsYkQxcmFucHNObWgyWm5KaWR6WmpOWEZrZW5kcE9XVnplSFowTVhZMWJYUjBOMjlrTjJoaU1qazBOell5TkcxdU5IVXdjbTF4TVhKb09XRnVhbU51ZUhnaWZYMHNleUp2Y0dWeVlYUnZjaUk2SW1GdVpDSjlMSHNpWTI5dWRISmhZM1JCWkdSeVpYTnpJam9pSWl3aWMzUmhibVJoY21SRGIyNTBjbUZqZEZSNWNHVWlPaUpUU1ZkRklpd2lZMmhoYVc0aU9pSmxkR2hsY21WMWJTSXNJbTFsZEdodlpDSTZJaUlzSW5CaGNtRnRaWFJsY25NaU9sc2lPbkpsYzI5MWNtTmxjeUpkTENKeVpYUjFjbTVXWVd4MVpWUmxjM1FpT25zaVkyOXRjR0Z5WVhSdmNpSTZJbU52Ym5SaGFXNXpJaXdpZG1Gc2RXVWlPaUpqWlhKaGJXbGpPaTh2S2o5dGIyUmxiRDFyYW5wc05taDJabkppZHpaak5tRmtOM2xrYmpCb2FUUjJkR0Z0ZURKMk5qSXdhR1JuZFRac2JIRTBPV2d5T0hKbVpEWmpjekF5WnpOamJXNDVlbUVpZlgwc2V5SnZjR1Z5WVhSdmNpSTZJbUZ1WkNKOUxIc2lZMjl1ZEhKaFkzUkJaR1J5WlhOeklqb2lJaXdpYzNSaGJtUmhjbVJEYjI1MGNtRmpkRlI1Y0dVaU9pSlRTVmRGSWl3aVkyaGhhVzRpT2lKbGRHaGxjbVYxYlNJc0ltMWxkR2h2WkNJNklpSXNJbkJoY21GdFpYUmxjbk1pT2xzaU9uSmxjMjkxY21ObGN5SmRMQ0p5WlhSMWNtNVdZV3gxWlZSbGMzUWlPbnNpWTI5dGNHRnlZWFJ2Y2lJNkltTnZiblJoYVc1eklpd2lkbUZzZFdVaU9pSmpaWEpoYldsak9pOHZLajl0YjJSbGJEMXJhbnBzTm1oMlpuSmlkelpqTnpZemRXSmthRzkzZW1Gdk1HMDBlWEE0TkdONGVtSm1ibXhvTkdoa2FUVmhiSEZ2TkhseVpXSnRZekJ4Y0dwa2FUVWlmWDFkIiwiZW5jcnlwdGVkIjoiQURYcWc3WldKVEp5SXRYZjFiM2tOMXpYbTRBMVhBRUw4WEtTeTVtWXFtZ2RuS29EZkNiV3dhTXd5d0ZTeUdmNlZVVFhreXFzeml4UkJHLWwzOGxpTVVfNDJwZWI0M2Z0YkdSb2NnTWFMMnVLMjZtUXIzMVRCcGRZQVl4RllVVzUifQ","createdAt":"2023-06-11T11:24:23.029Z","updatedAt":"2023-06-11T11:24:23.029Z","appVersion":"0.2.0","folderType":1,"contentFolderIds":["temp"]}`), + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + commit := &ceramic.GenesisCommitPayload{} + buf := bytes.NewBuffer(lo.Must(base64.StdEncoding.DecodeString(tt.args.base64Encoded))) + nd, _ := ceramic.DecodeDagCborNodeDataFromReader(buf) + if err := commit.DecodeFromNodeData(nd); (err != nil) != tt.wantErr { + t.Errorf("GenesisCommit.DecodeFromBlockReader() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(commit, tt.wantCommit) { + t.Errorf("ConvertFrom() = %v\nwant %v", commit, tt.wantCommit) + } + }) + } +} + +func TestAnchorCommit_DecodeFromBlockReader(t *testing.T) { + type args struct { + base64Encoded string + } + tests := []struct { + name string + wantCommit *ceramic.AnchorCommit + args args + wantErr bool + }{ + { + name: "common", + wantCommit: &ceramic.AnchorCommit{ + ID: cid.MustParse("bagcqcera73sgdmuyznkpycnrkskk222l7qu6menvrx2ldyenjxdmsdabru6q"), + Prev: cid.MustParse("bagcqcerafrbuvb252ortgwwdpequn6i3bn67qxiholbff2irmqgqp6bmtxuq"), + Proof: cid.MustParse("bafyreidtdpcjnltl7enswtp4s4xbsweb5zndvzihiyczl3t6ppqvbcgjpu"), + Path: "0/0/0/1/0/0/0/0/1", + }, + args: args{ + base64Encoded: "pGJpZNgqWCYAAYUBEiD+5GGymMtU/AmxVJSta0v8KeYRtY30seCNTcbJDAGNPWRwYXRocTAvMC8wLzEvMC8wLzAvMC8xZHByZXbYKlgmAAGFARIgLENKh13TozNaw3khRvkbC334XQdywlLpEWQNB/gsnellcHJvb2bYKlglAAFxEiBzG8SWrmv5GytN/JcuGViB7lo65QdGBZXufnvhUIjJfQ==", + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + commit := &ceramic.AnchorCommit{} + buf := bytes.NewBuffer(lo.Must(base64.StdEncoding.DecodeString(tt.args.base64Encoded))) + nd, _ := ceramic.DecodeDagCborNodeDataFromReader(buf) + if err := commit.DecodeFromNodeData(nd); (err != nil) != tt.wantErr { + t.Errorf("AnchorCommit.DecodeFromBlockReader() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(commit, tt.wantCommit) { + t.Errorf("ConvertFrom() = %v\nwant %v", commit, tt.wantCommit) + } + }) + } +} + +func TestSignedCommit_DecodeFromBlockReader(t *testing.T) { + type args struct { + base64Encoded string + } + tests := []struct { + name string + wantCommit *ceramic.SignedCommit + args args + wantErr bool + }{ + { + name: "common", + args: args{ + base64Encoded: "omdwYXlsb2FkWCQBcRIgGtqDmUTOFzN1JfGKAS9bP1KGrprc6FzbjWjnGQv9yjlqc2lnbmF0dXJlc4GiaXByb3RlY3RlZFjMeyJhbGciOiJFZERTQSIsImNhcCI6ImlwZnM6Ly9iYWZ5cmVpZm5qdno3NDZ1azJrcWhpdHpqN2I1b3hhNmRjcDR3N2J1ZzJhbnhqbHNlYXhiM2R0bG9qeSIsImtpZCI6ImRpZDprZXk6ejZNa3UxOUdnY2gxTlliUmlOREZQVGFwcmQ0aUZKVlVncThTTnpNNnNSTEZESk45I3o2TWt1MTlHZ2NoMU5ZYlJpTkRGUFRhcHJkNGlGSlZVZ3E4U056TTZzUkxGREpOOSJ9aXNpZ25hdHVyZVhAoy7KX9UhdAIpYq2cvN8Kjv+Ka3ps6GzjYHt6afsu8qYYI7pS4k9/Ln013MBMnUTe7eM0/+YuAKnnOmsO8a5ECw==", + }, + wantCommit: &ceramic.SignedCommit{ + Payload: cid.MustParse("bafyreia23kbzsrgoc4zxkjprrias6wz7kkdk5gw45bonxdli44mqx7okhe"), + Signatures: []ceramic.Signature{ + { + Header: nil, + Protected: []byte(`{"alg":"EdDSA","cap":"ipfs://bafyreifnjvz746uk2kqhitzj7b5oxa6dcp4w7bug2anxjlseaxb3dtlojy","kid":"did:key:z6Mku19Ggch1NYbRiNDFPTaprd4iFJVUgq8SNzM6sRLFDJN9#z6Mku19Ggch1NYbRiNDFPTaprd4iFJVUgq8SNzM6sRLFDJN9"}`), + Signature: hexutil.MustDecode("0xa32eca5fd52174022962ad9cbcdf0a8eff8a6b7a6ce86ce3607b7a69fb2ef2a61823ba52e24f7f2e7d35dcc04c9d44deede334ffe62e00a9e73a6b0ef1ae440b"), + }, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + commit := &ceramic.SignedCommit{} + buf := bytes.NewBuffer(lo.Must(base64.StdEncoding.DecodeString(tt.args.base64Encoded))) + nd, _ := ceramic.DecodeDagJWSNodeDataFromReader(buf) + if err := commit.DecodeFromNodeData(nd); (err != nil) != tt.wantErr { + t.Errorf("SignedCommit.DecodeFromBlockReader() error = %v, wantErr %v", err, tt.wantErr) + } + if !reflect.DeepEqual(commit, tt.wantCommit) { + t.Errorf("ConvertFrom() = %v\nwant %v", commit, tt.wantCommit) + } + }) + } +} diff --git a/ceramic/dagjose.go b/ceramic/dagjose.go new file mode 100644 index 0000000..902cbf6 --- /dev/null +++ b/ceramic/dagjose.go @@ -0,0 +1,83 @@ +package ceramic + +import ( + "context" + "encoding/base64" + "encoding/json" + "fmt" + "io" + + "github.com/ceramicnetwork/go-dag-jose/dagjose" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ipfs/boxo/coreiface/path" + "github.com/ipfs/go-cid" + "github.com/ipfs/kubo/client/rpc" + "github.com/ipld/go-ipld-prime/codec" + "github.com/ipld/go-ipld-prime/codec/dagjson" + "github.com/ipld/go-ipld-prime/datamodel" +) + +type DagJWS struct { + Link cid.Cid + Payload cid.Cid + Signatures []Signature +} + +type Signature struct { + Header any + Protected json.RawMessage + Signature []byte +} + +func (sig Signature) String() string { + return fmt.Sprintf("header: %s\n", sig.Header) + + fmt.Sprintf("protected: %s\n", string(sig.Protected)) + + fmt.Sprintf("signature: %s\n", hexutil.Encode(sig.Signature)) +} + +var ( + dagjsonEncodeOption = dagjson.EncodeOptions{ + EncodeLinks: true, + EncodeBytes: true, + MapSortMode: codec.MapSortMode_None, + } +) + +func LoadDagJWS(ctx context.Context, node *rpc.HttpApi, logCid cid.Cid) (dagJws dagjose.DecodedJWS, err error) { + var blockReader io.Reader + if blockReader, err = node.Block().Get(ctx, path.IpfsPath(logCid)); err != nil { + return + } + return DecodeDagJWSFromReader(blockReader) +} + +func DecodeDagJWSNodeDataFromReader(reader io.Reader) (nd datamodel.Node, err error) { + builder := dagjose.Type.DecodedJWS.NewBuilder() + cfg := dagjose.DecodeOptions{} + if err = cfg.DecodeJWS(builder, reader); err != nil { + return + } + nd = builder.Build() + return +} + +func DecodeDagJWSFromReader(reader io.Reader) (dagJws dagjose.DecodedJWS, err error) { + var nd datamodel.Node + if nd, err = DecodeDagJWSNodeDataFromReader(reader); err != nil { + return + } + var ok bool + if dagJws, ok = nd.(dagjose.DecodedJWS); !ok { + err = fmt.Errorf("cannot asset %s as dagjose.DecodedJWS", nd) + } + return +} + +func decodeBase64Url(field dagjose.Base64Url) (data []byte, err error) { + str, err := field.AsString() + if err != nil { + return + } + data, err = base64.RawURLEncoding.DecodeString(str) + return +} diff --git a/ceramic/dagjose_test.go b/ceramic/dagjose_test.go new file mode 100644 index 0000000..99b3739 --- /dev/null +++ b/ceramic/dagjose_test.go @@ -0,0 +1,36 @@ +package ceramic + +import ( + "bytes" + "encoding/base64" + "testing" +) + +func TestBuildDagJWSFromReader(t *testing.T) { + type args struct { + base64Encoded string + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "common", + args: args{ + base64Encoded: "omdwYXlsb2FkWCQBcRIgGtqDmUTOFzN1JfGKAS9bP1KGrprc6FzbjWjnGQv9yjlqc2lnbmF0dXJlc4GiaXByb3RlY3RlZFjMeyJhbGciOiJFZERTQSIsImNhcCI6ImlwZnM6Ly9iYWZ5cmVpZm5qdno3NDZ1azJrcWhpdHpqN2I1b3hhNmRjcDR3N2J1ZzJhbnhqbHNlYXhiM2R0bG9qeSIsImtpZCI6ImRpZDprZXk6ejZNa3UxOUdnY2gxTlliUmlOREZQVGFwcmQ0aUZKVlVncThTTnpNNnNSTEZESk45I3o2TWt1MTlHZ2NoMU5ZYlJpTkRGUFRhcHJkNGlGSlZVZ3E4U056TTZzUkxGREpOOSJ9aXNpZ25hdHVyZVhAoy7KX9UhdAIpYq2cvN8Kjv+Ka3ps6GzjYHt6afsu8qYYI7pS4k9/Ln013MBMnUTe7eM0/+YuAKnnOmsO8a5ECw==", + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + buf, _ := base64.StdEncoding.DecodeString(tt.args.base64Encoded) + _, err := DecodeDagJWSFromReader(bytes.NewBuffer(buf)) + if (err != nil) != tt.wantErr { + t.Errorf("BuildDagJWSFromReader() error = %v, wantErr %v", err, tt.wantErr) + return + } + }) + } +} diff --git a/ceramic/httpapi.go b/ceramic/httpapi.go new file mode 100644 index 0000000..6fe51e5 --- /dev/null +++ b/ceramic/httpapi.go @@ -0,0 +1,27 @@ +package ceramic + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "os" +) + +type HttpApi struct{} + +func (HttpApi) GetStreamId(ctx context.Context, streamId StreamId) (stream Stream, err error) { + url := fmt.Sprintf("%s/api/v0/streams/%s", os.Getenv("CERAMIC_URL"), streamId) + var req *http.Request + var resp *http.Response + if req, err = http.NewRequestWithContext(ctx, http.MethodGet, url, nil); err != nil { + return + } + if resp, err = http.DefaultClient.Do(req); err != nil { + return + } + if err = json.NewDecoder(resp.Body).Decode(&stream); err != nil { + return + } + return +} diff --git a/ceramic/ipfs.go b/ceramic/ipfs.go index 2df01f8..63813d8 100644 --- a/ceramic/ipfs.go +++ b/ceramic/ipfs.go @@ -1,136 +1,76 @@ package ceramic import ( + "bytes" "context" - "encoding/base64" - "encoding/json" "fmt" "io" - "github.com/ceramicnetwork/go-dag-jose/dagjose" - "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ipfs/boxo/coreiface/path" "github.com/ipfs/go-cid" "github.com/ipfs/kubo/client/rpc" "github.com/ipld/go-ipld-prime/datamodel" - cidlink "github.com/ipld/go-ipld-prime/linking/cid" - "github.com/ipld/go-ipld-prime/node/basicnode" - "github.com/ipld/go-ipld-prime/schema" ) -type Commit struct { - Link cid.Cid - Payload cid.Cid - Signatures []Signature +func NewIpfsImpl(node *rpc.HttpApi) IpfsImpl { + return IpfsImpl{node: node} } -type Signature struct { - Header any - Protected json.RawMessage - Signature []byte +type IpfsImpl struct { + node *rpc.HttpApi } -func (sig Signature) String() string { - return fmt.Sprintf("header: %s\n", sig.Header) + - fmt.Sprintf("protected: %s\n", string(sig.Protected)) + - fmt.Sprintf("signature: %s", hexutil.Encode(sig.Signature)) -} - -func ConvertFrom(dagJws dagjose.DecodedJWS) (commit Commit, err error) { - payloadData, err := decodeBase64Url(dagJws.FieldPayload()) - if err != nil { - fmt.Println(err) - } - if commit.Payload, err = cid.Cast(payloadData); err != nil { +func (impl IpfsImpl) LoadStreamState(ctx context.Context, tip cid.Cid) (state StreamState, err error) { + var commits []NodeDataDecoder + if commits, err = impl.LoadCommits(ctx, tip); err != nil { return } - if link := dagJws.FieldLink(); link.Exists() { - if link, ok := link.Must().Link().(cidlink.Link); ok { - commit.Link = link.Cid - } - } - signatureIter := dagJws.FieldSignatures().Must().Iterator() - for !signatureIter.Done() { - _, item := signatureIter.Next() - sig := Signature{} - if protected := item.FieldProtected(); protected.Exists() { - if sig.Protected, err = decodeBase64Url(protected.Must()); err != nil { + for _, commit := range commits { + if stateBuilder, ok := commit.(CommitPayload); ok { + if err = stateBuilder.ApplyToStream(&state); err != nil { return } } - if sig.Signature, err = decodeBase64Url(item.FieldSignature()); err != nil { - return - } - - commit.Signatures = append(commit.Signatures, sig) } return } -func LoadDagJWS(ctx context.Context, node *rpc.HttpApi, logCid cid.Cid) (dagJws dagjose.DecodedJWS, err error) { - var blockReader io.Reader - if blockReader, err = node.Block().Get(ctx, path.IpfsPath(logCid)); err != nil { - return - } - return BuildDagJWSFromReader(blockReader) -} +func (impl IpfsImpl) LoadCommits(ctx context.Context, c cid.Cid) (commits []NodeDataDecoder, err error) { -func BuildDagJWSFromReader(reader io.Reader) (dagJws dagjose.DecodedJWS, err error) { - builder := dagjose.Type.DecodedJWS.NewBuilder() - cfg := dagjose.DecodeOptions{ - AddLink: true, - } - if err = cfg.DecodeJWS(builder, reader); err != nil { - return - } - var ok bool - if dagJws, ok = builder.Build().(dagjose.DecodedJWS); !ok { - err = fmt.Errorf("cannot asset %s as dagjose.DecodedJWS", builder.Build()) - } return } -func BuildPayloadFromReader(reader io.Reader) { - builder := basicnode.Prototype.Map.NewBuilder() - _ = builder -} - -//nolint:unused -func lookupIgnoreAbsent(key string, n datamodel.Node) (datamodel.Node, error) { - value, err := n.LookupByString(key) - if err != nil { - if _, notFoundErr := err.(datamodel.ErrNotExists); !notFoundErr { - return nil, err - } - } - if value == datamodel.Absent { - value = nil +func (impl IpfsImpl) LoadLog(ctx context.Context, c cid.Cid) (commit NodeDataDecoder, err error) { + var ( + blkReader io.Reader + nd datamodel.Node + ) + if blkReader, err = impl.node.Block().Get(ctx, path.IpfsPath(c)); err != nil { + return } - return value, nil -} - -//nolint:unused -func lookupIgnoreNoSuchField(key string, n datamodel.Node) (datamodel.Node, error) { - value, err := lookupIgnoreAbsent(key, n) - if err != nil { - if _, noSuchFieldErr := err.(schema.ErrNoSuchField); !noSuchFieldErr { - return nil, err + if c.Prefix().Codec == cid.DagJOSE { + commit = &SignedCommit{} + if nd, err = DecodeDagJWSNodeDataFromReader(blkReader); err != nil { + return + } + var buf bytes.Buffer + if err = dagjsonEncodeOption.Encode(nd, &buf); err != nil { + return } + fmt.Println(c.Prefix().Codec, buf.String()) + err = commit.DecodeFromNodeData(nd) + impl.LoadLog(ctx, commit.(*SignedCommit).Payload) + return } - return value, nil -} -func decodeBase64Url(field dagjose.Base64Url) (data []byte, err error) { - str, err := field.AsString() - if err != nil { - fmt.Println(err) + if nd, err = DecodeDagCborNodeDataFromReader(blkReader); err != nil { + return } - data, err = base64.RawURLEncoding.DecodeString(str) - return -} + var buf bytes.Buffer + if err = dagjsonEncodeOption.Encode(nd, &buf); err != nil { + return + } + fmt.Println(c.Prefix().Codec, buf.String()) -//nolint:unused -func decodeBase64UrlString(field dagjose.Base64Url) (string, error) { - data, err := decodeBase64Url(field) - return string(data), err + return nil, nil } diff --git a/ceramic/ipfs_pubsub.go b/ceramic/ipfs_pubsub.go new file mode 100644 index 0000000..66639f5 --- /dev/null +++ b/ceramic/ipfs_pubsub.go @@ -0,0 +1,118 @@ +package ceramic + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "log" + + iface "github.com/ipfs/boxo/coreiface" + "github.com/ipfs/go-cid" + "github.com/ipfs/kubo/client/rpc" + "github.com/tidwall/gjson" +) + +type MessageType uint64 + +const ( + MessageTypeUpdate MessageType = iota + MessageTypeQuery + MessageTypeResponse + MessageTypeKeepalive +) + +type PubSubUpdateMessage struct { + Type MessageType `json:"typ"` + StreamId StreamId `json:"stream"` + Tip cid.Cid `json:"tip"` // the CID of the latest commit + Model *StreamId `json:"model"` // optional +} + +type PubSubQueryMessage struct { + Type MessageType `json:"typ"` + ID string `json:"id"` //query id + StreamId StreamId `json:"stream"` +} + +type PubSubResponseMessage struct { + Type MessageType `json:"typ"` + ID string `json:"id"` //query id + Tips map[StreamId]cid.Cid `json:"tips"` +} + +// All nodes will always ignore this message +type PubSubKeepaliveMessage struct { + Type MessageType `json:"typ"` + Timestamp uint64 `json:"ts"` // current time in milliseconds since epoch + Version string `json:"version"` // current ceramic version + IPFSVersion string `json:"ipfsVer"` +} + +func QueryStream(ctx context.Context, node *rpc.HttpApi, network string, streamId StreamId) (tip cid.Cid, err error) { + var buf bytes.Buffer + if err = json.NewEncoder(&buf).Encode(map[string]any{ + "typ": MessageTypeQuery, + "stream": streamId, + }); err != nil { + return + } + queryId := MessageHash(buf.Bytes()) + fmt.Println(queryId) + queryMsg := PubSubQueryMessage{ + Type: MessageTypeQuery, + ID: queryId, + StreamId: streamId, + } + buf = bytes.Buffer{} + if err = json.NewEncoder(&buf).Encode(queryMsg); err != nil { + return + } + fmt.Println(buf.String()) + if err = node.PubSub().Publish(ctx, network, buf.Bytes()); err != nil { + return + } + var sub iface.PubSubSubscription + if sub, err = node.PubSub().Subscribe(ctx, network); err != nil { + return + } + defer sub.Close() + for { + if msg, err := sub.Next(ctx); err != nil { + log.Println(err) + } else { + if typ := gjson.GetBytes(msg.Data(), "typ"); typ.Exists() && typ.Type == gjson.Number && typ.Num == float64(MessageTypeResponse) { + fmt.Println(string(msg.Data())) + if gjson.GetBytes(msg.Data(), "id").String() == queryId { + fmt.Println("hit", string(msg.Data())) + sub.Close() + break + } + } + } + } + return +} + +type MessageHander func(ctx context.Context, msg iface.PubSubMessage) error + +func SubscirbeMessage(ctx context.Context, node *rpc.HttpApi, network string, handlers map[MessageType]MessageHander) (err error) { + var sub iface.PubSubSubscription + if sub, err = node.PubSub().Subscribe(ctx, network); err != nil { + return + } + defer sub.Close() + for { + if msg, err := sub.Next(ctx); err != nil { + log.Println(err) + } else { + if typ := gjson.GetBytes(msg.Data(), "typ"); typ.Exists() && typ.Type == gjson.Number { + if h, exists := handlers[MessageType(typ.Num)]; exists { + if err := h(ctx, msg); err != nil { + log.Println(err) + } + } + } + } + } +} diff --git a/ceramic/ipfs_pubsub_utils.go b/ceramic/ipfs_pubsub_utils.go new file mode 100644 index 0000000..8a5baf8 --- /dev/null +++ b/ceramic/ipfs_pubsub_utils.go @@ -0,0 +1,12 @@ +package ceramic + +import ( + "crypto/sha256" + "encoding/base64" +) + +func MessageHash(msg []byte) string { + hash := sha256.New() + hash.Write(msg) + return base64.URLEncoding.EncodeToString(hash.Sum(nil)) +} diff --git a/ceramic/ipfs_test.go b/ceramic/ipfs_test.go index 9686f5e..0c55f97 100644 --- a/ceramic/ipfs_test.go +++ b/ceramic/ipfs_test.go @@ -1,108 +1 @@ package ceramic - -import ( - "bytes" - "encoding/base64" - "reflect" - "testing" - - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ipfs/go-cid" -) - -func TestBuildDagJWSFromReader(t *testing.T) { - type args struct { - base64Encoded string - } - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "common", - args: args{ - base64Encoded: "omdwYXlsb2FkWCQBcRIgGtqDmUTOFzN1JfGKAS9bP1KGrprc6FzbjWjnGQv9yjlqc2lnbmF0dXJlc4GiaXByb3RlY3RlZFjMeyJhbGciOiJFZERTQSIsImNhcCI6ImlwZnM6Ly9iYWZ5cmVpZm5qdno3NDZ1azJrcWhpdHpqN2I1b3hhNmRjcDR3N2J1ZzJhbnhqbHNlYXhiM2R0bG9qeSIsImtpZCI6ImRpZDprZXk6ejZNa3UxOUdnY2gxTlliUmlOREZQVGFwcmQ0aUZKVlVncThTTnpNNnNSTEZESk45I3o2TWt1MTlHZ2NoMU5ZYlJpTkRGUFRhcHJkNGlGSlZVZ3E4U056TTZzUkxGREpOOSJ9aXNpZ25hdHVyZVhAoy7KX9UhdAIpYq2cvN8Kjv+Ka3ps6GzjYHt6afsu8qYYI7pS4k9/Ln013MBMnUTe7eM0/+YuAKnnOmsO8a5ECw==", - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - buf, _ := base64.StdEncoding.DecodeString(tt.args.base64Encoded) - _, err := BuildDagJWSFromReader(bytes.NewBuffer(buf)) - if (err != nil) != tt.wantErr { - t.Errorf("BuildDagJWSFromReader() error = %v, wantErr %v", err, tt.wantErr) - return - } - }) - } -} - -func TestBuildPayloadFromReader(t *testing.T) { - type args struct { - base64Encoded string - } - tests := []struct { - name string - args args - }{ - { - name: "common", - args: args{ - base64Encoded: "omRkYXRhpmdvcHRpb25zeQomZXlKbWIyeGtaWEpPWVcxbElqb2lWVzUwYVhSc1pXUWlMQ0ptYjJ4a1pYSkVaWE5qY21sd2RHbHZiaUk2SWlJc0ltVnVZM0o1Y0hSbFpGTjViVzFsZEhKcFkwdGxlU0k2SW1NM1pUWm1ORGs0T0RVeVpXWXlaV000TVRRd1l6WmhZamN3WkRkallXVTRZbVF3WmpNNU5HUTROemhqTURNNE9UTmpaR1JpTVdVNVlqbGhNekExTVRKaFpHRXlaRFV5TnpjelpUSm1OV001WXpCa01UVTBNak5pTWpOaE1tUXdaV1JrWkdVNVlUY3pZak0wWTJKbE1tTTNNRFJrTWpJMk1UWTBNekZoTkRBM1pEVXpNekl4WkRWaE5EbGpaR1JpTlRjMlkySTJPR05sWVRjd01tRTJObVptTm1abU5HUTRPR05rT1dabFpqTTBaamMxTVROaE56WmtaamhtTnpBNFptWmtNREJpWldJM1lqQXdObUk0WkRZME9UVXdOemxrWlRoaVpUQXpaR1kzTURVMU5qUm1OREJqTTJKallXRTFNV1UyTUdFM01EQmlPR016WW1abFl6RXdNREF3TURBd01EQXdNREF3TURJd05EaGhOalpsWVRkaE5URTVObUk0TW1Fell6VTRZbVJrWkdJMk1UQTBNV0l3WXpZNE16Z3dNREJrWkdZMFpUaGlaalEzTm1FNFpXSXpOV0UxWlRjeU1XUm1NbVpoTXpsak5qRmpORFl5WVRGa056VmxZMk5sTWpBME1tUmpOemcxSWl3aVpHVmpjbmx3ZEdsdmJrTnZibVJwZEdsdmJuTWlPaUpYTTNOcFdUSTVkV1JJU21oWk0xSkNXa2RTZVZwWVRucEphbTlwU1dsM2FXTXpVbWhpYlZKb1kyMVNSR0l5TlRCamJVWnFaRVpTTldOSFZXbFBhVWxwVEVOS2FtRkhSbkJpYVVrMlNXMVdNR0ZIVm5sYVdGWjBTV2wzYVdKWFZqQmhSemxyU1dwdmFVbHBkMmxqUjBaNVdWY3hiR1JIVm5samVVazJWM2xKTm1SWVRteGphMFpyV2toS2JHTXpUV2xZVTNkcFkyMVdNR1JZU25WV2JVWnpaRmRXVlZwWVRqQkphbkEzU1cxT2RtSllRbWhqYlVZd1lqTkphVTlwU1RsSmFYZHBaRzFHYzJSWFZXbFBhVWwzWlVSTmVFMXRWa0pQUkZWNVRucEpNbEpVVGtKUFYxa3lUWHBPUWsxRVRUTk9NazEzV2xkRk5FOUVTWGRQUkZwclRtcFpNazVxV1dsbVdEQnpaWGxLZG1OSFZubFpXRkoyWTJsSk5rbHRSblZhUTBvNVRFaHphVmt5T1hWa1NFcG9XVE5TUWxwSFVubGFXRTU2U1dwdmFVbHBkMmxqTTFKb1ltMVNhR050VWtSaU1qVXdZMjFHYW1SR1VqVmpSMVZwVDJsS1ZGTldaRVpKYVhkcFdUSm9hR0ZYTkdsUGFVcHNaRWRvYkdOdFZqRmlVMGx6U1cweGJHUkhhSFphUTBrMlNXbEpjMGx1UW1oamJVWjBXbGhTYkdOdVRXbFBiSE5wVDI1S2JHTXlPVEZqYlU1c1kzbEtaRXhEU25sYVdGSXhZMjAxVjFsWGVERmFWbEpzWXpOUmFVOXVjMmxaTWpsMFkwZEdlVmxZVW5aamFVazJTVzFPZG1KdVVtaGhWelY2U1dsM2FXUnRSbk5rVjFWcFQybEthbHBZU21oaVYyeHFUMms0ZGt0cU9YUmlNbEpzWWtReGNtRnVjSE5PYldneVdtNUthV1I2V21wT1dFWnJaVzVrY0U5WFZucGxTRm93VFZoWk1XSllVakJPTWpsclRqSm9hVTFxYXpCT2VsbDVUa2N4ZFU1SVZYZGpiVEY0VFZoS2IwOVhSblZoYlU1MVpVaG5hV1pZTUhObGVVcDJZMGRXZVZsWVVuWmphVWsyU1cxR2RWcERTamxNU0hOcFdUSTVkV1JJU21oWk0xSkNXa2RTZVZwWVRucEphbTlwU1dsM2FXTXpVbWhpYlZKb1kyMVNSR0l5TlRCamJVWnFaRVpTTldOSFZXbFBhVXBVVTFaa1JrbHBkMmxaTW1ob1lWYzBhVTlwU214a1IyaHNZMjFXTVdKVFNYTkpiVEZzWkVkb2RscERTVFpKYVVselNXNUNhR050Um5SYVdGSnNZMjVOYVU5c2MybFBia3BzWXpJNU1XTnRUbXhqZVVwa1RFTktlVnBZVWpGamJUVlhXVmQ0TVZwV1VteGpNMUZwVDI1emFWa3lPWFJqUjBaNVdWaFNkbU5wU1RaSmJVNTJZbTVTYUdGWE5YcEphWGRwWkcxR2MyUlhWV2xQYVVwcVdsaEthR0pYYkdwUGFUaDJTMm81ZEdJeVVteGlSREZ5WVc1d2MwNXRhREphYmtwcFpIcGFhazV0Um10T00yeHJZbXBDYjJGVVVqSmtSMFowWlVSS01rNXFTWGRoUjFKdVpGUmFjMkpJUlRCUFYyZDVUMGhLYlZwRVdtcGpla0Y1V25wT2FtSlhORFZsYlVWcFpsZ3djMlY1U25aalIxWjVXVmhTZG1OcFNUWkpiVVoxV2tOS09VeEljMmxaTWpsMVpFaEthRmt6VWtKYVIxSjVXbGhPZWtscWIybEphWGRwWXpOU2FHSnRVbWhqYlZKRVlqSTFNR050Um1wa1JsSTFZMGRWYVU5cFNsUlRWbVJHU1dsM2FWa3lhR2hoVnpScFQybEtiR1JIYUd4amJWWXhZbE5KYzBsdE1XeGtSMmgyV2tOSk5rbHBTWE5KYmtKb1kyMUdkRnBZVW14amJrMXBUMnh6YVU5dVNteGpNamt4WTIxT2JHTjVTbVJNUTBwNVdsaFNNV050TlZkWlYzZ3hXbFpTYkdNelVXbFBibk5wV1RJNWRHTkhSbmxaV0ZKMlkybEpOa2x0VG5aaWJsSm9ZVmMxZWtscGQybGtiVVp6WkZkVmFVOXBTbXBhV0Vwb1lsZHNhazlwT0haTGFqbDBZakpTYkdKRU1YSmhibkJ6VG0xb01scHVTbWxrZWxwcVRucFplbVJYU210aFJ6a3paVzFHZGsxSE1EQmxXRUUwVGtkT05HVnRTbTFpYlhodlRrZG9hMkZVVm1oaVNFWjJUa2hzZVZwWFNuUlpla0o0WTBkd2EyRlVWV2xtV0RGa0lpd2laVzVqY25sd2RHVmtJam9pUVVSWWNXYzNXbGRLVkVwNVNYUllaakZpTTJ0T01YcFliVFJCTVZoQlJVdzRXRXRUZVRWdFdYRnRaMlJ1UzI5RVprTmlWM2RoVFhkNWQwWlRlVWRtTmxaVlZGaHJlWEZ6ZW1sNFVrSkhMV3d6T0d4cFRWVmZOREp3WldJME0yWjBZa2RTYjJOblRXRk1NblZMTWpadFVYSXpNVlJDY0dSWlFWbDRSbGxWVnpVaWZRaWNyZWF0ZWRBdHgYMjAyMy0wNi0xMVQxMToyNDoyMy4wMjlaaXVwZGF0ZWRBdHgYMjAyMy0wNi0xMVQxMToyNDoyMy4wMjlaamFwcFZlcnNpb25lMC4yLjBqZm9sZGVyVHlwZQFwY29udGVudEZvbGRlcklkc4FkdGVtcGZoZWFkZXKjZW1vZGVsWCjOAQIBhQESIBzfRtp3sMC9cDyAKBAj8zq/N2Xd5IJPzEEoVKyvyJM1ZnVuaXF1ZUwrbXEamTAna5uAMqJrY29udHJvbGxlcnOBeDtkaWQ6cGtoOmVpcDE1NToxOjB4MzEyZUE4NTI3MjZFM0E5ZjYzM0EwMzc3YzBlYTg4MjA4NmQ2NjY2Ng==", - }, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - buf, _ := base64.StdEncoding.DecodeString(tt.args.base64Encoded) - BuildPayloadFromReader(bytes.NewBuffer(buf)) - }) - } -} - -func TestConvertFrom(t *testing.T) { - type args struct { - base64Encoded string - } - tests := []struct { - name string - args args - wantCommit Commit - wantErr bool - }{ - { - name: "common", - args: args{ - base64Encoded: "omdwYXlsb2FkWCQBcRIgGtqDmUTOFzN1JfGKAS9bP1KGrprc6FzbjWjnGQv9yjlqc2lnbmF0dXJlc4GiaXByb3RlY3RlZFjMeyJhbGciOiJFZERTQSIsImNhcCI6ImlwZnM6Ly9iYWZ5cmVpZm5qdno3NDZ1azJrcWhpdHpqN2I1b3hhNmRjcDR3N2J1ZzJhbnhqbHNlYXhiM2R0bG9qeSIsImtpZCI6ImRpZDprZXk6ejZNa3UxOUdnY2gxTlliUmlOREZQVGFwcmQ0aUZKVlVncThTTnpNNnNSTEZESk45I3o2TWt1MTlHZ2NoMU5ZYlJpTkRGUFRhcHJkNGlGSlZVZ3E4U056TTZzUkxGREpOOSJ9aXNpZ25hdHVyZVhAoy7KX9UhdAIpYq2cvN8Kjv+Ka3ps6GzjYHt6afsu8qYYI7pS4k9/Ln013MBMnUTe7eM0/+YuAKnnOmsO8a5ECw==", - }, - wantCommit: Commit{ - Link: cid.MustParse("bafyreia23kbzsrgoc4zxkjprrias6wz7kkdk5gw45bonxdli44mqx7okhe"), - Payload: cid.MustParse("bafyreia23kbzsrgoc4zxkjprrias6wz7kkdk5gw45bonxdli44mqx7okhe"), - Signatures: []Signature{ - { - Header: nil, - Protected: []byte(`{"alg":"EdDSA","cap":"ipfs://bafyreifnjvz746uk2kqhitzj7b5oxa6dcp4w7bug2anxjlseaxb3dtlojy","kid":"did:key:z6Mku19Ggch1NYbRiNDFPTaprd4iFJVUgq8SNzM6sRLFDJN9#z6Mku19Ggch1NYbRiNDFPTaprd4iFJVUgq8SNzM6sRLFDJN9"}`), - Signature: hexutil.MustDecode("0xa32eca5fd52174022962ad9cbcdf0a8eff8a6b7a6ce86ce3607b7a69fb2ef2a61823ba52e24f7f2e7d35dcc04c9d44deede334ffe62e00a9e73a6b0ef1ae440b"), - }, - }, - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - buf, _ := base64.StdEncoding.DecodeString(tt.args.base64Encoded) - dagJws, _ := BuildDagJWSFromReader(bytes.NewBuffer(buf)) - gotCommit, err := ConvertFrom(dagJws) - if (err != nil) != tt.wantErr { - t.Errorf("ConvertFrom() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(gotCommit, tt.wantCommit) { - t.Errorf("ConvertFrom() = %v\nwant %v", gotCommit, tt.wantCommit) - } - }) - } -} diff --git a/ceramic/stream.go b/ceramic/stream.go index a21cf18..4b38572 100644 --- a/ceramic/stream.go +++ b/ceramic/stream.go @@ -1,13 +1,9 @@ package ceramic import ( - "context" "crypto/sha256" "encoding/hex" "encoding/json" - "fmt" - "net/http" - "os" "github.com/ipfs/go-cid" ) @@ -74,19 +70,3 @@ func (state StreamState) ContentHash() (sum [32]byte, err error) { hex.EncodeToString(sum[0:]) return } - -func GetStreamId(ctx context.Context, streamId StreamId) (stream Stream, err error) { - url := fmt.Sprintf("%s/api/v0/streams/%s", os.Getenv("CERAMIC_URL"), streamId) - var req *http.Request - var resp *http.Response - if req, err = http.NewRequestWithContext(ctx, http.MethodGet, url, nil); err != nil { - return - } - if resp, err = http.DefaultClient.Do(req); err != nil { - return - } - if err = json.NewDecoder(resp.Body).Decode(&stream); err != nil { - return - } - return -} diff --git a/ceramic/streamid.go b/ceramic/streamid.go index aba40f2..e25c8db 100644 --- a/ceramic/streamid.go +++ b/ceramic/streamid.go @@ -75,7 +75,7 @@ func (id StreamId) With(str string) StreamId { } func (id StreamId) GetStream(ctx context.Context) (stream Stream, err error) { - return GetStreamId(ctx, id) + return HttpApi.GetStreamId(HttpApi{}, ctx, id) } func NewStreamId(t StreamType, cidStr ...string) (id StreamId, err error) { @@ -87,13 +87,18 @@ func NewStreamId(t StreamType, cidStr ...string) (id StreamId, err error) { return } +func MustParseStreamID(str string) StreamId { + id, err := ParseStreamID(str) + if err != nil { + panic(err) + } + return id +} + func ParseStreamID(str string) (id StreamId, err error) { var ( - buf []byte - encoding multibase.Encoding - streamCodec uint64 - streamType uint64 - idx int + buf []byte + encoding multibase.Encoding ) if encoding, buf, err = multibase.Decode(str); err != nil { @@ -103,34 +108,43 @@ func ParseStreamID(str string) (id StreamId, err error) { err = fmt.Errorf("unexpected encoding id %c with input %s", encoding, str) return } + return CastStreamID(buf) +} + +func CastStreamID(data []byte) (id StreamId, err error) { + var ( + streamCodec uint64 + streamType uint64 + idx int + ) // check - if streamCodec, idx = binary.Uvarint(buf); idx <= 0 { - err = fmt.Errorf("unable to unpack stream codec %v", buf) + if streamCodec, idx = binary.Uvarint(data); idx <= 0 { + err = fmt.Errorf("unable to unpack stream codec %v", data) return } if multicodec.Code(streamCodec) != multicodec.Streamid { - err = fmt.Errorf("unexpected multicodec %x != 0xce", buf[0]) + err = fmt.Errorf("unexpected multicodec %x != 0xce", data[0]) return } - buf = buf[idx:] + data = data[idx:] // check - if streamType, idx = binary.Uvarint(buf); idx <= 0 { - err = fmt.Errorf("unable to unpack stream type %v", buf) + if streamType, idx = binary.Uvarint(data); idx <= 0 { + err = fmt.Errorf("unable to unpack stream type %v", data) return } id.Type = StreamType(streamType) - buf = buf[idx:] + data = data[idx:] var nr int - if nr, id.Cid, err = cid.CidFromBytes(buf); err != nil { + if nr, id.Cid, err = cid.CidFromBytes(data); err != nil { return } - buf = buf[nr:] - if len(buf) != 0 { - if len(buf) == 1 && buf[0] == 0 { + data = data[nr:] + if len(data) != 0 { + if len(data) == 1 && data[0] == 0 { id.GenesisLog = true - } else if _, id.Log, err = cid.CidFromBytes(buf); err != nil { + } else if _, id.Log, err = cid.CidFromBytes(data); err != nil { return } } @@ -139,7 +153,7 @@ func ParseStreamID(str string) (id StreamId, err error) { var _ json.Marshaler = (*StreamId)(nil) -func (id *StreamId) MarshalJSON() ([]byte, error) { +func (id StreamId) MarshalJSON() ([]byte, error) { return json.Marshal(id.String()) } From 158b33cbfffd036577ce227205602c301d6302e3 Mon Sep 17 00:00:00 2001 From: FDKevin Date: Fri, 1 Sep 2023 18:21:34 +0800 Subject: [PATCH 18/18] feat(wnfs): commit log rule --- ceramic/commit_utils.go | 3 +- ceramic/commits.go | 81 +++++++++++++++++++++++++++------------- ceramic/ipfs.go | 83 ++++++++++++++++++++++++++++------------- ceramic/ipfs_pubsub.go | 6 +-- ceramic/rules.go | 29 ++++++++++++++ ceramic/stream.go | 23 ++++++++---- go.mod | 1 + go.sum | 3 ++ internal/wnfs/policy.go | 65 ++++++++++++++++++++++++++++++++ internal/wnfs/proof.go | 13 +++++-- 10 files changed, 243 insertions(+), 64 deletions(-) create mode 100644 ceramic/rules.go diff --git a/ceramic/commit_utils.go b/ceramic/commit_utils.go index 65507e4..d04c502 100644 --- a/ceramic/commit_utils.go +++ b/ceramic/commit_utils.go @@ -26,5 +26,6 @@ func DecodeDagCborNodeDataFromReader(reader io.Reader) (nd datamodel.Node, err e } func ContainField(nd datamodel.Node, key string) bool { - return lo.T2(nd.LookupByString(key)).A.IsNull() + v, err := nd.LookupByString(key) + return err == nil && v != nil } diff --git a/ceramic/commits.go b/ceramic/commits.go index 4baadd0..bb61e0b 100644 --- a/ceramic/commits.go +++ b/ceramic/commits.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "io" + "strings" "github.com/ceramicnetwork/go-dag-jose/dagjose" "github.com/ipfs/boxo/coreiface/path" @@ -13,8 +14,13 @@ import ( "github.com/ipld/go-ipld-prime/datamodel" cidlink "github.com/ipld/go-ipld-prime/linking/cid" "github.com/samber/lo" + "github.com/tidwall/sjson" ) +type Commit interface { + NodeDataDecoder +} + type NodeDataDecoder interface { DecodeFromNodeData(nd datamodel.Node) (err error) } @@ -28,7 +34,7 @@ type CommitWithPayload interface { } type CommitPayload interface { - NodeDataDecoder + Commit DelectType(nd datamodel.Node) bool ApplyToStream(state *StreamState) (err error) } @@ -69,8 +75,18 @@ type GenesisCommitPayload struct { Data json.RawMessage } -func (commit *GenesisCommitPayload) ApplyToStream(state *StreamState) (err error) { - state.Content = commit.Data +func (payload *GenesisCommitPayload) GetData() []byte { + return payload.Data +} + +func (payload *GenesisCommitPayload) ApplyToStream(state *StreamState) (err error) { + state.Content = payload.Data + if state.Metadata, err = json.Marshal(map[string]any{ + "controllers": payload.Header.Controllers, + "model": payload.Header.Model, + }); err != nil { + return + } return } @@ -78,7 +94,7 @@ func (*GenesisCommitPayload) DelectType(nd datamodel.Node) bool { return ContainField(nd, "header") && !ContainField(nd, "id") } -func (commit *GenesisCommitPayload) DecodeFromNodeData(nd datamodel.Node) (err error) { +func (payload *GenesisCommitPayload) DecodeFromNodeData(nd datamodel.Node) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("recovered in %s", r) @@ -89,9 +105,9 @@ func (commit *GenesisCommitPayload) DecodeFromNodeData(nd datamodel.Node) (err e if err = dagjsonEncodeOption.Encode(lo.Must(nd.LookupByString("data")), &buf); err != nil { return } - commit.Data = buf.Bytes() + payload.Data = buf.Bytes() if headerNode, e := nd.LookupByString("header"); e == nil && !headerNode.IsNull() { - if err = commit.Header.DecodeFromNodeData(headerNode); err != nil { + if err = payload.Header.DecodeFromNodeData(headerNode); err != nil { return } } @@ -104,24 +120,26 @@ type DataCommitPayload struct { ID cid.Cid // link to init event Prev cid.Cid Header *CommitHeader - Data json.RawMessage + Pathes []Patch } -func (commit *DataCommitPayload) DecodeFromNodeData(nd datamodel.Node) (err error) { +func (payload *DataCommitPayload) DecodeFromNodeData(nd datamodel.Node) (err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("recovered in %s", r) return } }() - commit.ID = MustParseLink(nd, "id") - commit.Prev = MustParseLink(nd, "prev") + payload.ID = MustParseLink(nd, "id") + payload.Prev = MustParseLink(nd, "prev") var buf bytes.Buffer if err = dagjsonEncodeOption.Encode(lo.Must(nd.LookupByString("data")), &buf); err != nil { return } - commit.Data = buf.Bytes() + if err = json.Unmarshal(buf.Bytes(), &payload.Pathes); err != nil { + return + } return } @@ -129,8 +147,26 @@ func (DataCommitPayload) DelectType(nd datamodel.Node) bool { return ContainField(nd, "prev") && !ContainField(nd, "proof") } +type Patch struct { + Operation string `json:"op"` + Path string `json:"path"` + Value any `json:"value"` +} + func (commit *DataCommitPayload) ApplyToStream(state *StreamState) (err error) { - //TODO + for _, v := range commit.Pathes { + path := strings.ReplaceAll(v.Path[1:], "/", ".") + switch v.Operation { + case "add", "replace": + if state.Content, err = sjson.SetBytes(state.Content, path, v.Value); err != nil { + return + } + case "remove": + if state.Content, err = sjson.DeleteBytes(state.Content, path); err != nil { + return + } + } + } return } @@ -168,33 +204,28 @@ func (commit *AnchorCommit) DecodeFromNodeData(nd datamodel.Node) (err error) { var _ NodeDataDecoder = (*SignedCommit)(nil) type SignedCommit struct { - linkedCommit CommitPayload - Link cid.Cid - Payload cid.Cid - Signatures []Signature -} - -func (commit *SignedCommit) GetPayload() CommitPayload { - return commit.linkedCommit + Link cid.Cid + Payload cid.Cid + Signatures []Signature } -func (commit *SignedCommit) LoadPayload(ctx context.Context, impl IpfsImpl) (err error) { +func (commit *SignedCommit) LoadPayload(ctx context.Context, impl IpfsImpl) (payload CommitPayload, err error) { var ( blkReader io.Reader nd datamodel.Node ) - if blkReader, err = impl.node.Block().Get(ctx, path.IpfsPath(commit.Payload)); err != nil { + if blkReader, err = impl.blockAPI.Get(ctx, path.IpfsPath(commit.Payload)); err != nil { return } if nd, err = DecodeDagCborNodeDataFromReader(blkReader); err != nil { return } if ContainField(nd, "prev") { - commit.linkedCommit = &DataCommitPayload{} + payload = &DataCommitPayload{} } else { - commit.linkedCommit = &GenesisCommitPayload{} + payload = &GenesisCommitPayload{} } - if err = commit.DecodeFromNodeData(nd); err != nil { + if err = payload.DecodeFromNodeData(nd); err != nil { return } return diff --git a/ceramic/ipfs.go b/ceramic/ipfs.go index 63813d8..128d68e 100644 --- a/ceramic/ipfs.go +++ b/ceramic/ipfs.go @@ -6,6 +6,7 @@ import ( "fmt" "io" + iface "github.com/ipfs/boxo/coreiface" "github.com/ipfs/boxo/coreiface/path" "github.com/ipfs/go-cid" "github.com/ipfs/kubo/client/rpc" @@ -13,56 +14,89 @@ import ( ) func NewIpfsImpl(node *rpc.HttpApi) IpfsImpl { - return IpfsImpl{node: node} + return IpfsImpl{ + blockAPI: node.Block(), + pubSubAPI: node.PubSub(), + } } type IpfsImpl struct { - node *rpc.HttpApi + network string + blockAPI iface.BlockAPI + pubSubAPI iface.PubSubAPI } -func (impl IpfsImpl) LoadStreamState(ctx context.Context, tip cid.Cid) (state StreamState, err error) { - var commits []NodeDataDecoder - if commits, err = impl.LoadCommits(ctx, tip); err != nil { +func (impl IpfsImpl) LoadStreamSate(ctx context.Context, streamId StreamId, rules ...CommitVerifier) (state StreamState, err error) { + if streamId.Log.ByteLen() == 0 { + if streamId.Log, err = impl.QueryStream(ctx, streamId); err != nil { + return + } + } + if state, err = impl.LoadStreamCommits(ctx, streamId.Log, rules...); err != nil { return } - for _, commit := range commits { - if stateBuilder, ok := commit.(CommitPayload); ok { - if err = stateBuilder.ApplyToStream(&state); err != nil { + state.Type = streamId.Type + return +} + +func (impl IpfsImpl) LoadStreamCommits(ctx context.Context, tip cid.Cid, rules ...CommitVerifier) (state StreamState, err error) { + var commit Commit + if commit, err = impl.LoadCommit(ctx, tip); err != nil { + return + } + commitLog := StreamLog{Cid: tip.String()} + var payload CommitPayload + if signedCommit, ok := commit.(*SignedCommit); ok { + if payload, err = signedCommit.LoadPayload(ctx, impl); err != nil { + return + } + switch t := payload.(type) { + case *DataCommitPayload: + commitLog.Type = CommitTypeSigned + if err = ValidatePatches(t.Pathes, rules); err != nil { + return + } + if state, err = impl.LoadStreamCommits(ctx, t.Prev, rules...); err != nil { return } + case *GenesisCommitPayload: + commitLog.Type = CommitTypeGenesis + if err = ValidateData(t.Data, rules); err != nil { + return + } + } + payload.ApplyToStream(&state) + state.Log = append(state.Log, commitLog) + } else if anchorCommit, ok := commit.(*AnchorCommit); ok { + if state, err = impl.LoadStreamCommits(ctx, anchorCommit.Prev, rules...); err != nil { + return } + commitLog.Type = CommitTypeAnchor + state.Log = append(state.Log, commitLog) + } else { + err = fmt.Errorf("unreconized commit event") } return } -func (impl IpfsImpl) LoadCommits(ctx context.Context, c cid.Cid) (commits []NodeDataDecoder, err error) { - - return -} - -func (impl IpfsImpl) LoadLog(ctx context.Context, c cid.Cid) (commit NodeDataDecoder, err error) { +func (impl IpfsImpl) LoadCommit(ctx context.Context, tip cid.Cid) (commit Commit, err error) { var ( blkReader io.Reader nd datamodel.Node ) - if blkReader, err = impl.node.Block().Get(ctx, path.IpfsPath(c)); err != nil { + if blkReader, err = impl.blockAPI.Get(ctx, path.IpfsPath(tip)); err != nil { return } - if c.Prefix().Codec == cid.DagJOSE { + if tip.Prefix().Codec == cid.DagJOSE { commit = &SignedCommit{} if nd, err = DecodeDagJWSNodeDataFromReader(blkReader); err != nil { return } - var buf bytes.Buffer - if err = dagjsonEncodeOption.Encode(nd, &buf); err != nil { - return - } - fmt.Println(c.Prefix().Codec, buf.String()) err = commit.DecodeFromNodeData(nd) - impl.LoadLog(ctx, commit.(*SignedCommit).Payload) return } + commit = &AnchorCommit{} if nd, err = DecodeDagCborNodeDataFromReader(blkReader); err != nil { return } @@ -70,7 +104,6 @@ func (impl IpfsImpl) LoadLog(ctx context.Context, c cid.Cid) (commit NodeDataDec if err = dagjsonEncodeOption.Encode(nd, &buf); err != nil { return } - fmt.Println(c.Prefix().Codec, buf.String()) - - return nil, nil + err = commit.DecodeFromNodeData(nd) + return } diff --git a/ceramic/ipfs_pubsub.go b/ceramic/ipfs_pubsub.go index 66639f5..effc21d 100644 --- a/ceramic/ipfs_pubsub.go +++ b/ceramic/ipfs_pubsub.go @@ -49,7 +49,7 @@ type PubSubKeepaliveMessage struct { IPFSVersion string `json:"ipfsVer"` } -func QueryStream(ctx context.Context, node *rpc.HttpApi, network string, streamId StreamId) (tip cid.Cid, err error) { +func (impl IpfsImpl) QueryStream(ctx context.Context, streamId StreamId) (tip cid.Cid, err error) { var buf bytes.Buffer if err = json.NewEncoder(&buf).Encode(map[string]any{ "typ": MessageTypeQuery, @@ -69,11 +69,11 @@ func QueryStream(ctx context.Context, node *rpc.HttpApi, network string, streamI return } fmt.Println(buf.String()) - if err = node.PubSub().Publish(ctx, network, buf.Bytes()); err != nil { + if err = impl.pubSubAPI.Publish(ctx, impl.network, buf.Bytes()); err != nil { return } var sub iface.PubSubSubscription - if sub, err = node.PubSub().Subscribe(ctx, network); err != nil { + if sub, err = impl.pubSubAPI.Subscribe(ctx, impl.network); err != nil { return } defer sub.Close() diff --git a/ceramic/rules.go b/ceramic/rules.go new file mode 100644 index 0000000..9193f49 --- /dev/null +++ b/ceramic/rules.go @@ -0,0 +1,29 @@ +package ceramic + +import "encoding/json" + +type CommitVerifier interface { + ProtectedFields() []string + ValidateData(data json.RawMessage) (err error) + ValidatePatches(patche Patch) (err error) +} + +func ValidateData(data json.RawMessage, rules []CommitVerifier) (err error) { + for _, rule := range rules { + if err = rule.ValidateData(data); err != nil { + return + } + } + return +} + +func ValidatePatches(patches []Patch, rules []CommitVerifier) (err error) { + for _, rule := range rules { + for _, patch := range patches { + if err = rule.ValidatePatches(patch); err != nil { + return + } + } + } + return +} diff --git a/ceramic/stream.go b/ceramic/stream.go index 4b38572..f6f7e3b 100644 --- a/ceramic/stream.go +++ b/ceramic/stream.go @@ -4,6 +4,7 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" + "fmt" "github.com/ipfs/go-cid" ) @@ -28,7 +29,7 @@ type StreamLog struct { Cid string `json:"cid"` Type CommitType `json:"type"` ExpirationTime *uint64 `json:"expirationTime,omitempty"` - Timestamp uint64 `json:"timestamp"` + Timestamp uint64 `json:"timestamp,omitempty"` } type AnchorProof struct { @@ -38,15 +39,23 @@ type AnchorProof struct { ChainId string `json:"chainId"` } -func (state StreamState) StreamId() StreamId { - return StreamId{ - Type: state.Type, - Cid: cid.MustParse(state.Log[0].Cid), +func (state StreamState) StreamId() (id StreamId, err error) { + id.Type = state.Type + if len(state.Log) == 0 { + err = fmt.Errorf("missing gensis stream log") + return } + if id.Cid, err = cid.Parse(state.Log[0].Cid); err != nil { + return + } + return } -func (state StreamState) CommitIds() (commitIds []StreamId) { - streamId := state.StreamId() +func (state StreamState) CommitIds() (commitIds []StreamId, err error) { + var streamId StreamId + if streamId, err = state.StreamId(); err != nil { + return + } commitIds = append(commitIds, streamId.Genesis()) for _, v := range state.Log[1:] { commitIds = append(commitIds, streamId.With(v.Cid)) diff --git a/go.mod b/go.mod index 809b2ac..321c612 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/samber/lo v1.38.1 github.com/spf13/cobra v1.7.0 github.com/tidwall/gjson v1.16.0 + github.com/tidwall/sjson v1.2.5 go.etcd.io/bbolt v1.3.7 golang.org/x/sync v0.3.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 5313e4d..a0ab88e 100644 --- a/go.sum +++ b/go.sum @@ -424,6 +424,7 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg= github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= @@ -431,6 +432,8 @@ github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JT github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= diff --git a/internal/wnfs/policy.go b/internal/wnfs/policy.go index c1d9bd7..47439be 100644 --- a/internal/wnfs/policy.go +++ b/internal/wnfs/policy.go @@ -1,9 +1,74 @@ package wnfs import ( + "encoding/base64" "encoding/json" + "fmt" + + "github.com/dataverse-os/dapp-backend/ceramic" + "github.com/tidwall/gjson" ) +var _ ceramic.CommitVerifier = (*IndexFileVerifier)(nil) + +type IndexFileVerifier struct{} + +func (*IndexFileVerifier) ProtectedFields() []string { + return []string{ + "contentId", "contentType", + } +} + +func (v *IndexFileVerifier) ValidateData(data json.RawMessage) (err error) { + obj := gjson.ParseBytes(data) + if err = v.validateStreamId(obj.Get("contentId").String()); err != nil { + return + } + // check acl + if err = v.validateACL(obj.Get("accessControl").String()); err != nil { + return + } + return +} + +func (v *IndexFileVerifier) ValidatePatches(patch ceramic.Patch) (err error) { + if patch.Path == "/accessControl" { + if aclStr, ok := patch.Value.(string); ok { + if err = v.validateACL(aclStr); err != nil { + return + } + } else { + err = fmt.Errorf("cannot parse accessControl field value: %s as string", patch.Value) + } + } + return +} + +func (*IndexFileVerifier) validateStreamId(streamIdStr string) (err error) { + var streamId ceramic.StreamId + if streamId, err = ceramic.ParseStreamID(streamIdStr); err != nil { + return + } + _ = streamId + // TODO check streamId not fs stream + // TODO check streamId is Dapp stream + // TODO check streamId can get from ceramic + return +} + +func (*IndexFileVerifier) validateACL(data string) (err error) { + var acl []byte + if acl, err = base64.RawStdEncoding.DecodeString(data); err != nil { + return + } + obj := gjson.ParseBytes(acl) + obj.Get("encryptionProvider.decryptionConditions").ForEach(func(_, value gjson.Result) bool { + // TODO: check model is dapp + return true + }) + return +} + func CheckPolicy(streamContents []json.RawMessage) (err error) { return } diff --git a/internal/wnfs/proof.go b/internal/wnfs/proof.go index 4e0724a..7b1a8cf 100644 --- a/internal/wnfs/proof.go +++ b/internal/wnfs/proof.go @@ -108,17 +108,24 @@ type CommitProof struct { func StoreAndVerifyContentHash(ctx context.Context, streamState ceramic.StreamState) (err error) { var ( - streamId = streamState.StreamId() + streamId ceramic.StreamId commit ceramic.Stream commitProofs = make([]CommitProof, len(streamState.Log)) commitProofsInDB []CommitProof commitProofsInDBMap = make(map[ceramic.StreamId]CommitProof) - commitIds = streamState.CommitIds() + commitIds []ceramic.StreamId ) + if streamId, err = streamState.StreamId(); err != nil { + return + } + if commitIds, err = streamState.CommitIds(); err != nil { + return + } + defer func() { if err != nil { - fmt.Printf("wnfs check %s with %d commits\n", streamState.StreamId(), len(commitProofs)) + fmt.Printf("wnfs check %s with %d commits\n", streamId, len(commitProofs)) } }()