diff --git a/.circleci/config.yml b/.circleci/config.yml index b025ff5c..1316e8aa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -142,7 +142,7 @@ jobs: default: golang golangci-lint-version: type: string - default: 1.17.1 + default: 1.21.0 concurrency: type: string default: '2' diff --git a/datatransfer/cbor-gen/main.go b/datatransfer/cbor-gen/main.go deleted file mode 100644 index e10058bf..00000000 --- a/datatransfer/cbor-gen/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "fmt" - "os" - - graphsyncimpl "github.com/filecoin-project/go-fil-components/datatransfer/impl/graphsync" - "github.com/filecoin-project/go-fil-components/datatransfer/message" -) - -// main func has ONE JOB -func main() { - fmt.Print("Generating Cbor Marshal/Unmarshal...") - - if err := message.RunCborGen(); err != nil { - fmt.Println("Failed: ") - fmt.Println(err) - os.Exit(1) - } - if err := graphsyncimpl.RunCborGen(); err != nil { - fmt.Println("Failed: ") - fmt.Println(err) - os.Exit(1) - } - fmt.Println("Done.") -} diff --git a/datatransfer/impl/graphsync/graphsync_impl.go b/datatransfer/impl/graphsync/graphsync_impl.go index e9d55e2c..8feff6b6 100644 --- a/datatransfer/impl/graphsync/graphsync_impl.go +++ b/datatransfer/impl/graphsync/graphsync_impl.go @@ -26,6 +26,8 @@ const ( ExtensionDataTransfer = graphsync.ExtensionName("fil/data-transfer") ) +//go:generate cbor-gen-for ExtensionDataTransferData + // ExtensionDataTransferData is the extension data for // the graphsync extension. type ExtensionDataTransferData struct { diff --git a/datatransfer/impl/graphsync/cbor_gen.go b/datatransfer/impl/graphsync/graphsync_impl_cbor_gen.go similarity index 81% rename from datatransfer/impl/graphsync/cbor_gen.go rename to datatransfer/impl/graphsync/graphsync_impl_cbor_gen.go index b22f1484..f61acf15 100644 --- a/datatransfer/impl/graphsync/cbor_gen.go +++ b/datatransfer/impl/graphsync/graphsync_impl_cbor_gen.go @@ -9,7 +9,7 @@ import ( xerrors "golang.org/x/xerrors" ) -/* This file was generated by github.com/whyrusleeping/cbor-gen */ +// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. var _ = xerrors.Errorf @@ -22,12 +22,12 @@ func (t *ExtensionDataTransferData) MarshalCBOR(w io.Writer) error { return err } - // t.t.TransferID (uint64) (uint64) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.TransferID))); err != nil { // nolint: unconvert + // t.TransferID (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.TransferID))); err != nil { return err } - // t.t.Initiator (peer.ID) (string) + // t.Initiator (peer.ID) (string) if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.Initiator)))); err != nil { return err } @@ -35,7 +35,7 @@ func (t *ExtensionDataTransferData) MarshalCBOR(w io.Writer) error { return err } - // t.t.IsPull (bool) (bool) + // t.IsPull (bool) (bool) if err := cbg.WriteBool(w, t.IsPull); err != nil { return err } @@ -57,7 +57,7 @@ func (t *ExtensionDataTransferData) UnmarshalCBOR(r io.Reader) error { return fmt.Errorf("cbor input had wrong number of fields") } - // t.t.TransferID (uint64) (uint64) + // t.TransferID (uint64) (uint64) maj, extra, err = cbg.CborReadHeader(br) if err != nil { @@ -66,8 +66,8 @@ func (t *ExtensionDataTransferData) UnmarshalCBOR(r io.Reader) error { if maj != cbg.MajUnsignedInt { return fmt.Errorf("wrong type for uint64 field") } - t.TransferID = uint64(extra) // nolint: unconvert - // t.t.Initiator (peer.ID) (string) + t.TransferID = uint64(extra) + // t.Initiator (peer.ID) (string) { sval, err := cbg.ReadString(br) @@ -77,7 +77,7 @@ func (t *ExtensionDataTransferData) UnmarshalCBOR(r io.Reader) error { t.Initiator = peer.ID(sval) } - // t.t.IsPull (bool) (bool) + // t.IsPull (bool) (bool) maj, extra, err = cbg.CborReadHeader(br) if err != nil { diff --git a/datatransfer/impl/graphsync/run_cbor_gen.go b/datatransfer/impl/graphsync/run_cbor_gen.go deleted file mode 100644 index 14d167ea..00000000 --- a/datatransfer/impl/graphsync/run_cbor_gen.go +++ /dev/null @@ -1,27 +0,0 @@ -package graphsyncimpl - -import ( - "fmt" - "os" - - cborgen "github.com/whyrusleeping/cbor-gen" -) - -func RunCborGen() error { - genName := "./impl/graphsync/cbor_gen.go" - reName := "./impl/graphsync/cbor_gen_old.go" - if err := os.Rename(genName, reName); err != nil { - return fmt.Errorf("could not rename %s to %s", genName, reName) - } - if err := cborgen.WriteTupleEncodersToFile( - genName, - "graphsyncimpl", - ExtensionDataTransferData{}, - ); err != nil { - return err - } - if err := os.Remove(reName); err != nil { - return err - } - return nil -} diff --git a/datatransfer/message/cbor_gen.go b/datatransfer/message/cbor_gen.go deleted file mode 100644 index 1c3a0cbd..00000000 --- a/datatransfer/message/cbor_gen.go +++ /dev/null @@ -1,403 +0,0 @@ -package message - -import ( - "fmt" - "io" - - cbg "github.com/whyrusleeping/cbor-gen" - xerrors "golang.org/x/xerrors" -) - -/* This file was generated by github.com/whyrusleeping/cbor-gen */ - -var _ = xerrors.Errorf - -func (t *transferMessage) MarshalCBOR(w io.Writer) error { - if t == nil { - _, err := w.Write(cbg.CborNull) - return err - } - if _, err := w.Write([]byte{131}); err != nil { - return err - } - - // t.t.IsRq (bool) (bool) - if err := cbg.WriteBool(w, t.IsRq); err != nil { - return err - } - - // t.t.Request (message.transferRequest) (struct) - if err := t.Request.MarshalCBOR(w); err != nil { - return err - } - - // t.t.Response (message.transferResponse) (struct) - if err := t.Response.MarshalCBOR(w); err != nil { - return err - } - return nil -} - -func (t *transferMessage) UnmarshalCBOR(r io.Reader) error { - br := cbg.GetPeeker(r) - - maj, extra, err := cbg.CborReadHeader(br) - if err != nil { - return err - } - if maj != cbg.MajArray { - return fmt.Errorf("cbor input should be of type array") - } - - if extra != 3 { - return fmt.Errorf("cbor input had wrong number of fields") - } - - // t.t.IsRq (bool) (bool) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if maj != cbg.MajOther { - return fmt.Errorf("booleans must be major type 7") - } - switch extra { - case 20: - t.IsRq = false - case 21: - t.IsRq = true - default: - return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) - } - // t.t.Request (message.transferRequest) (struct) - - { - - pb, err := br.PeekByte() - if err != nil { - return err - } - if pb == cbg.CborNull[0] { - var nbuf [1]byte - if _, err := br.Read(nbuf[:]); err != nil { - return err - } - } else { - t.Request = new(transferRequest) - if err := t.Request.UnmarshalCBOR(br); err != nil { - return err - } - } - - } - // t.t.Response (message.transferResponse) (struct) - - { - - pb, err := br.PeekByte() - if err != nil { - return err - } - if pb == cbg.CborNull[0] { - var nbuf [1]byte - if _, err := br.Read(nbuf[:]); err != nil { - return err - } - } else { - t.Response = new(transferResponse) - if err := t.Response.UnmarshalCBOR(br); err != nil { - return err - } - } - - } - return nil -} - -func (t *transferRequest) MarshalCBOR(w io.Writer) error { - if t == nil { - _, err := w.Write(cbg.CborNull) - return err - } - if _, err := w.Write([]byte{137}); err != nil { - return err - } - - // t.t.BCid (string) (string) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.BCid)))); err != nil { - return err - } - if _, err := w.Write([]byte(t.BCid)); err != nil { - return err - } - - // t.t.Canc (bool) (bool) - if err := cbg.WriteBool(w, t.Canc); err != nil { - return err - } - - // t.t.PID ([]uint8) (slice) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.PID)))); err != nil { - return err - } - if _, err := w.Write(t.PID); err != nil { - return err - } - - // t.t.Part (bool) (bool) - if err := cbg.WriteBool(w, t.Part); err != nil { - return err - } - - // t.t.Pull (bool) (bool) - if err := cbg.WriteBool(w, t.Pull); err != nil { - return err - } - - // t.t.Stor ([]uint8) (slice) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Stor)))); err != nil { - return err - } - if _, err := w.Write(t.Stor); err != nil { - return err - } - - // t.t.Vouch ([]uint8) (slice) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Vouch)))); err != nil { - return err - } - if _, err := w.Write(t.Vouch); err != nil { - return err - } - - // t.t.VTyp (string) (string) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.VTyp)))); err != nil { - return err - } - if _, err := w.Write([]byte(t.VTyp)); err != nil { - return err - } - - // t.t.XferID (uint64) (uint64) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.XferID))); err != nil { // nolint: unconvert - return err - } - return nil -} - -func (t *transferRequest) UnmarshalCBOR(r io.Reader) error { - br := cbg.GetPeeker(r) - - maj, extra, err := cbg.CborReadHeader(br) - if err != nil { - return err - } - if maj != cbg.MajArray { - return fmt.Errorf("cbor input should be of type array") - } - - if extra != 9 { - return fmt.Errorf("cbor input had wrong number of fields") - } - - // t.t.BCid (string) (string) - - { - sval, err := cbg.ReadString(br) - if err != nil { - return err - } - - t.BCid = string(sval) // nolint: unconvert - } - // t.t.Canc (bool) (bool) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if maj != cbg.MajOther { - return fmt.Errorf("booleans must be major type 7") - } - switch extra { - case 20: - t.Canc = false - case 21: - t.Canc = true - default: - return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) - } - // t.t.PID ([]uint8) (slice) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if extra > 8192 { - return fmt.Errorf("t.PID: array too large (%d)", extra) - } - - if maj != cbg.MajByteString { - return fmt.Errorf("expected byte array") - } - t.PID = make([]byte, extra) - if _, err := io.ReadFull(br, t.PID); err != nil { - return err - } - // t.t.Part (bool) (bool) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if maj != cbg.MajOther { - return fmt.Errorf("booleans must be major type 7") - } - switch extra { - case 20: - t.Part = false - case 21: - t.Part = true - default: - return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) - } - // t.t.Pull (bool) (bool) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if maj != cbg.MajOther { - return fmt.Errorf("booleans must be major type 7") - } - switch extra { - case 20: - t.Pull = false - case 21: - t.Pull = true - default: - return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) - } - // t.t.Stor ([]uint8) (slice) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if extra > 8192 { - return fmt.Errorf("t.Stor: array too large (%d)", extra) - } - - if maj != cbg.MajByteString { - return fmt.Errorf("expected byte array") - } - t.Stor = make([]byte, extra) - if _, err := io.ReadFull(br, t.Stor); err != nil { - return err - } - // t.t.Vouch ([]uint8) (slice) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if extra > 8192 { - return fmt.Errorf("t.Vouch: array too large (%d)", extra) - } - - if maj != cbg.MajByteString { - return fmt.Errorf("expected byte array") - } - t.Vouch = make([]byte, extra) - if _, err := io.ReadFull(br, t.Vouch); err != nil { - return err - } - // t.t.VTyp (string) (string) - - { - sval, err := cbg.ReadString(br) - if err != nil { - return err - } - - t.VTyp = string(sval) // nolint: unconvert - } - // t.t.XferID (uint64) (uint64) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if maj != cbg.MajUnsignedInt { - return fmt.Errorf("wrong type for uint64 field") - } - t.XferID = uint64(extra) // nolint: unconvert - return nil -} - -func (t *transferResponse) MarshalCBOR(w io.Writer) error { - if t == nil { - _, err := w.Write(cbg.CborNull) - return err - } - if _, err := w.Write([]byte{130}); err != nil { - return err - } - - // t.t.Acpt (bool) (bool) - if err := cbg.WriteBool(w, t.Acpt); err != nil { - return err - } - - // t.t.XferID (uint64) (uint64) - if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.XferID))); err != nil { // nolint: unconvert - return err - } - return nil -} - -func (t *transferResponse) UnmarshalCBOR(r io.Reader) error { - br := cbg.GetPeeker(r) - - maj, extra, err := cbg.CborReadHeader(br) - if err != nil { - return err - } - if maj != cbg.MajArray { - return fmt.Errorf("cbor input should be of type array") - } - - if extra != 2 { - return fmt.Errorf("cbor input had wrong number of fields") - } - - // t.t.Acpt (bool) (bool) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if maj != cbg.MajOther { - return fmt.Errorf("booleans must be major type 7") - } - switch extra { - case 20: - t.Acpt = false - case 21: - t.Acpt = true - default: - return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) - } - // t.t.XferID (uint64) (uint64) - - maj, extra, err = cbg.CborReadHeader(br) - if err != nil { - return err - } - if maj != cbg.MajUnsignedInt { - return fmt.Errorf("wrong type for uint64 field") - } - t.XferID = uint64(extra) // nolint: unconvert - return nil -} diff --git a/datatransfer/message/run_cbor_gen.go b/datatransfer/message/run_cbor_gen.go deleted file mode 100644 index cdbc94d6..00000000 --- a/datatransfer/message/run_cbor_gen.go +++ /dev/null @@ -1,29 +0,0 @@ -package message - -import ( - "fmt" - "os" - - cborgen "github.com/whyrusleeping/cbor-gen" -) - -func RunCborGen() error { - genName := "./message/cbor_gen.go" - reName := "./message/cbor_gen_old.go" - if err := os.Rename(genName, reName); err != nil { - return fmt.Errorf("could not rename %s to %s", genName, reName) - } - if err := cborgen.WriteTupleEncodersToFile( - genName, - "message", - transferMessage{}, - transferRequest{}, - transferResponse{}, - ); err != nil { - return err - } - if err := os.Remove(reName); err != nil { - return err - } - return nil -} diff --git a/datatransfer/message/transfer_message.go b/datatransfer/message/transfer_message.go index 0ab271b1..87c5638f 100644 --- a/datatransfer/message/transfer_message.go +++ b/datatransfer/message/transfer_message.go @@ -6,6 +6,7 @@ import ( "github.com/filecoin-project/go-fil-components/datatransfer" ) +//go:generate cbor-gen-for transferMessage type transferMessage struct { IsRq bool diff --git a/datatransfer/message/transfer_message_cbor_gen.go b/datatransfer/message/transfer_message_cbor_gen.go new file mode 100644 index 00000000..f53464e8 --- /dev/null +++ b/datatransfer/message/transfer_message_cbor_gen.go @@ -0,0 +1,116 @@ +package message + +import ( + "fmt" + "io" + + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" +) + +// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. + +var _ = xerrors.Errorf + +func (t *transferMessage) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{131}); err != nil { + return err + } + + // t.IsRq (bool) (bool) + if err := cbg.WriteBool(w, t.IsRq); err != nil { + return err + } + + // t.Request (message.transferRequest) (struct) + if err := t.Request.MarshalCBOR(w); err != nil { + return err + } + + // t.Response (message.transferResponse) (struct) + if err := t.Response.MarshalCBOR(w); err != nil { + return err + } + return nil +} + +func (t *transferMessage) UnmarshalCBOR(r io.Reader) error { + br := cbg.GetPeeker(r) + + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 3 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.IsRq (bool) (bool) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajOther { + return fmt.Errorf("booleans must be major type 7") + } + switch extra { + case 20: + t.IsRq = false + case 21: + t.IsRq = true + default: + return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) + } + // t.Request (message.transferRequest) (struct) + + { + + pb, err := br.PeekByte() + if err != nil { + return err + } + if pb == cbg.CborNull[0] { + var nbuf [1]byte + if _, err := br.Read(nbuf[:]); err != nil { + return err + } + } else { + t.Request = new(transferRequest) + if err := t.Request.UnmarshalCBOR(br); err != nil { + return err + } + } + + } + // t.Response (message.transferResponse) (struct) + + { + + pb, err := br.PeekByte() + if err != nil { + return err + } + if pb == cbg.CborNull[0] { + var nbuf [1]byte + if _, err := br.Read(nbuf[:]); err != nil { + return err + } + } else { + t.Response = new(transferResponse) + if err := t.Response.UnmarshalCBOR(br); err != nil { + return err + } + } + + } + return nil +} diff --git a/datatransfer/message/transfer_request.go b/datatransfer/message/transfer_request.go index 8ce059f1..4a00ea98 100644 --- a/datatransfer/message/transfer_request.go +++ b/datatransfer/message/transfer_request.go @@ -7,6 +7,8 @@ import ( "github.com/ipfs/go-cid" ) +//go:generate cbor-gen-for transferRequest + // transferRequest is a struct that fulfills the DataTransferRequest interface. // its members are exported to be used by cbor-gen type transferRequest struct { diff --git a/datatransfer/message/transfer_request_cbor_gen.go b/datatransfer/message/transfer_request_cbor_gen.go new file mode 100644 index 00000000..31742b96 --- /dev/null +++ b/datatransfer/message/transfer_request_cbor_gen.go @@ -0,0 +1,234 @@ +package message + +import ( + "fmt" + "io" + + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" +) + +// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. + +var _ = xerrors.Errorf + +func (t *transferRequest) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{137}); err != nil { + return err + } + + // t.BCid (string) (string) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.BCid)))); err != nil { + return err + } + if _, err := w.Write([]byte(t.BCid)); err != nil { + return err + } + + // t.Canc (bool) (bool) + if err := cbg.WriteBool(w, t.Canc); err != nil { + return err + } + + // t.PID ([]uint8) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.PID)))); err != nil { + return err + } + if _, err := w.Write(t.PID); err != nil { + return err + } + + // t.Part (bool) (bool) + if err := cbg.WriteBool(w, t.Part); err != nil { + return err + } + + // t.Pull (bool) (bool) + if err := cbg.WriteBool(w, t.Pull); err != nil { + return err + } + + // t.Stor ([]uint8) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Stor)))); err != nil { + return err + } + if _, err := w.Write(t.Stor); err != nil { + return err + } + + // t.Vouch ([]uint8) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Vouch)))); err != nil { + return err + } + if _, err := w.Write(t.Vouch); err != nil { + return err + } + + // t.VTyp (string) (string) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajTextString, uint64(len(t.VTyp)))); err != nil { + return err + } + if _, err := w.Write([]byte(t.VTyp)); err != nil { + return err + } + + // t.XferID (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.XferID))); err != nil { + return err + } + return nil +} + +func (t *transferRequest) UnmarshalCBOR(r io.Reader) error { + br := cbg.GetPeeker(r) + + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 9 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.BCid (string) (string) + + { + sval, err := cbg.ReadString(br) + if err != nil { + return err + } + + t.BCid = string(sval) + } + // t.Canc (bool) (bool) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajOther { + return fmt.Errorf("booleans must be major type 7") + } + switch extra { + case 20: + t.Canc = false + case 21: + t.Canc = true + default: + return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) + } + // t.PID ([]uint8) (slice) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.PID: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + t.PID = make([]byte, extra) + if _, err := io.ReadFull(br, t.PID); err != nil { + return err + } + // t.Part (bool) (bool) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajOther { + return fmt.Errorf("booleans must be major type 7") + } + switch extra { + case 20: + t.Part = false + case 21: + t.Part = true + default: + return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) + } + // t.Pull (bool) (bool) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajOther { + return fmt.Errorf("booleans must be major type 7") + } + switch extra { + case 20: + t.Pull = false + case 21: + t.Pull = true + default: + return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) + } + // t.Stor ([]uint8) (slice) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.Stor: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + t.Stor = make([]byte, extra) + if _, err := io.ReadFull(br, t.Stor); err != nil { + return err + } + // t.Vouch ([]uint8) (slice) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.Vouch: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + t.Vouch = make([]byte, extra) + if _, err := io.ReadFull(br, t.Vouch); err != nil { + return err + } + // t.VTyp (string) (string) + + { + sval, err := cbg.ReadString(br) + if err != nil { + return err + } + + t.VTyp = string(sval) + } + // t.XferID (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.XferID = uint64(extra) + return nil +} diff --git a/datatransfer/message/transfer_response.go b/datatransfer/message/transfer_response.go index af119462..9f897102 100644 --- a/datatransfer/message/transfer_response.go +++ b/datatransfer/message/transfer_response.go @@ -6,6 +6,8 @@ import ( "github.com/filecoin-project/go-fil-components/datatransfer" ) +//go:generate cbor-gen-for transferResponse + // transferResponse is a private struct that satisfies the DataTransferResponse interface type transferResponse struct { Acpt bool diff --git a/datatransfer/message/transfer_response_cbor_gen.go b/datatransfer/message/transfer_response_cbor_gen.go new file mode 100644 index 00000000..04f2db7e --- /dev/null +++ b/datatransfer/message/transfer_response_cbor_gen.go @@ -0,0 +1,79 @@ +package message + +import ( + "fmt" + "io" + + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" +) + +// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. + +var _ = xerrors.Errorf + +func (t *transferResponse) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{130}); err != nil { + return err + } + + // t.Acpt (bool) (bool) + if err := cbg.WriteBool(w, t.Acpt); err != nil { + return err + } + + // t.XferID (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.XferID))); err != nil { + return err + } + return nil +} + +func (t *transferResponse) UnmarshalCBOR(r io.Reader) error { + br := cbg.GetPeeker(r) + + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 2 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Acpt (bool) (bool) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajOther { + return fmt.Errorf("booleans must be major type 7") + } + switch extra { + case 20: + t.Acpt = false + case 21: + t.Acpt = true + default: + return fmt.Errorf("booleans are either major type 7, value 20 or 21 (got %d)", extra) + } + // t.XferID (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.XferID = uint64(extra) + return nil +} diff --git a/filestore/file.go b/filestore/file.go index 20fcd34e..dcfeb2a9 100644 --- a/filestore/file.go +++ b/filestore/file.go @@ -3,29 +3,28 @@ package filestore import "os" type fd struct { - *os.File - filename string + *os.File + filename string } func newFile(filename Path) (File, error) { - var err error - result := fd{filename: string(filename) } - result.File, err = os.OpenFile(result.filename, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644) - if err != nil { - return nil, err - } - return &result, nil + var err error + result := fd{filename: string(filename)} + result.File, err = os.OpenFile(result.filename, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644) + if err != nil { + return nil, err + } + return &result, nil } func (f fd) Path() Path { - return Path(f.filename) + return Path(f.filename) } func (f fd) Size() int64 { - info, err := os.Stat(f.filename) - if err != nil { - return -1 - } - return info.Size() + info, err := os.Stat(f.filename) + if err != nil { + return -1 + } + return info.Size() } - diff --git a/filestore/filestore.go b/filestore/filestore.go index 0d7054e2..2fd88063 100644 --- a/filestore/filestore.go +++ b/filestore/filestore.go @@ -18,7 +18,7 @@ func NewLocalFileStore(basedirectory string) (FileStore, error) { break } } - base := basedirectory[0:i + 1] + base := basedirectory[0 : i+1] info, err := os.Stat(base) if err != nil { return nil, fmt.Errorf("error getting %s info: %s", base, err.Error()) @@ -64,5 +64,3 @@ func (fs fileStore) Store(p Path, src File) error { func (fs fileStore) Delete(p Path) error { return os.Remove(fs.filename(p)) } - - diff --git a/filestore/filestore_test.go b/filestore/filestore_test.go index d07131a2..74c6bf4c 100644 --- a/filestore/filestore_test.go +++ b/filestore/filestore_test.go @@ -6,7 +6,7 @@ import ( "os" "testing" - filestore "github.com/filecoin-project/go-fil-filestore" + filestore "github.com/filecoin-project/go-fil-components/filestore" "github.com/stretchr/testify/require" ) @@ -107,7 +107,10 @@ func Test_CreateFile(t *testing.T) { path := fmt.Sprintf("%s%c%s", baseDir, os.PathSeparator, name) file, err := store.Create(name) require.NoError(t, err) - defer func () { store.Delete(name) } () + defer func() { + err := store.Delete(name) + require.NoError(t, err) + }() require.Equal(t, filestore.Path(path), file.Path()) bytesToWrite := 32 written, err := file.Write(randBytes(bytesToWrite)) @@ -127,10 +130,10 @@ func Test_OpenAndReadFile(t *testing.T) { offset, err := file.Seek(pos, 0) require.NoError(t, err) require.Equal(t, pos, offset) - buffer := make([]byte, size / 2) + buffer := make([]byte, size/2) read, err := file.Read(buffer) require.NoError(t, err) - require.Equal(t, int(size / 2), read) + require.Equal(t, int(size/2), read) err = file.Close() require.NoError(t, err) } diff --git a/go.mod b/go.mod index f356e229..4fd81726 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,8 @@ go 1.13 require ( github.com/filecoin-project/filecoin-ffi v0.0.0-20191210104338-2383ce072e95 - github.com/filecoin-project/go-fil-filestore v0.0.0-20191202230242-40c6a5a2306c github.com/gogo/protobuf v1.3.1 // indirect - github.com/google/go-cmp v0.3.1 // indirect - github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect - github.com/hashicorp/golang-lru v0.5.3 // indirect - github.com/ipfs/go-bitswap v0.1.8 // indirect + github.com/hannahhoward/cbor-gen-for v0.0.0-20191216214420-3e450425c40c github.com/ipfs/go-block-format v0.0.2 github.com/ipfs/go-blockservice v0.1.3-0.20190908200855-f22eea50656c github.com/ipfs/go-car v0.0.3-0.20191203022317-23b0a85fd1b1 @@ -21,26 +17,25 @@ require ( github.com/ipfs/go-ipfs-chunker v0.0.1 github.com/ipfs/go-ipfs-exchange-offline v0.0.1 github.com/ipfs/go-ipfs-files v0.0.4 + github.com/ipfs/go-ipld-cbor v0.0.3 github.com/ipfs/go-ipld-format v0.0.2 github.com/ipfs/go-log v1.0.0 github.com/ipfs/go-merkledag v0.2.4 github.com/ipfs/go-unixfs v0.2.2-0.20190827150610-868af2e9e5cb github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785 + github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c github.com/libp2p/go-libp2p v0.3.0 github.com/libp2p/go-libp2p-blankhost v0.1.4 // indirect github.com/libp2p/go-libp2p-core v0.2.4 github.com/libp2p/go-libp2p-record v0.1.1 // indirect github.com/libp2p/go-libp2p-swarm v0.2.2 // indirect + github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 github.com/multiformats/go-multiaddr-dns v0.2.0 // indirect - github.com/onsi/ginkgo v1.9.0 // indirect - github.com/onsi/gomega v1.6.0 // indirect - github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a // indirect - github.com/smartystreets/assertions v1.0.1 // indirect - github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect + github.com/multiformats/go-varint v0.0.1 + github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a github.com/stretchr/testify v1.4.0 - github.com/whyrusleeping/cbor-gen v0.0.0-20191116002219-891f55cd449d - golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 // indirect + github.com/whyrusleeping/cbor-gen v0.0.0-20191212224538-d370462a7e8a golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 ) diff --git a/go.sum b/go.sum index 294b51eb..8b4d8b4b 100644 --- a/go.sum +++ b/go.sum @@ -27,7 +27,10 @@ github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8Nz github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 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= @@ -41,13 +44,12 @@ github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUn github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fd/go-nat v1.0.0/go.mod h1:BTBu/CKvMmOMUPkKVef1pngt2WFH/lg7E6yQnulfp6E= -github.com/filecoin-project/go-fil-filestore v0.0.0-20191202230242-40c6a5a2306c h1:Byp8vSRghdZNyYsai6/P0yleQToc5P6BVdakhtBJONU= -github.com/filecoin-project/go-fil-filestore v0.0.0-20191202230242-40c6a5a2306c/go.mod h1:pPW5DjeA3Fk89gLGxMYH7FFd8TzZ4H3NAryc7UWQVCg= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -62,23 +64,22 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/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/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f h1:KMlcu9X58lhTA/KrfX8Bi1LQSO4pzoVjTiL3h4Jk+Zk= -github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= github.com/gxed/pubsub v0.0.0-20180201040156-26ebdf44f824/go.mod h1:OiEWyHgK+CWrmOlVquHaIK1vhpUJydC9m0Je6mhaiNE= +github.com/hannahhoward/cbor-gen-for v0.0.0-20191216214420-3e450425c40c h1:+MSf4NEnLCYZoAgK6fqwc7NH88nM8haFSxKGUGIG3vA= +github.com/hannahhoward/cbor-gen-for v0.0.0-20191216214420-3e450425c40c/go.mod h1:WVPCl0HO/0RAL5+vBH2GMxBomlxBF70MAS78+Lu1//k= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= -github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -92,9 +93,8 @@ 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/go-bitswap v0.1.0/go.mod h1:FFJEf18E9izuCqUtHxbWEvq+reg7o4CW5wSAE1wsxj0= github.com/ipfs/go-bitswap v0.1.2/go.mod h1:qxSWS4NXGs7jQ6zQvoPY3+NmOfHHG47mhkiLzBpJQIs= +github.com/ipfs/go-bitswap v0.1.3 h1:jAl9Z/TYObpGeGATUemnOZ7RYb0F/kzNVlhcYZesz+0= github.com/ipfs/go-bitswap v0.1.3/go.mod h1:YEQlFy0kkxops5Vy+OxWdRSEZIoS7I7KDIwoa5Chkps= -github.com/ipfs/go-bitswap v0.1.8 h1:38X1mKXkiU6Nzw4TOSWD8eTVY5eX3slQunv3QEWfXKg= -github.com/ipfs/go-bitswap v0.1.8/go.mod h1:TOWoxllhccevbWFUR2N7B1MTSVVge1s6XSMiCSA4MzM= github.com/ipfs/go-block-format v0.0.1/go.mod h1:DK/YYcsSUIVAFNwo/KZCdIIbpN0ROH/baNLgayt4pFc= github.com/ipfs/go-block-format v0.0.2 h1:qPDvcP19izTjU8rgo6p7gTXZlkMkF5bz5G3fqIsSCPE= github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY= @@ -172,6 +172,8 @@ github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785 h1:fASnkvtR+S github.com/ipld/go-ipld-prime v0.0.2-0.20191108012745-28a82f04c785/go.mod h1:bDDSvVz7vaK12FNvMeRYnpRFkSUPNQOiCYQezMD/P3w= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5 h1:lSip43rAdyGA+yRQuy6ju0ucZkWpYc1F2CTQtZTVW/4= github.com/ipld/go-ipld-prime-proto v0.0.0-20191113031812-e32bd156a1e5/go.mod h1:gcvzoEDBjwycpXt3LBE061wT9f46szXGHAmj9uoP6fU= +github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c= +github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4= github.com/jackpal/gateway v1.0.4/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= @@ -215,6 +217,7 @@ github.com/libp2p/go-conn-security v0.0.1/go.mod h1:bGmu51N0KU9IEjX7kl2PQjgZa40J github.com/libp2p/go-conn-security-multistream v0.1.0 h1:aqGmto+ttL/uJgX0JtQI0tD21CIEy5eYd1Hlp0juHY0= github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= github.com/libp2p/go-eventbus v0.0.2/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= +github.com/libp2p/go-eventbus v0.0.3 h1:4sB0NrwnWr6qGeq2RWUp/JG1wNajf6gyILInId72hrw= github.com/libp2p/go-eventbus v0.0.3/go.mod h1:Hr/yGlwxA/stuLnpMiu82lpNKpvRy3EaJxPu40XYOwk= github.com/libp2p/go-eventbus v0.1.0 h1:mlawomSAjjkk97QnYiEmHsLu7E136+2oCWSHRUvMfzQ= github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= @@ -357,12 +360,14 @@ github.com/multiformats/go-multiaddr v0.1.1 h1:rVAztJYMhCQ7vEFr8FvxW3mS+HF2eY/oP github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-dns v0.0.3 h1:P19q/k9jwmtgh+qXFkKfgFM7rCg/9l5AVqh7VNxSXhs= github.com/multiformats/go-multiaddr-dns v0.0.3/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= github.com/multiformats/go-multiaddr-dns v0.2.0 h1:YWJoIDwLePniH7OU5hBnDZV6SWuvJqJ0YtN6pLeH9zA= github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= 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-multiaddr-net v0.0.1 h1:76O59E3FavvHqNg7jvzWzsPSW5JSi/ek0E4eiDVbg9g= github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= github.com/multiformats/go-multiaddr-net v0.1.0 h1:ZepO8Ezwovd+7b5XPPDhQhayk1yt0AJpzQBpq9fejx4= github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= @@ -377,15 +382,15 @@ github.com/multiformats/go-multihash v0.0.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa github.com/multiformats/go-multistream v0.0.1/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= github.com/multiformats/go-multistream v0.1.0 h1:UpO6jrsjqs46mqAK3n6wKRYFhugss9ArzbyUzU+4wkQ= github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= +github.com/multiformats/go-varint v0.0.1 h1:TR/0rdQtnNxuN2IhiB639xC3tWM4IUi7DkTBVTdGW/M= +github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.9.0 h1:SZjF721BByVj8QH636/8S2DnX4n0Re3SteMmw3N+tzc= -github.com/onsi/ginkgo v1.9.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.6.0 h1:8XTW0fcJZEq9q+Upcyws4JSGua2MFysCL5xkaSgHc+M= -github.com/onsi/gomega v1.6.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= @@ -398,17 +403,20 @@ github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXx github.com/polydawn/refmt v0.0.0-20190408063855-01bf1e26dd14/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a h1:hjZfReYVLbqFkAtr2us7vdy04YWz3LVAirzP7reh8+M= github.com/polydawn/refmt v0.0.0-20190809202753-05966cbd336a/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= +github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= -github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= -github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945 h1:N8Bg45zpk/UcpNGnfJt2y/3lRWASHNTUET8owPYCgYI= github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8= -github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU= @@ -431,12 +439,15 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli/v2 v2.0.0 h1:+HU9SCbu8GnEUFtIBfuUNXN39ofWViIEJIp6SURMpCg= +github.com/urfave/cli/v2 v2.0.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830 h1:8kxMKmKzXXL4Ru1nyhvdms/JjWt+3YLpvRb/bAjO/y0= github.com/warpfork/go-wish v0.0.0-20190328234359-8b3e70f8e830/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw= -github.com/whyrusleeping/cbor-gen v0.0.0-20191116002219-891f55cd449d h1:NRa/Vs7+b91GdXrp0AqsG7pspWV6CLk5Gk7i46L4tGo= -github.com/whyrusleeping/cbor-gen v0.0.0-20191116002219-891f55cd449d/go.mod h1:xdlJQaiqipF0HW+Mzpg7XRM3fWbGvfgFlcppuvlkIvY= +github.com/whyrusleeping/cbor-gen v0.0.0-20191212224538-d370462a7e8a h1:xc8sbWMwBsvi8OrxFZR8zxw/fdCneHBLFDJJaV14eaE= +github.com/whyrusleeping/cbor-gen v0.0.0-20191212224538-d370462a7e8a/go.mod h1:xdlJQaiqipF0HW+Mzpg7XRM3fWbGvfgFlcppuvlkIvY= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f h1:jQa4QT2UP9WYv2nzyawpKMOCl+Z/jW7djv2/J50lj9E= github.com/whyrusleeping/chunker v0.0.0-20181014151217-fe64bd25879f/go.mod h1:p9UJB6dDgdPgMJZs7UjUOdulKyRr9fqkS+6JKAInPy8= github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= @@ -482,6 +493,7 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20180524181706-dfa909b99c79/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -501,6 +513,7 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -515,9 +528,8 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190524122548-abf6ff778158/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e h1:D5TXcfTk7xF7hvieo4QErS3qqCB4teTffacDWr7CI+0= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456 h1:ng0gs1AKnRRuEMZoTLLlbOd+C17zUDepwGQBb/n+JVg= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -529,6 +541,8 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 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-20191216173652-a0e659d51361 h1:RIIXAeV6GvDBuADKumTODatUqANFZ+5BPMnzsy4hulY= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pieceio/cario/cario.go b/pieceio/cario/cario.go index be764c47..e15ea19e 100644 --- a/pieceio/cario/cario.go +++ b/pieceio/cario/cario.go @@ -1,42 +1,42 @@ package cario import ( - "context" - "fmt" - "github.com/filecoin-project/go-fil-components/pieceio" - "github.com/ipfs/go-car" - "github.com/ipfs/go-cid" - "github.com/ipld/go-ipld-prime" - "github.com/ipld/go-ipld-prime/traversal/selector" - "io" + "context" + "fmt" + "github.com/filecoin-project/go-fil-components/pieceio" + "github.com/ipfs/go-car" + "github.com/ipfs/go-cid" + "github.com/ipld/go-ipld-prime" + "github.com/ipld/go-ipld-prime/traversal/selector" + "io" ) type carIO struct { } func NewCarIO() pieceio.CarIO { - return &carIO{} + return &carIO{} } func (c carIO) WriteCar(ctx context.Context, bs pieceio.ReadStore, payloadCid cid.Cid, node ipld.Node, w io.Writer) error { - selector, err := selector.ParseSelector(node) - if err != nil { - return err - } - return car.WriteSelectiveCar(ctx, bs, []car.CarDag{{Root: payloadCid, Selector: selector}}, w) + selector, err := selector.ParseSelector(node) + if err != nil { + return err + } + return car.WriteSelectiveCar(ctx, bs, []car.CarDag{{Root: payloadCid, Selector: selector}}, w) } func (c carIO) LoadCar(bs pieceio.WriteStore, r io.Reader) (cid.Cid, error) { - header, err := car.LoadCar(bs, r) - if err != nil { - return cid.Undef, err - } - l := len(header.Roots) - if l == 0 { - return cid.Undef, fmt.Errorf("invalid header: missing root") - } - if l > 1 { - return cid.Undef, fmt.Errorf("invalid header: contains %d roots (expecting 1)", l) - } - return header.Roots[0], nil + header, err := car.LoadCar(bs, r) + if err != nil { + return cid.Undef, err + } + l := len(header.Roots) + if l == 0 { + return cid.Undef, fmt.Errorf("invalid header: missing root") + } + if l > 1 { + return cid.Undef, fmt.Errorf("invalid header: contains %d roots (expecting 1)", l) + } + return header.Roots[0], nil } diff --git a/pieceio/padreader/padreader.go b/pieceio/padreader/padreader.go index e3697e70..3c97ded6 100644 --- a/pieceio/padreader/padreader.go +++ b/pieceio/padreader/padreader.go @@ -1,27 +1,27 @@ package padreader import ( - ffi "github.com/filecoin-project/filecoin-ffi" - "github.com/filecoin-project/go-fil-components/pieceio" - "math/bits" + ffi "github.com/filecoin-project/filecoin-ffi" + "github.com/filecoin-project/go-fil-components/pieceio" + "math/bits" ) type padReader struct { } func NewPadReader() pieceio.PadReader { - return &padReader{} + return &padReader{} } // Functions bellow copied from lotus/lib/padreader/padreader.go func (p padReader) PaddedSize(size uint64) uint64 { - logv := 64 - bits.LeadingZeros64(size) + logv := 64 - bits.LeadingZeros64(size) - sectSize := uint64(1 << logv) - bound := ffi.GetMaxUserBytesPerStagedSector(sectSize) - if size <= bound { - return bound - } + sectSize := uint64(1 << logv) + bound := ffi.GetMaxUserBytesPerStagedSector(sectSize) + if size <= bound { + return bound + } - return ffi.GetMaxUserBytesPerStagedSector(1 << (logv + 1)) + return ffi.GetMaxUserBytesPerStagedSector(1 << (logv + 1)) } diff --git a/pieceio/pieceio_test.go b/pieceio/pieceio_test.go index 6d58918e..aec46d29 100644 --- a/pieceio/pieceio_test.go +++ b/pieceio/pieceio_test.go @@ -19,7 +19,6 @@ import ( "testing" ) - func Test_ThereAndBackAgain(t *testing.T) { tempDir := filestore.Path("./tempDir") sc := sectorcalculator.NewSectorCalculator(tempDir) @@ -83,7 +82,7 @@ func Test_ThereAndBackAgain(t *testing.T) { for idx := int64(0); idx < int64(read); idx++ { if buf[idx] == 0 { if padStart == -1 { - padStart = skipped + loops * bufSize + idx + padStart = skipped + loops*bufSize + idx } } else { padStart = -1 @@ -151,7 +150,7 @@ func Test_StoreRestoreMemoryBuffer(t *testing.T) { } f, err := os.Open(string(filename)) require.NoError(t, err) - defer func () { + defer func() { f.Close() os.Remove(f.Name()) }() @@ -162,4 +161,4 @@ func Test_StoreRestoreMemoryBuffer(t *testing.T) { secondCommitment, err := sc.GeneratePieceCommitment(buffer, uint64(info.Size())) require.NoError(t, err) require.Equal(t, commitment, secondCommitment) -} \ No newline at end of file +} diff --git a/pieceio/sectorcalculator/sectorcalculator.go b/pieceio/sectorcalculator/sectorcalculator.go index df41deff..5441e22c 100644 --- a/pieceio/sectorcalculator/sectorcalculator.go +++ b/pieceio/sectorcalculator/sectorcalculator.go @@ -1,45 +1,45 @@ package sectorcalculator import ( - ffi "github.com/filecoin-project/filecoin-ffi" - "github.com/filecoin-project/go-fil-components/filestore" - "github.com/filecoin-project/go-fil-components/pieceio" - "io" - "io/ioutil" - "os" + ffi "github.com/filecoin-project/filecoin-ffi" + "github.com/filecoin-project/go-fil-components/filestore" + "github.com/filecoin-project/go-fil-components/pieceio" + "io" + "io/ioutil" + "os" ) type sectorCalculator struct { - tempDir filestore.Path + tempDir filestore.Path } func NewSectorCalculator(tempDir filestore.Path) pieceio.SectorCalculator { - return §orCalculator{tempDir} + return §orCalculator{tempDir} } func (s sectorCalculator) GeneratePieceCommitment(piece io.Reader, pieceSize uint64) ([]byte, error) { - f, ok := piece.(*os.File) // try to avoid yet another temp file - var err error - if !ok { - f, err = ioutil.TempFile(string(s.tempDir), "") - if err != nil { - return nil, err - } - defer func () { // cleanup - f.Close() - os.Remove(f.Name()) - }() - _, err = io.Copy(f, io.LimitReader(piece, int64(pieceSize))) - if err != nil { - return nil, err - } - _, err = f.Seek(0, io.SeekStart) - if err != nil { - return nil, err - } - } else { - defer f.Close() - } - commP, err := ffi.GeneratePieceCommitmentFromFile(f, pieceSize) - return commP[:], err + f, ok := piece.(*os.File) // try to avoid yet another temp file + var err error + if !ok { + f, err = ioutil.TempFile(string(s.tempDir), "") + if err != nil { + return nil, err + } + defer func() { // cleanup + f.Close() + os.Remove(f.Name()) + }() + _, err = io.Copy(f, io.LimitReader(piece, int64(pieceSize))) + if err != nil { + return nil, err + } + _, err = f.Seek(0, io.SeekStart) + if err != nil { + return nil, err + } + } else { + defer f.Close() + } + commP, err := ffi.GeneratePieceCommitmentFromFile(f, pieceSize) + return commP[:], err } diff --git a/shared/address/address.go b/shared/address/address.go new file mode 100644 index 00000000..7cf99e67 --- /dev/null +++ b/shared/address/address.go @@ -0,0 +1,415 @@ +package address + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "strconv" + + bls "github.com/filecoin-project/filecoin-ffi" + cbor "github.com/ipfs/go-ipld-cbor" + "github.com/minio/blake2b-simd" + "github.com/multiformats/go-varint" + "github.com/polydawn/refmt/obj/atlas" + "golang.org/x/xerrors" + + cbg "github.com/whyrusleeping/cbor-gen" +) + +func init() { + cbor.RegisterCborType(addressAtlasEntry) +} + +var addressAtlasEntry = atlas.BuildEntry(Address{}).Transform(). + TransformMarshal(atlas.MakeMarshalTransformFunc( + func(a Address) (string, error) { + return string(a.Bytes()), nil + })). + TransformUnmarshal(atlas.MakeUnmarshalTransformFunc( + func(x string) (Address, error) { + return NewFromBytes([]byte(x)) + })). + Complete() + +// Address is the go type that represents an address in the filecoin network. +type Address struct{ str string } + +// Undef is the type that represents an undefined address. +var Undef = Address{} + +// Network represents which network an address belongs to. +type Network = byte + +const ( + // Mainnet is the main network. + Mainnet Network = iota + // Testnet is the test network. + Testnet +) + +// MainnetPrefix is the main network prefix. +const MainnetPrefix = "f" + +// TestnetPrefix is the main network prefix. +const TestnetPrefix = "t" + +// Protocol represents which protocol an address uses. +type Protocol = byte + +const ( + // ID represents the address ID protocol. + ID Protocol = iota + // SECP256K1 represents the address SECP256K1 protocol. + SECP256K1 + // Actor represents the address Actor protocol. + Actor + // BLS represents the address BLS protocol. + BLS + + Unknown = Protocol(255) +) + +// Protocol returns the protocol used by the address. +func (a Address) Protocol() Protocol { + if len(a.str) == 0 { + return Unknown + } + return a.str[0] +} + +// Payload returns the payload of the address. +func (a Address) Payload() []byte { + return []byte(a.str[1:]) +} + +// Bytes returns the address as bytes. +func (a Address) Bytes() []byte { + return []byte(a.str) +} + +// String returns an address encoded as a string. +func (a Address) String() string { + str, err := encode(Testnet, a) + if err != nil { + panic(err) // I don't know if this one is okay + } + return str +} + +// Empty returns true if the address is empty, false otherwise. +func (a Address) Empty() bool { + return a == Undef +} + +// Unmarshal unmarshals the cbor bytes into the address. +func (a Address) Unmarshal(b []byte) error { + return cbor.DecodeInto(b, &a) +} + +// Marshal marshals the address to cbor. +func (a Address) Marshal() ([]byte, error) { + return cbor.DumpObject(a) +} + +// UnmarshalJSON implements the json unmarshal interface. +func (a *Address) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + addr, err := decode(s) + if err != nil { + return err + } + *a = addr + return nil +} + +// MarshalJSON implements the json marshal interface. +func (a Address) MarshalJSON() ([]byte, error) { + return []byte(`"` + a.String() + `"`), nil +} + +// Format implements the Formatter interface. +func (a Address) Format(f fmt.State, c rune) { + switch c { + case 'v': + if a.Empty() { + fmt.Fprint(f, UndefAddressString) //nolint: errcheck + } else { + fmt.Fprintf(f, "[%x - %x]", a.Protocol(), a.Payload()) // nolint: errcheck + } + case 's': + fmt.Fprintf(f, "%s", a.String()) // nolint: errcheck + default: + fmt.Fprintf(f, "%"+string(c), a.Bytes()) // nolint: errcheck + } +} + +func (a *Address) Scan(value interface{}) error { + switch value := value.(type) { + case string: + a1, err := decode(value) + if err != nil { + return err + } + + *a = a1 + + return nil + default: + return xerrors.New("non-string types unsupported") + } +} + +// NewIDAddress returns an address using the ID protocol. +func NewIDAddress(id uint64) (Address, error) { + return newAddress(ID, varint.ToUvarint(id)) +} + +// NewSecp256k1Address returns an address using the SECP256K1 protocol. +func NewSecp256k1Address(pubkey []byte) (Address, error) { + return newAddress(SECP256K1, addressHash(pubkey)) +} + +// NewActorAddress returns an address using the Actor protocol. +func NewActorAddress(data []byte) (Address, error) { + return newAddress(Actor, addressHash(data)) +} + +// NewBLSAddress returns an address using the BLS protocol. +func NewBLSAddress(pubkey []byte) (Address, error) { + return newAddress(BLS, pubkey) +} + +// NewFromString returns the address represented by the string `addr`. +func NewFromString(addr string) (Address, error) { + return decode(addr) +} + +// NewFromBytes return the address represented by the bytes `addr`. +func NewFromBytes(addr []byte) (Address, error) { + if len(addr) == 0 { + return Undef, nil + } + if len(addr) == 1 { + return Undef, ErrInvalidLength + } + return newAddress(addr[0], addr[1:]) +} + +// Checksum returns the checksum of `ingest`. +func Checksum(ingest []byte) []byte { + return hash(ingest, checksumHashConfig) +} + +// ValidateChecksum returns true if the checksum of `ingest` is equal to `expected`> +func ValidateChecksum(ingest, expect []byte) bool { + digest := Checksum(ingest) + return bytes.Equal(digest, expect) +} + +func addressHash(ingest []byte) []byte { + return hash(ingest, payloadHashConfig) +} + +func newAddress(protocol Protocol, payload []byte) (Address, error) { + switch protocol { + case ID: + _, n, err := varint.FromUvarint(payload) + if err != nil { + return Undef, xerrors.Errorf("could not decode: %v: %w", err, ErrInvalidPayload) + } + if n != len(payload) { + return Undef, xerrors.Errorf("different varint length (v:%d != p:%d): %w", + n, len(payload), ErrInvalidPayload) + } + case SECP256K1, Actor: + if len(payload) != PayloadHashLength { + return Undef, ErrInvalidPayload + } + case BLS: + if len(payload) != bls.PublicKeyBytes { + return Undef, ErrInvalidPayload + } + default: + return Undef, ErrUnknownProtocol + } + explen := 1 + len(payload) + buf := make([]byte, explen) + + buf[0] = protocol + copy(buf[1:], payload) + + return Address{string(buf)}, nil +} + +func encode(network Network, addr Address) (string, error) { + if addr == Undef { + return UndefAddressString, nil + } + var ntwk string + switch network { + case Mainnet: + ntwk = MainnetPrefix + case Testnet: + ntwk = TestnetPrefix + default: + return UndefAddressString, ErrUnknownNetwork + } + + var strAddr string + switch addr.Protocol() { + case SECP256K1, Actor, BLS: + cksm := Checksum(append([]byte{addr.Protocol()}, addr.Payload()...)) + strAddr = ntwk + fmt.Sprintf("%d", addr.Protocol()) + AddressEncoding.WithPadding(-1).EncodeToString(append(addr.Payload(), cksm[:]...)) + case ID: + i, n, err := varint.FromUvarint(addr.Payload()) + if err != nil { + return UndefAddressString, xerrors.Errorf("could not decode varint: %w", err) + } + if n != len(addr.Payload()) { + return UndefAddressString, xerrors.Errorf("payload contains additional bytes") + } + strAddr = fmt.Sprintf("%s%d%d", ntwk, addr.Protocol(), i) + default: + return UndefAddressString, ErrUnknownProtocol + } + return strAddr, nil +} + +func decode(a string) (Address, error) { + if len(a) == 0 { + return Undef, nil + } + if a == UndefAddressString { + return Undef, nil + } + if len(a) > MaxAddressStringLength || len(a) < 3 { + return Undef, ErrInvalidLength + } + + if string(a[0]) != MainnetPrefix && string(a[0]) != TestnetPrefix { + return Undef, ErrUnknownNetwork + } + + var protocol Protocol + switch a[1] { + case '0': + protocol = ID + case '1': + protocol = SECP256K1 + case '2': + protocol = Actor + case '3': + protocol = BLS + default: + return Undef, ErrUnknownProtocol + } + + raw := a[2:] + if protocol == ID { + // 20 is length of math.MaxUint64 as a string + if len(raw) > 20 { + return Undef, ErrInvalidLength + } + id, err := strconv.ParseUint(raw, 10, 64) + if err != nil { + return Undef, ErrInvalidPayload + } + return newAddress(protocol, varint.ToUvarint(id)) + } + + payloadcksm, err := AddressEncoding.WithPadding(-1).DecodeString(raw) + if err != nil { + return Undef, err + } + payload := payloadcksm[:len(payloadcksm)-ChecksumHashLength] + cksm := payloadcksm[len(payloadcksm)-ChecksumHashLength:] + + if protocol == SECP256K1 || protocol == Actor { + if len(payload) != 20 { + return Undef, ErrInvalidPayload + } + } + + if !ValidateChecksum(append([]byte{protocol}, payload...), cksm) { + return Undef, ErrInvalidChecksum + } + + return newAddress(protocol, payload) +} + +func hash(ingest []byte, cfg *blake2b.Config) []byte { + hasher, err := blake2b.New(cfg) + if err != nil { + // If this happens sth is very wrong. + panic(fmt.Sprintf("invalid address hash configuration: %v", err)) // ok + } + if _, err := hasher.Write(ingest); err != nil { + // blake2bs Write implementation never returns an error in its current + // setup. So if this happens sth went very wrong. + panic(fmt.Sprintf("blake2b is unable to process hashes: %v", err)) // ok + } + return hasher.Sum(nil) +} + +func (a Address) MarshalCBOR(w io.Writer) error { + if a == Undef { + return fmt.Errorf("cannot marshal undefined address") + } + + abytes := a.Bytes() + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(abytes)))); err != nil { + return err + } + + if _, err := w.Write(abytes); err != nil { + return err + } + + return nil +} + +func (a *Address) UnmarshalCBOR(br io.Reader) error { + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + + if maj != cbg.MajByteString { + return fmt.Errorf("cbor type for address unmarshal was not byte string") + } + + if extra > 64 { + return fmt.Errorf("too many bytes to unmarshal for an address") + } + + buf := make([]byte, int(extra)) + if _, err := io.ReadFull(br, buf); err != nil { + return err + } + + addr, err := NewFromBytes(buf) + if err != nil { + return err + } + if addr == Undef { + return fmt.Errorf("cbor input should not contain empty addresses") + } + + *a = addr + + return nil +} + +func IDFromAddress(addr Address) (uint64, error) { + if addr.Protocol() != ID { + return 0, xerrors.Errorf("cannot get id from non id address") + } + + i, _, err := varint.FromUvarint(addr.Payload()) + return i, err +} diff --git a/shared/address/address_test.go b/shared/address/address_test.go new file mode 100644 index 00000000..dba88bbf --- /dev/null +++ b/shared/address/address_test.go @@ -0,0 +1,542 @@ +package address + +import ( + "bytes" + "encoding/base32" + "fmt" + "math" + "math/rand" + "strconv" + "testing" + "time" + + ffi "github.com/filecoin-project/filecoin-ffi" + "github.com/multiformats/go-varint" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/go-fil-components/shared/crypto" +) + +func init() { + rand.Seed(time.Now().Unix()) +} + +func TestRandomIDAddress(t *testing.T) { + assert := assert.New(t) + + addr, err := NewIDAddress(uint64(rand.Int())) + assert.NoError(err) + assert.Equal(ID, addr.Protocol()) + + str, err := encode(Testnet, addr) + assert.NoError(err) + + maybe, err := decode(str) + assert.NoError(err) + assert.Equal(addr, maybe) + +} + +var allTestAddresses = []string{ + "t00", + "t01", + "t010", + "t0150", + "t0499", + "t01024", + "t01729", + "t0999999", + "t15ihq5ibzwki2b4ep2f46avlkrqzhpqgtga7pdrq", + "t12fiakbhe2gwd5cnmrenekasyn6v5tnaxaqizq6a", + "t1wbxhu3ypkuo6eyp6hjx6davuelxaxrvwb2kuwva", + "t1xtwapqc6nh4si2hcwpr3656iotzmlwumogqbuaa", + "t1xcbgdhkgkwht3hrrnui3jdopeejsoatkzmoltqy", + "t17uoq6tp427uzv7fztkbsnn64iwotfrristwpryy", + "t24vg6ut43yw2h2jqydgbg2xq7x6f4kub3bg6as6i", + "t25nml2cfbljvn4goqtclhifepvfnicv6g7mfmmvq", + "t2nuqrg7vuysaue2pistjjnt3fadsdzvyuatqtfei", + "t24dd4ox4c2vpf5vk5wkadgyyn6qtuvgcpxxon64a", + "t2gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr23y", + "t3vvmn62lofvhjd2ugzca6sof2j2ubwok6cj4xxbfzz4yuxfkgobpihhd2thlanmsh3w2ptld2gqkn2jvlss4a", + "t3wmuu6crofhqmm3v4enos73okk2l366ck6yc4owxwbdtkmpk42ohkqxfitcpa57pjdcftql4tojda2poeruwa", + "t3s2q2hzhkpiknjgmf4zq3ejab2rh62qbndueslmsdzervrhapxr7dftie4kpnpdiv2n6tvkr743ndhrsw6d3a", + "t3q22fijmmlckhl56rn5nkyamkph3mcfu5ed6dheq53c244hfmnq2i7efdma3cj5voxenwiummf2ajlsbxc65a", + "t3u5zgwa4ael3vuocgc5mfgygo4yuqocrntuuhcklf4xzg5tcaqwbyfabxetwtj4tsam3pbhnwghyhijr5mixa", +} + +func TestVectorsIDAddress(t *testing.T) { + testCases := []struct { + input uint64 + expected string + }{ + {uint64(0), "t00"}, + {uint64(1), "t01"}, + {uint64(10), "t010"}, + {uint64(150), "t0150"}, + {uint64(499), "t0499"}, + {uint64(1024), "t01024"}, + {uint64(1729), "t01729"}, + {uint64(999999), "t0999999"}, + {math.MaxUint64, fmt.Sprintf("t0%s", strconv.FormatUint(math.MaxUint64, 10))}, + } + + for _, tc := range testCases { + tc := tc + t.Run(fmt.Sprintf("testing actorID address: %s", tc.expected), func(t *testing.T) { + assert := assert.New(t) + + // Round trip encoding and decoding from string + addr, err := NewIDAddress(tc.input) + assert.NoError(err) + assert.Equal(tc.expected, addr.String()) + + maybeAddr, err := NewFromString(tc.expected) + assert.NoError(err) + assert.Equal(ID, maybeAddr.Protocol()) + id, _, err := varint.FromUvarint(maybeAddr.Payload()) + assert.NoError(err) + assert.Equal(tc.input, id) + + // Round trip to and from bytes + maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes()) + assert.NoError(err) + assert.Equal(maybeAddr, maybeAddrBytes) + + // Round trip encoding and decoding json + b, err := addr.MarshalJSON() + assert.NoError(err) + + var newAddr Address + err = newAddr.UnmarshalJSON(b) + assert.NoError(err) + assert.Equal(addr, newAddr) + }) + } + +} + +func TestSecp256k1Address(t *testing.T) { + assert := assert.New(t) + + sk, err := crypto.GenerateKey() + assert.NoError(err) + + addr, err := NewSecp256k1Address(crypto.PublicKey(sk)) + assert.NoError(err) + assert.Equal(SECP256K1, addr.Protocol()) + + str, err := encode(Mainnet, addr) + assert.NoError(err) + + maybe, err := decode(str) + assert.NoError(err) + assert.Equal(addr, maybe) + +} + +func TestVectorSecp256k1Address(t *testing.T) { + testCases := []struct { + input []byte + expected string + }{ + {[]byte{4, 148, 2, 250, 195, 126, 100, 50, 164, 22, 163, 160, 202, 84, + 38, 181, 24, 90, 179, 178, 79, 97, 52, 239, 162, 92, 228, 135, 200, + 45, 46, 78, 19, 191, 69, 37, 17, 224, 210, 36, 84, 33, 248, 97, 59, + 193, 13, 114, 250, 33, 102, 102, 169, 108, 59, 193, 57, 32, 211, + 255, 35, 63, 208, 188, 5}, + "t15ihq5ibzwki2b4ep2f46avlkrqzhpqgtga7pdrq"}, + + {[]byte{4, 118, 135, 185, 16, 55, 155, 242, 140, 190, 58, 234, 103, 75, + 18, 0, 12, 107, 125, 186, 70, 255, 192, 95, 108, 148, 254, 42, 34, + 187, 204, 38, 2, 255, 127, 92, 118, 242, 28, 165, 93, 54, 149, 145, + 82, 176, 225, 232, 135, 145, 124, 57, 53, 118, 238, 240, 147, 246, + 30, 189, 58, 208, 111, 127, 218}, + "t12fiakbhe2gwd5cnmrenekasyn6v5tnaxaqizq6a"}, + {[]byte{4, 222, 253, 208, 16, 1, 239, 184, 110, 1, 222, 213, 206, 52, + 248, 71, 167, 58, 20, 129, 158, 230, 65, 188, 182, 11, 185, 41, 147, + 89, 111, 5, 220, 45, 96, 95, 41, 133, 248, 209, 37, 129, 45, 172, + 65, 99, 163, 150, 52, 155, 35, 193, 28, 194, 255, 53, 157, 229, 75, + 226, 135, 234, 98, 49, 155}, + "t1wbxhu3ypkuo6eyp6hjx6davuelxaxrvwb2kuwva"}, + {[]byte{4, 3, 237, 18, 200, 20, 182, 177, 13, 46, 224, 157, 149, 180, + 104, 141, 178, 209, 128, 208, 169, 163, 122, 107, 106, 125, 182, 61, + 41, 129, 30, 233, 115, 4, 121, 216, 239, 145, 57, 233, 18, 73, 202, + 189, 57, 50, 145, 207, 229, 210, 119, 186, 118, 222, 69, 227, 224, + 133, 163, 118, 129, 191, 54, 69, 210}, + "t1xtwapqc6nh4si2hcwpr3656iotzmlwumogqbuaa"}, + {[]byte{4, 247, 150, 129, 154, 142, 39, 22, 49, 175, 124, 24, 151, 151, + 181, 69, 214, 2, 37, 147, 97, 71, 230, 1, 14, 101, 98, 179, 206, 158, + 254, 139, 16, 20, 65, 97, 169, 30, 208, 180, 236, 137, 8, 0, 37, 63, + 166, 252, 32, 172, 144, 251, 241, 251, 242, 113, 48, 164, 236, 195, + 228, 3, 183, 5, 118}, + "t1xcbgdhkgkwht3hrrnui3jdopeejsoatkzmoltqy"}, + {[]byte{4, 66, 131, 43, 248, 124, 206, 158, 163, 69, 185, 3, 80, 222, + 125, 52, 149, 133, 156, 164, 73, 5, 156, 94, 136, 221, 231, 66, 133, + 223, 251, 158, 192, 30, 186, 188, 95, 200, 98, 104, 207, 234, 235, + 167, 174, 5, 191, 184, 214, 142, 183, 90, 82, 104, 120, 44, 248, 111, + 200, 112, 43, 239, 138, 31, 224}, + "t17uoq6tp427uzv7fztkbsnn64iwotfrristwpryy"}, + } + + for _, tc := range testCases { + tc := tc + t.Run(fmt.Sprintf("testing secp256k1 address: %s", tc.expected), func(t *testing.T) { + assert := assert.New(t) + + // Round trip encoding and decoding from string + addr, err := NewSecp256k1Address(tc.input) + assert.NoError(err) + assert.Equal(tc.expected, addr.String()) + + maybeAddr, err := NewFromString(tc.expected) + assert.NoError(err) + assert.Equal(SECP256K1, maybeAddr.Protocol()) + assert.Equal(addressHash(tc.input), maybeAddr.Payload()) + + // Round trip to and from bytes + maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes()) + assert.NoError(err) + assert.Equal(maybeAddr, maybeAddrBytes) + + // Round trip encoding and decoding json + b, err := addr.MarshalJSON() + assert.NoError(err) + + var newAddr Address + err = newAddr.UnmarshalJSON(b) + assert.NoError(err) + assert.Equal(addr, newAddr) + }) + } +} + +func TestRandomActorAddress(t *testing.T) { + assert := assert.New(t) + + actorMsg := make([]byte, 20) + rand.Read(actorMsg) + + addr, err := NewActorAddress(actorMsg) + assert.NoError(err) + assert.Equal(Actor, addr.Protocol()) + + str, err := encode(Mainnet, addr) + assert.NoError(err) + + maybe, err := decode(str) + assert.NoError(err) + assert.Equal(addr, maybe) + +} + +func TestVectorActorAddress(t *testing.T) { + testCases := []struct { + input []byte + expected string + }{ + {[]byte{118, 18, 129, 144, 205, 240, 104, 209, 65, 128, 68, 172, 192, + 62, 11, 103, 129, 151, 13, 96}, + "t24vg6ut43yw2h2jqydgbg2xq7x6f4kub3bg6as6i"}, + {[]byte{44, 175, 184, 226, 224, 107, 186, 152, 234, 101, 124, 92, 245, + 244, 32, 35, 170, 35, 232, 142}, + "t25nml2cfbljvn4goqtclhifepvfnicv6g7mfmmvq"}, + {[]byte{2, 44, 158, 14, 162, 157, 143, 64, 197, 106, 190, 195, 92, 141, + 88, 125, 160, 166, 76, 24}, + "t2nuqrg7vuysaue2pistjjnt3fadsdzvyuatqtfei"}, + {[]byte{223, 236, 3, 14, 32, 79, 15, 89, 216, 15, 29, 94, 233, 29, 253, + 6, 109, 127, 99, 189}, + "t24dd4ox4c2vpf5vk5wkadgyyn6qtuvgcpxxon64a"}, + {[]byte{61, 58, 137, 232, 221, 171, 84, 120, 50, 113, 108, 109, 70, 140, + 53, 96, 201, 244, 127, 216}, + "t2gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr23y"}, + } + + for _, tc := range testCases { + tc := tc + t.Run(fmt.Sprintf("testing Actor address: %s", tc.expected), func(t *testing.T) { + assert := assert.New(t) + + // Round trip encoding and decoding from string + addr, err := NewActorAddress(tc.input) + assert.NoError(err) + assert.Equal(tc.expected, addr.String()) + + maybeAddr, err := NewFromString(tc.expected) + assert.NoError(err) + assert.Equal(Actor, maybeAddr.Protocol()) + assert.Equal(addressHash(tc.input), maybeAddr.Payload()) + + // Round trip to and from bytes + maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes()) + assert.NoError(err) + assert.Equal(maybeAddr, maybeAddrBytes) + + // Round trip encoding and decoding json + b, err := addr.MarshalJSON() + assert.NoError(err) + + var newAddr Address + err = newAddr.UnmarshalJSON(b) + assert.NoError(err) + assert.Equal(addr, newAddr) + }) + } +} + +func TestRandomBLSAddress(t *testing.T) { + assert := assert.New(t) + + pk := ffi.PrivateKeyPublicKey(ffi.PrivateKeyGenerate()) + + addr, err := NewBLSAddress(pk[:]) + assert.NoError(err) + assert.Equal(BLS, addr.Protocol()) + + str, err := encode(Mainnet, addr) + assert.NoError(err) + + maybe, err := decode(str) + assert.NoError(err) + assert.Equal(addr, maybe) + +} + +func TestVectorBLSAddress(t *testing.T) { + testCases := []struct { + input []byte + expected string + }{ + {[]byte{173, 88, 223, 105, 110, 45, 78, 145, 234, 134, 200, 129, 233, 56, + 186, 78, 168, 27, 57, 94, 18, 121, 123, 132, 185, 207, 49, 75, 149, 70, + 112, 94, 131, 156, 122, 153, 214, 6, 178, 71, 221, 180, 249, 172, 122, + 52, 20, 221}, + "t3vvmn62lofvhjd2ugzca6sof2j2ubwok6cj4xxbfzz4yuxfkgobpihhd2thlanmsh3w2ptld2gqkn2jvlss4a"}, + {[]byte{179, 41, 79, 10, 46, 41, 224, 198, 110, 188, 35, 93, 47, 237, + 202, 86, 151, 191, 120, 74, 246, 5, 199, 90, 246, 8, 230, 166, 61, 92, + 211, 142, 168, 92, 168, 152, 158, 14, 253, 233, 24, 139, 56, 47, + 147, 114, 70, 13}, + "t3wmuu6crofhqmm3v4enos73okk2l366ck6yc4owxwbdtkmpk42ohkqxfitcpa57pjdcftql4tojda2poeruwa"}, + {[]byte{150, 161, 163, 228, 234, 122, 20, 212, 153, 133, 230, 97, 178, + 36, 1, 212, 79, 237, 64, 45, 29, 9, 37, 178, 67, 201, 35, 88, 156, + 15, 188, 126, 50, 205, 4, 226, 158, 215, 141, 21, 211, 125, 58, 170, + 63, 230, 218, 51}, + "t3s2q2hzhkpiknjgmf4zq3ejab2rh62qbndueslmsdzervrhapxr7dftie4kpnpdiv2n6tvkr743ndhrsw6d3a"}, + {[]byte{134, 180, 84, 37, 140, 88, 148, 117, 247, 209, 111, 90, 172, 1, + 138, 121, 246, 193, 22, 157, 32, 252, 51, 146, 29, 216, 181, 206, 28, + 172, 108, 52, 143, 144, 163, 96, 54, 36, 246, 174, 185, 27, 100, 81, + 140, 46, 128, 149}, + "t3q22fijmmlckhl56rn5nkyamkph3mcfu5ed6dheq53c244hfmnq2i7efdma3cj5voxenwiummf2ajlsbxc65a"}, + {[]byte{167, 114, 107, 3, 128, 34, 247, 90, 56, 70, 23, 88, 83, 96, 206, + 230, 41, 7, 10, 45, 157, 40, 113, 41, 101, 229, 242, 110, 204, 64, + 133, 131, 130, 128, 55, 36, 237, 52, 242, 114, 3, 54, 240, 157, 182, + 49, 240, 116}, + "t3u5zgwa4ael3vuocgc5mfgygo4yuqocrntuuhcklf4xzg5tcaqwbyfabxetwtj4tsam3pbhnwghyhijr5mixa"}, + } + + for _, tc := range testCases { + tc := tc + t.Run(fmt.Sprintf("testing bls address: %s", tc.expected), func(t *testing.T) { + assert := assert.New(t) + + // Round trip encoding and decoding from string + addr, err := NewBLSAddress(tc.input) + assert.NoError(err) + assert.Equal(tc.expected, addr.String()) + + maybeAddr, err := NewFromString(tc.expected) + assert.NoError(err) + assert.Equal(BLS, maybeAddr.Protocol()) + assert.Equal(tc.input, maybeAddr.Payload()) + + // Round trip to and from bytes + maybeAddrBytes, err := NewFromBytes(maybeAddr.Bytes()) + assert.NoError(err) + assert.Equal(maybeAddr, maybeAddrBytes) + + // Round trip encoding and decoding json + b, err := addr.MarshalJSON() + assert.NoError(err) + + var newAddr Address + err = newAddr.UnmarshalJSON(b) + assert.NoError(err) + assert.Equal(addr, newAddr) + }) + } +} + +func TestInvalidStringAddresses(t *testing.T) { + testCases := []struct { + input string + expetErr error + }{ + {"Q2gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr23y", ErrUnknownNetwork}, + {"t4gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr23y", ErrUnknownProtocol}, + {"t2gfvuyh7v2sx3patm5k23wdzmhyhtmqctasbr24y", ErrInvalidChecksum}, + {"t0banananananannnnnnnnn", ErrInvalidLength}, + {"t0banananananannnnnnnn", ErrInvalidPayload}, + {"t2gfvuyh7v2sx3patm1k23wdzmhyhtmqctasbr24y", base32.CorruptInputError(16)}, // '1' is not in base32 alphabet + {"t2gfvuyh7v2sx3paTm1k23wdzmhyhtmqctasbr24y", base32.CorruptInputError(14)}, // 'T' is not in base32 alphabet + {"t2", ErrInvalidLength}, + } + + for _, tc := range testCases { + tc := tc + t.Run(fmt.Sprintf("testing string address: %s", tc.expetErr), func(t *testing.T) { + assert := assert.New(t) + + _, err := NewFromString(tc.input) + assert.Equal(tc.expetErr, err) + }) + } + +} + +func TestInvalidByteAddresses(t *testing.T) { + testCases := []struct { + input []byte + expetErr error + }{ + // Unknown Protocol + {[]byte{4, 4, 4}, ErrUnknownProtocol}, + + // ID protocol + {[]byte{0}, ErrInvalidLength}, + + // SECP256K1 Protocol + {append([]byte{1}, make([]byte, PayloadHashLength-1)...), ErrInvalidPayload}, + {append([]byte{1}, make([]byte, PayloadHashLength+1)...), ErrInvalidPayload}, + // Actor Protocol + {append([]byte{2}, make([]byte, PayloadHashLength-1)...), ErrInvalidPayload}, + {append([]byte{2}, make([]byte, PayloadHashLength+1)...), ErrInvalidPayload}, + + // BLS Protocol + {append([]byte{3}, make([]byte, ffi.PublicKeyBytes-1)...), ErrInvalidPayload}, + {append([]byte{3}, make([]byte, ffi.PrivateKeyBytes+1)...), ErrInvalidPayload}, + } + + for _, tc := range testCases { + tc := tc + t.Run(fmt.Sprintf("testing byte address: %s", tc.expetErr), func(t *testing.T) { + assert := assert.New(t) + + _, err := NewFromBytes(tc.input) + assert.Equal(tc.expetErr, err) + }) + } + +} + +func TestChecksum(t *testing.T) { + assert := assert.New(t) + + data := []byte("helloworld") + bata := []byte("kittinmittins") + + cksm := Checksum(data) + assert.Len(cksm, ChecksumHashLength) + + assert.True(ValidateChecksum(data, cksm)) + assert.False(ValidateChecksum(bata, cksm)) + +} + +func TestAddressFormat(t *testing.T) { + assert := assert.New(t) + require := require.New(t) + + a, err := NewActorAddress([]byte("hello")) + require.NoError(err) + + assert.Equal("t2wvjry4bx6bwj6kkhcmvgu5zafqyi5cjzbtet3va", a.String()) + assert.Equal("02B5531C7037F06C9F2947132A6A77202C308E8939", fmt.Sprintf("%X", a)) + assert.Equal("[2 - b5531c7037f06c9f2947132a6a77202c308e8939]", fmt.Sprintf("%v", a)) + + assert.Equal("", fmt.Sprintf("%X", Undef)) + assert.Equal(UndefAddressString, Undef.String()) + assert.Equal(UndefAddressString, fmt.Sprintf("%v", Undef)) +} + +func TestCborMarshal(t *testing.T) { + for _, a := range allTestAddresses { + addr, err := NewFromString(a) + if err != nil { + t.Fatal(err) + } + + buf := new(bytes.Buffer) + if err := addr.MarshalCBOR(buf); err != nil { + t.Fatal(err) + } + + /* + // Note: this is commented out because we're currently serializing addresses as cbor "text strings", not "byte strings". + // This is to get around the restriction that refmt only allows string keys in maps. + // if you change it to serialize to byte strings and uncomment this, the tests pass fine + oldbytes, err := cbor.DumpObject(addr) + if err != nil { + t.Fatal(err) + } + + if !bytes.Equal(oldbytes, buf.Bytes()) { + t.Fatalf("serialization doesnt match old serialization: %s", a) + } + */ + + var out Address + if err := out.UnmarshalCBOR(buf); err != nil { + t.Fatal(err) + } + + if out != addr { + t.Fatalf("failed to round trip %s", a) + } + } +} + +func BenchmarkCborMarshal(b *testing.B) { + addr, err := NewFromString("t15ihq5ibzwki2b4ep2f46avlkrqzhpqgtga7pdrq") + if err != nil { + b.Fatal(err) + } + + b.ReportAllocs() + b.ResetTimer() + + buf := new(bytes.Buffer) + for i := 0; i < b.N; i++ { + buf.Reset() + if err := addr.MarshalCBOR(buf); err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkCborUnmarshal(b *testing.B) { + addr, err := NewFromString("t15ihq5ibzwki2b4ep2f46avlkrqzhpqgtga7pdrq") + if err != nil { + b.Fatal(err) + } + + buf := new(bytes.Buffer) + if err := addr.MarshalCBOR(buf); err != nil { + b.Fatal(err) + } + + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + var a Address + if err := a.UnmarshalCBOR(bytes.NewReader(buf.Bytes())); err != nil { + b.Fatal(err) + } + } +} + +func TestIDEdgeCase(t *testing.T) { + a, err := NewFromBytes([]byte{0, 0x80}) + _ = a.String() + assert.Error(t, err) +} diff --git a/shared/address/bench_test.go b/shared/address/bench_test.go new file mode 100644 index 00000000..2c21d549 --- /dev/null +++ b/shared/address/bench_test.go @@ -0,0 +1,94 @@ +package address + +import ( + "fmt" + "math/rand" + + "testing" +) + +func blsaddr(n int64) Address { + buf := make([]byte, 48) + r := rand.New(rand.NewSource(n)) + r.Read(buf) + + addr, err := NewBLSAddress(buf) + if err != nil { + panic(err) // ok + } + + return addr +} + +func makeActorAddresses(n int) [][]byte { + var addrs [][]byte + for i := 0; i < n; i++ { + a, err := NewActorAddress([]byte(fmt.Sprintf("ACTOR ADDRESS %d", i))) + if err != nil { + panic(err) // ok + } + addrs = append(addrs, a.Bytes()) + } + + return addrs +} + +func makeBlsAddresses(n int64) [][]byte { + var addrs [][]byte + for i := int64(0); i < n; i++ { + addrs = append(addrs, blsaddr(n).Bytes()) + } + return addrs +} + +func makeSecpAddresses(n int) [][]byte { + var addrs [][]byte + for i := 0; i < n; i++ { + r := rand.New(rand.NewSource(int64(i))) + buf := make([]byte, 32) + r.Read(buf) + + a, err := NewSecp256k1Address(buf) + if err != nil { + panic(err) // ok + } + + addrs = append(addrs, a.Bytes()) + } + return addrs +} + +func makeIDAddresses(n int) [][]byte { + var addrs [][]byte + for i := 0; i < n; i++ { + + a, err := NewIDAddress(uint64(i)) + if err != nil { + panic(err) // ok + } + + addrs = append(addrs, a.Bytes()) + } + return addrs +} + +func BenchmarkParseActorAddress(b *testing.B) { + benchTestWithAddrs := func(a [][]byte) func(b *testing.B) { + return func(b *testing.B) { + b.ReportAllocs() + b.ResetTimer() + + for i := 0; i < b.N; i++ { + _, err := NewFromBytes(a[i%len(a)]) + if err != nil { + b.Fatal(err) + } + } + } + } + + b.Run("actor", benchTestWithAddrs(makeActorAddresses(20))) + b.Run("bls", benchTestWithAddrs(makeBlsAddresses(20))) + b.Run("secp256k1", benchTestWithAddrs(makeSecpAddresses(20))) + b.Run("id", benchTestWithAddrs(makeIDAddresses(20))) +} diff --git a/shared/address/constants.go b/shared/address/constants.go new file mode 100644 index 00000000..9eabb862 --- /dev/null +++ b/shared/address/constants.go @@ -0,0 +1,65 @@ +package address + +import ( + "encoding/base32" + "errors" + + "github.com/minio/blake2b-simd" +) + +func init() { + + var err error + + TestAddress, err = NewActorAddress([]byte("satoshi")) + if err != nil { + panic(err) + } + + TestAddress2, err = NewActorAddress([]byte("nakamoto")) + if err != nil { + panic(err) + } +} + +var ( + // TestAddress is an account with some initial funds in it. + TestAddress Address + // TestAddress2 is an account with some initial funds in it. + TestAddress2 Address +) + +var ( + // ErrUnknownNetwork is returned when encountering an unknown network in an address. + ErrUnknownNetwork = errors.New("unknown address network") + + // ErrUnknownProtocol is returned when encountering an unknown protocol in an address. + ErrUnknownProtocol = errors.New("unknown address protocol") + // ErrInvalidPayload is returned when encountering an invalid address payload. + ErrInvalidPayload = errors.New("invalid address payload") + // ErrInvalidLength is returned when encountering an address of invalid length. + ErrInvalidLength = errors.New("invalid address length") + // ErrInvalidChecksum is returned when encountering an invalid address checksum. + ErrInvalidChecksum = errors.New("invalid address checksum") +) + +// UndefAddressString is the string used to represent an empty address when encoded to a string. +var UndefAddressString = "" + +// PayloadHashLength defines the hash length taken over addresses using the Actor and SECP256K1 protocols. +const PayloadHashLength = 20 + +// ChecksumHashLength defines the hash length used for calculating address checksums. +const ChecksumHashLength = 4 + +// MaxAddressStringLength is the max length of an address encoded as a string +// it include the network prefx, protocol, and bls publickey +const MaxAddressStringLength = 2 + 84 + +var payloadHashConfig = &blake2b.Config{Size: PayloadHashLength} +var checksumHashConfig = &blake2b.Config{Size: ChecksumHashLength} + +const encodeStd = "abcdefghijklmnopqrstuvwxyz234567" + +// AddressEncoding defines the base32 config used for address encoding and decoding. +var AddressEncoding = base32.NewEncoding(encodeStd) diff --git a/shared/address/testing.go b/shared/address/testing.go new file mode 100644 index 00000000..9bc41376 --- /dev/null +++ b/shared/address/testing.go @@ -0,0 +1,20 @@ +package address + +import ( + "fmt" +) + +// NewForTestGetter returns a closure that returns an address unique to that invocation. +// The address is unique wrt the closure returned, not globally. +func NewForTestGetter() func() Address { + i := 0 + return func() Address { + s := fmt.Sprintf("address%d", i) + i++ + newAddr, err := NewActorAddress([]byte(s)) + if err != nil { + panic(err) + } + return newAddr + } +} diff --git a/shared/cborutil/rpc.go b/shared/cborutil/rpc.go new file mode 100644 index 00000000..06af9a15 --- /dev/null +++ b/shared/cborutil/rpc.go @@ -0,0 +1,80 @@ +package cborutil + +import ( + "bytes" + "encoding/hex" + "io" + "math" + + cbor "github.com/ipfs/go-ipld-cbor" + ipld "github.com/ipfs/go-ipld-format" + logging "github.com/ipfs/go-log" + cbg "github.com/whyrusleeping/cbor-gen" +) + +var log = logging.Logger("cborrrpc") + +const Debug = false + +func init() { + if Debug { + log.Warn("CBOR-RPC Debugging enabled") + } +} + +func WriteCborRPC(w io.Writer, obj interface{}) error { + if m, ok := obj.(cbg.CBORMarshaler); ok { + // TODO: impl debug + return m.MarshalCBOR(w) + } + data, err := cbor.DumpObject(obj) + if err != nil { + return err + } + + if Debug { + log.Infof("> %s", hex.EncodeToString(data)) + } + + _, err = w.Write(data) + return err +} + +func ReadCborRPC(r io.Reader, out interface{}) error { + if um, ok := out.(cbg.CBORUnmarshaler); ok { + return um.UnmarshalCBOR(r) + } + return cbor.DecodeReader(r, out) +} + +func Dump(obj interface{}) ([]byte, error) { + var out bytes.Buffer + if err := WriteCborRPC(&out, obj); err != nil { + return nil, err + } + return out.Bytes(), nil +} + +// TODO: this is a bit ugly, and this package is not exactly the best place +func AsIpld(obj interface{}) (ipld.Node, error) { + if m, ok := obj.(cbg.CBORMarshaler); ok { + b, err := Dump(m) + if err != nil { + return nil, err + } + return cbor.Decode(b, math.MaxUint64, -1) + } + return cbor.WrapObject(obj, math.MaxUint64, -1) +} + +func Equals(a cbg.CBORMarshaler, b cbg.CBORMarshaler) (bool, error) { + ab, err := Dump(a) + if err != nil { + return false, err + } + bb, err := Dump(b) + if err != nil { + return false, err + } + return bytes.Equal(ab, bb), nil +} diff --git a/shared/crypto/crypto.go b/shared/crypto/crypto.go new file mode 100644 index 00000000..977e8ae9 --- /dev/null +++ b/shared/crypto/crypto.go @@ -0,0 +1,70 @@ +package crypto + +import ( + "bytes" + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "io" + + secp256k1 "github.com/ipsn/go-secp256k1" +) + +// PrivateKeyBytes is the size of a serialized private key. +const PrivateKeyBytes = 32 + +// PublicKeyBytes is the size of a serialized public key. +const PublicKeyBytes = 65 + +// PublicKey returns the public key for this private key. +func PublicKey(sk []byte) []byte { + x, y := secp256k1.S256().ScalarBaseMult(sk) + return elliptic.Marshal(secp256k1.S256(), x, y) +} + +// Sign signs the given message, which must be 32 bytes long. +func Sign(sk, msg []byte) ([]byte, error) { + return secp256k1.Sign(msg, sk) +} + +// Equals compares two private key for equality and returns true if they are the same. +func Equals(sk, other []byte) bool { + return bytes.Equal(sk, other) +} + +// Verify checks the given signature and returns true if it is valid. +func Verify(pk, msg, signature []byte) bool { + if len(signature) == 65 { + // Drop the V (1byte) in [R | S | V] style signatures. + // The V (1byte) is the recovery bit and is not apart of the signature verification. + return secp256k1.VerifySignature(pk[:], msg, signature[:len(signature)-1]) + } + + return secp256k1.VerifySignature(pk[:], msg, signature) +} + +// GenerateKeyFromSeed generates a new key from the given reader. +func GenerateKeyFromSeed(seed io.Reader) ([]byte, error) { + key, err := ecdsa.GenerateKey(secp256k1.S256(), seed) + if err != nil { + return nil, err + } + + privkey := make([]byte, PrivateKeyBytes) + blob := key.D.Bytes() + + // the length is guaranteed to be fixed, given the serialization rules for secp2561k curve points. + copy(privkey[PrivateKeyBytes-len(blob):], blob) + + return privkey, nil +} + +// GenerateKey creates a new key using secure randomness from crypto.rand. +func GenerateKey() ([]byte, error) { + return GenerateKeyFromSeed(rand.Reader) +} + +// EcRecover recovers the public key from a message, signature pair. +func EcRecover(msg, signature []byte) ([]byte, error) { + return secp256k1.RecoverPubkey(msg, signature) +} diff --git a/shared/crypto/crypto_test.go b/shared/crypto/crypto_test.go new file mode 100644 index 00000000..5cf25352 --- /dev/null +++ b/shared/crypto/crypto_test.go @@ -0,0 +1,61 @@ +package crypto_test + +import ( + "math/rand" + "testing" + "time" + + "github.com/stretchr/testify/assert" + + "github.com/filecoin-project/go-fil-components/shared/crypto" +) + +func TestGenerateKey(t *testing.T) { + rand.Seed(time.Now().UnixNano()) + + sk, err := crypto.GenerateKey() + assert.NoError(t, err) + + assert.Equal(t, len(sk), 32) + + msg := make([]byte, 32) + for i := 0; i < len(msg); i++ { + msg[i] = byte(i) + } + + digest, err := crypto.Sign(sk, msg) + assert.NoError(t, err) + assert.Equal(t, len(digest), 65) + pk := crypto.PublicKey(sk) + + // valid signature + assert.True(t, crypto.Verify(pk, msg, digest)) + + // invalid signature - different message (too short) + assert.False(t, crypto.Verify(pk, msg[3:], digest)) + + // invalid signature - different message + msg2 := make([]byte, 32) + copy(msg2, msg) + rand.Shuffle(len(msg2), func(i, j int) { msg2[i], msg2[j] = msg2[j], msg2[i] }) + assert.False(t, crypto.Verify(pk, msg2, digest)) + + // invalid signature - different digest + digest2 := make([]byte, 65) + copy(digest2, digest) + rand.Shuffle(len(digest2), func(i, j int) { digest2[i], digest2[j] = digest2[j], digest2[i] }) + assert.False(t, crypto.Verify(pk, msg, digest2)) + + // invalid signature - digest too short + assert.False(t, crypto.Verify(pk, msg, digest[3:])) + assert.False(t, crypto.Verify(pk, msg, digest[:29])) + + // invalid signature - digest too long + digest3 := make([]byte, 70) + copy(digest3, digest) + assert.False(t, crypto.Verify(pk, msg, digest3)) + + recovered, err := crypto.EcRecover(msg, digest) + assert.NoError(t, err) + assert.Equal(t, recovered, crypto.PublicKey(sk)) +} diff --git a/shared/params/params_shared.go b/shared/params/params_shared.go new file mode 100644 index 00000000..31f2f255 --- /dev/null +++ b/shared/params/params_shared.go @@ -0,0 +1,46 @@ +package params + +import ( + "math/big" +) + +// Core network constants + +// ///// +// Storage + +const UnixfsChunkSize uint64 = 1 << 20 +const UnixfsLinksPerLevel = 1024 + +// ///// +// Devnet settings + +const TotalFilecoin = 2_000_000_000 +const MiningRewardTotal = 1_400_000_000 + +const InitialRewardStr = "153856861913558700202" + +var InitialReward *big.Int + +const FilecoinPrecision = 1_000_000_000_000_000_000 + +// six years +// Epochs +const HalvingPeriodEpochs = 6 * 365 * 24 * 60 * 2 + +// TODO: Move other important consts here + +func init() { + InitialReward = new(big.Int) + + var ok bool + InitialReward, ok = InitialReward. + SetString(InitialRewardStr, 10) + if !ok { + panic("could not parse InitialRewardStr") + } +} + +// assuming 4000 messages per round, this lets us not lose any messages across a +// 10 block reorg. +const BlsSignatureCacheSize = 40000 diff --git a/shared/tokenamount/tokenamount.go b/shared/tokenamount/tokenamount.go new file mode 100644 index 00000000..bd910b24 --- /dev/null +++ b/shared/tokenamount/tokenamount.go @@ -0,0 +1,271 @@ +package tokenamount + +import ( + "encoding/json" + "fmt" + "io" + "math/big" + "strings" + + "github.com/filecoin-project/go-fil-components/shared/params" + cbor "github.com/ipfs/go-ipld-cbor" + "github.com/polydawn/refmt/obj/atlas" + + cbg "github.com/whyrusleeping/cbor-gen" + "golang.org/x/xerrors" +) + +const BigIntMaxSerializedLen = 128 // is this big enough? or too big? + +var TotalFilecoinInt = FromFil(params.TotalFilecoin) + +func init() { + cbor.RegisterCborType(atlas.BuildEntry(TokenAmount{}).Transform(). + TransformMarshal(atlas.MakeMarshalTransformFunc( + func(i TokenAmount) ([]byte, error) { + return i.cborBytes(), nil + })). + TransformUnmarshal(atlas.MakeUnmarshalTransformFunc( + func(x []byte) (TokenAmount, error) { + return fromCborBytes(x) + })). + Complete()) +} + +var EmptyInt = TokenAmount{} + +type TokenAmount struct { + *big.Int +} + +func NewInt(i uint64) TokenAmount { + return TokenAmount{big.NewInt(0).SetUint64(i)} +} + +func FromFil(i uint64) TokenAmount { + return BigMul(NewInt(i), NewInt(params.FilecoinPrecision)) +} + +func BigFromBytes(b []byte) TokenAmount { + i := big.NewInt(0).SetBytes(b) + return TokenAmount{i} +} + +func BigFromString(s string) (TokenAmount, error) { + v, ok := big.NewInt(0).SetString(s, 10) + if !ok { + return TokenAmount{}, fmt.Errorf("failed to parse string as a big int") + } + + return TokenAmount{v}, nil +} + +func BigMul(a, b TokenAmount) TokenAmount { + return TokenAmount{big.NewInt(0).Mul(a.Int, b.Int)} +} + +func BigDiv(a, b TokenAmount) TokenAmount { + return TokenAmount{big.NewInt(0).Div(a.Int, b.Int)} +} + +func BigMod(a, b TokenAmount) TokenAmount { + return TokenAmount{big.NewInt(0).Mod(a.Int, b.Int)} +} + +func BigAdd(a, b TokenAmount) TokenAmount { + return TokenAmount{big.NewInt(0).Add(a.Int, b.Int)} +} + +func BigSub(a, b TokenAmount) TokenAmount { + return TokenAmount{big.NewInt(0).Sub(a.Int, b.Int)} +} + +func BigCmp(a, b TokenAmount) int { + return a.Int.Cmp(b.Int) +} + +func (bi TokenAmount) Nil() bool { + return bi.Int == nil +} + +// LessThan returns true if bi < o +func (bi TokenAmount) LessThan(o TokenAmount) bool { + return BigCmp(bi, o) < 0 +} + +// GreaterThan returns true if bi > o +func (bi TokenAmount) GreaterThan(o TokenAmount) bool { + return BigCmp(bi, o) > 0 +} + +// Equals returns true if bi == o +func (bi TokenAmount) Equals(o TokenAmount) bool { + return BigCmp(bi, o) == 0 +} + +func (bi *TokenAmount) MarshalJSON() ([]byte, error) { + return json.Marshal(bi.String()) +} + +func (bi *TokenAmount) UnmarshalJSON(b []byte) error { + var s string + if err := json.Unmarshal(b, &s); err != nil { + return err + } + + i, ok := big.NewInt(0).SetString(s, 10) + if !ok { + if string(s) == "" { + return nil + } + return xerrors.Errorf("failed to parse bigint string: '%s'", string(b)) + } + + bi.Int = i + return nil +} + +func (bi *TokenAmount) Scan(value interface{}) error { + switch value := value.(type) { + case string: + i, ok := big.NewInt(0).SetString(value, 10) + if !ok { + if value == "" { + return nil + } + return xerrors.Errorf("failed to parse bigint string: '%s'", value) + } + + bi.Int = i + + return nil + case int64: + bi.Int = big.NewInt(value) + return nil + default: + return xerrors.Errorf("non-string types unsupported: %T", value) + } +} + +func (bi *TokenAmount) cborBytes() []byte { + if bi.Int == nil { + return []byte{} + } + + switch { + case bi.Sign() > 0: + return append([]byte{0}, bi.Bytes()...) + case bi.Sign() < 0: + return append([]byte{1}, bi.Bytes()...) + default: // bi.Sign() == 0: + return []byte{} + } +} + +func fromCborBytes(buf []byte) (TokenAmount, error) { + if len(buf) == 0 { + return NewInt(0), nil + } + + var negative bool + switch buf[0] { + case 0: + negative = false + case 1: + negative = true + default: + return EmptyInt, fmt.Errorf("big int prefix should be either 0 or 1, got %d", buf[0]) + } + + i := big.NewInt(0).SetBytes(buf[1:]) + if negative { + i.Neg(i) + } + + return TokenAmount{i}, nil +} + +func (bi *TokenAmount) MarshalCBOR(w io.Writer) error { + if bi.Int == nil { + zero := NewInt(0) + return zero.MarshalCBOR(w) + } + + enc := bi.cborBytes() + + header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(enc))) + if _, err := w.Write(header); err != nil { + return err + } + + if _, err := w.Write(enc); err != nil { + return err + } + + return nil +} + +func (bi *TokenAmount) UnmarshalCBOR(br io.Reader) error { + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + + if maj != cbg.MajByteString { + return fmt.Errorf("cbor input for fil big int was not a byte string (%x)", maj) + } + + if extra == 0 { + bi.Int = big.NewInt(0) + return nil + } + + if extra > BigIntMaxSerializedLen { + return fmt.Errorf("big integer byte array too long") + } + + buf := make([]byte, extra) + if _, err := io.ReadFull(br, buf); err != nil { + return err + } + + i, err := fromCborBytes(buf) + if err != nil { + return err + } + + *bi = i + + return nil +} + +func (f TokenAmount) String() string { + r := new(big.Rat).SetFrac(f.Int, big.NewInt(params.FilecoinPrecision)) + if r.Sign() == 0 { + return "0" + } + return strings.TrimRight(strings.TrimRight(r.FloatString(18), "0"), ".") +} + +func (f TokenAmount) Format(s fmt.State, ch rune) { + switch ch { + case 's', 'v': + fmt.Fprint(s, f.String()) + default: + f.Int.Format(s, ch) + } +} + +func ParseTokenAmount(s string) (TokenAmount, error) { + r, ok := new(big.Rat).SetString(s) + if !ok { + return TokenAmount{}, fmt.Errorf("failed to parse %q as a decimal number", s) + } + + r = r.Mul(r, big.NewRat(params.FilecoinPrecision, 1)) + if !r.IsInt() { + return TokenAmount{}, fmt.Errorf("invalid FIL value: %q", s) + } + + return TokenAmount{r.Num()}, nil +} diff --git a/shared/tokenamount/tokenamount_test.go b/shared/tokenamount/tokenamount_test.go new file mode 100644 index 00000000..87b7fcef --- /dev/null +++ b/shared/tokenamount/tokenamount_test.go @@ -0,0 +1,51 @@ +package tokenamount + +import ( + "bytes" + "testing" +) + +func TestBigIntSerializationRoundTrip(t *testing.T) { + testValues := []string{ + "0", "1", "10", "-10", "9999", "12345678901234567891234567890123456789012345678901234567890", + } + + for _, v := range testValues { + bi, err := BigFromString(v) + if err != nil { + t.Fatal(err) + } + + buf := new(bytes.Buffer) + if err := bi.MarshalCBOR(buf); err != nil { + t.Fatal(err) + } + + var out TokenAmount + if err := out.UnmarshalCBOR(buf); err != nil { + t.Fatal(err) + } + + if BigCmp(out, bi) != 0 { + t.Fatal("failed to round trip BigInt through cbor") + } + + } +} + +func TestFilRoundTrip(t *testing.T) { + testValues := []string{ + "0", "1", "1.001", "100.10001", "101100", "5000.01", "5000", + } + + for _, v := range testValues { + fval, err := ParseTokenAmount(v) + if err != nil { + t.Fatal(err) + } + + if fval.String() != v { + t.Fatal("mismatch in values!", v, fval.String()) + } + } +} diff --git a/shared/types/signature.go b/shared/types/signature.go new file mode 100644 index 00000000..5394e9be --- /dev/null +++ b/shared/types/signature.go @@ -0,0 +1,123 @@ +package types + +import ( + "bytes" + "encoding/binary" + "fmt" + logging "github.com/ipfs/go-log" + "io" + + cbg "github.com/whyrusleeping/cbor-gen" +) + +var log = logging.Logger("types") + +const SignatureMaxLength = 200 + +const ( + KTSecp256k1 = "secp256k1" + KTBLS = "bls" +) + +const ( + IKTUnknown = -1 + + IKTSecp256k1 = iota + IKTBLS +) + +type Signature struct { + Type string + Data []byte +} + +func SignatureFromBytes(x []byte) (Signature, error) { + val, nr := binary.Uvarint(x) + if nr != 1 { + return Signature{}, fmt.Errorf("signatures with type field longer than one byte are invalid") + } + var ts string + switch val { + case IKTSecp256k1: + ts = KTSecp256k1 + case IKTBLS: + ts = KTBLS + default: + return Signature{}, fmt.Errorf("unsupported signature type: %d", val) + } + + return Signature{ + Type: ts, + Data: x[1:], + }, nil +} + +func (s *Signature) TypeCode() int { + switch s.Type { + case KTSecp256k1: + return IKTSecp256k1 + case KTBLS: + return IKTBLS + default: + return IKTUnknown + } +} + +func (s *Signature) MarshalCBOR(w io.Writer) error { + if s == nil { + _, err := w.Write(cbg.CborNull) + return err + } + + header := cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(s.Data)+1)) + + if _, err := w.Write(header); err != nil { + return err + } + + if _, err := w.Write([]byte{byte(s.TypeCode())}); err != nil { + return err + } + + if _, err := w.Write(s.Data); err != nil { + return err + } + + return nil +} + +func (s *Signature) UnmarshalCBOR(br io.Reader) error { + maj, l, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + + if maj != cbg.MajByteString { + return fmt.Errorf("cbor input for signature was not a byte string") + } + + if l > SignatureMaxLength { + return fmt.Errorf("cbor byte array for signature was too long") + } + + buf := make([]byte, l) + if _, err := io.ReadFull(br, buf); err != nil { + return err + } + + switch buf[0] { + default: + return fmt.Errorf("invalid signature type in cbor input: %d", buf[0]) + case IKTSecp256k1: + s.Type = KTSecp256k1 + case IKTBLS: + s.Type = KTBLS + } + s.Data = buf[1:] + + return nil +} + +func (s *Signature) Equals(o *Signature) bool { + return s.Type == o.Type && bytes.Equal(s.Data, o.Data) +} diff --git a/shared/types/signature_cgo.go b/shared/types/signature_cgo.go new file mode 100644 index 00000000..f01b79d2 --- /dev/null +++ b/shared/types/signature_cgo.go @@ -0,0 +1,55 @@ +//+build cgo + +package types + +import ( + "fmt" + + bls "github.com/filecoin-project/filecoin-ffi" + "github.com/filecoin-project/go-fil-components/shared/address" + "github.com/filecoin-project/go-fil-components/shared/crypto" + "github.com/minio/blake2b-simd" +) + +func (s *Signature) Verify(addr address.Address, msg []byte) error { + if addr.Protocol() == address.ID { + return fmt.Errorf("must resolve ID addresses before using them to verify a signature") + } + b2sum := blake2b.Sum256(msg) + + switch s.Type { + case KTSecp256k1: + pubk, err := crypto.EcRecover(b2sum[:], s.Data) + if err != nil { + return err + } + + maybeaddr, err := address.NewSecp256k1Address(pubk) + if err != nil { + return err + } + + if addr != maybeaddr { + return fmt.Errorf("signature did not match") + } + + return nil + case KTBLS: + digests := []bls.Digest{bls.Hash(bls.Message(msg))} + + var pubk bls.PublicKey + copy(pubk[:], addr.Payload()) + pubkeys := []bls.PublicKey{pubk} + + var sig bls.Signature + copy(sig[:], s.Data) + + if !bls.Verify(&sig, digests, pubkeys) { + return fmt.Errorf("bls signature failed to verify") + } + + return nil + default: + return fmt.Errorf("cannot verify signature of unsupported type: %s", s.Type) + } +} diff --git a/shared/types/signature_test.go b/shared/types/signature_test.go new file mode 100644 index 00000000..b45024b2 --- /dev/null +++ b/shared/types/signature_test.go @@ -0,0 +1,27 @@ +package types + +import ( + "bytes" + "testing" +) + +func TestSignatureSerializeRoundTrip(t *testing.T) { + s := &Signature{ + Data: []byte("foo bar cat dog"), + Type: KTBLS, + } + + buf := new(bytes.Buffer) + if err := s.MarshalCBOR(buf); err != nil { + t.Fatal(err) + } + + var outs Signature + if err := outs.UnmarshalCBOR(buf); err != nil { + t.Fatal(err) + } + + if !outs.Equals(s) { + t.Fatal("serialization round trip failed") + } +} diff --git a/shared/types/voucher.go b/shared/types/voucher.go new file mode 100644 index 00000000..ac628a31 --- /dev/null +++ b/shared/types/voucher.go @@ -0,0 +1,91 @@ +package types + +import ( + "bytes" + "encoding/base64" + + "github.com/filecoin-project/go-fil-components/shared/address" + cborrpc "github.com/filecoin-project/go-fil-components/shared/cborutil" + "github.com/filecoin-project/go-fil-components/shared/tokenamount" + cbor "github.com/ipfs/go-ipld-cbor" +) + +//go:generate cbor-gen-for SignedVoucher ModVerifyParams Merge + +type SignedVoucher struct { + TimeLock uint64 + SecretPreimage []byte + Extra *ModVerifyParams + Lane uint64 + Nonce uint64 + Amount tokenamount.TokenAmount + MinCloseHeight uint64 + + Merges []Merge + + Signature *Signature +} + +func (sv *SignedVoucher) SigningBytes() ([]byte, error) { + osv := *sv + osv.Signature = nil + + buf := new(bytes.Buffer) + //if err := osv.MarshalCBOR(buf); err != nil { + // return nil, err + //} + + return buf.Bytes(), nil +} + +func (sv *SignedVoucher) EncodedString() (string, error) { + buf := new(bytes.Buffer) + if err := sv.MarshalCBOR(buf); err != nil { + return "", err + } + + return base64.RawURLEncoding.EncodeToString(buf.Bytes()), nil +} + +func (sv *SignedVoucher) Equals(other *SignedVoucher) bool { + // TODO: make this less bad + + selfB, err := cborrpc.Dump(sv) + if err != nil { + log.Errorf("SignedVoucher.Equals: dump self: %s", err) + return false + } + + otherB, err := cborrpc.Dump(other) + if err != nil { + log.Errorf("SignedVoucher.Equals: dump other: %s", err) + return false + } + + return bytes.Equal(selfB, otherB) +} + +func DecodeSignedVoucher(s string) (*SignedVoucher, error) { + data, err := base64.RawURLEncoding.DecodeString(s) + if err != nil { + return nil, err + } + + var sv SignedVoucher + if err := cbor.DecodeInto(data, &sv); err != nil { + return nil, err + } + + return &sv, nil +} + +type Merge struct { + Lane uint64 + Nonce uint64 +} + +type ModVerifyParams struct { + Actor address.Address + Method uint64 + Data []byte +} diff --git a/shared/types/voucher_cbor_gen.go b/shared/types/voucher_cbor_gen.go new file mode 100644 index 00000000..2d0f84e7 --- /dev/null +++ b/shared/types/voucher_cbor_gen.go @@ -0,0 +1,372 @@ +package types + +import ( + "fmt" + "io" + + cbg "github.com/whyrusleeping/cbor-gen" + xerrors "golang.org/x/xerrors" +) + +// Code generated by github.com/whyrusleeping/cbor-gen. DO NOT EDIT. + +var _ = xerrors.Errorf + +func (t *SignedVoucher) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{137}); err != nil { + return err + } + + // t.TimeLock (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.TimeLock))); err != nil { + return err + } + + // t.SecretPreimage ([]uint8) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.SecretPreimage)))); err != nil { + return err + } + if _, err := w.Write(t.SecretPreimage); err != nil { + return err + } + + // t.Extra (types.ModVerifyParams) (struct) + if err := t.Extra.MarshalCBOR(w); err != nil { + return err + } + + // t.Lane (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Lane))); err != nil { + return err + } + + // t.Nonce (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Nonce))); err != nil { + return err + } + + // t.Amount (tokenamount.TokenAmount) (struct) + if err := t.Amount.MarshalCBOR(w); err != nil { + return err + } + + // t.MinCloseHeight (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.MinCloseHeight))); err != nil { + return err + } + + // t.Merges ([]types.Merge) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajArray, uint64(len(t.Merges)))); err != nil { + return err + } + for _, v := range t.Merges { + if err := v.MarshalCBOR(w); err != nil { + return err + } + } + + // t.Signature (types.Signature) (struct) + if err := t.Signature.MarshalCBOR(w); err != nil { + return err + } + return nil +} + +func (t *SignedVoucher) UnmarshalCBOR(r io.Reader) error { + br := cbg.GetPeeker(r) + + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 9 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.TimeLock (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.TimeLock = uint64(extra) + // t.SecretPreimage ([]uint8) (slice) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.SecretPreimage: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + t.SecretPreimage = make([]byte, extra) + if _, err := io.ReadFull(br, t.SecretPreimage); err != nil { + return err + } + // t.Extra (types.ModVerifyParams) (struct) + + { + + pb, err := br.PeekByte() + if err != nil { + return err + } + if pb == cbg.CborNull[0] { + var nbuf [1]byte + if _, err := br.Read(nbuf[:]); err != nil { + return err + } + } else { + t.Extra = new(ModVerifyParams) + if err := t.Extra.UnmarshalCBOR(br); err != nil { + return err + } + } + + } + // t.Lane (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.Lane = uint64(extra) + // t.Nonce (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.Nonce = uint64(extra) + // t.Amount (tokenamount.TokenAmount) (struct) + + { + + if err := t.Amount.UnmarshalCBOR(br); err != nil { + return err + } + + } + // t.MinCloseHeight (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.MinCloseHeight = uint64(extra) + // t.Merges ([]types.Merge) (slice) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + + if extra > cbg.MaxLength { + return fmt.Errorf("t.Merges: array too large (%d)", extra) + } + + if maj != cbg.MajArray { + return fmt.Errorf("expected cbor array") + } + if extra > 0 { + t.Merges = make([]Merge, extra) + } + for i := 0; i < int(extra); i++ { + + var v Merge + if err := v.UnmarshalCBOR(br); err != nil { + return err + } + + t.Merges[i] = v + } + + // t.Signature (types.Signature) (struct) + + { + + pb, err := br.PeekByte() + if err != nil { + return err + } + if pb == cbg.CborNull[0] { + var nbuf [1]byte + if _, err := br.Read(nbuf[:]); err != nil { + return err + } + } else { + t.Signature = new(Signature) + if err := t.Signature.UnmarshalCBOR(br); err != nil { + return err + } + } + + } + return nil +} + +func (t *ModVerifyParams) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{131}); err != nil { + return err + } + + // t.Actor (address.Address) (struct) + if err := t.Actor.MarshalCBOR(w); err != nil { + return err + } + + // t.Method (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Method))); err != nil { + return err + } + + // t.Data ([]uint8) (slice) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajByteString, uint64(len(t.Data)))); err != nil { + return err + } + if _, err := w.Write(t.Data); err != nil { + return err + } + return nil +} + +func (t *ModVerifyParams) UnmarshalCBOR(r io.Reader) error { + br := cbg.GetPeeker(r) + + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 3 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Actor (address.Address) (struct) + + { + + if err := t.Actor.UnmarshalCBOR(br); err != nil { + return err + } + + } + // t.Method (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.Method = uint64(extra) + // t.Data ([]uint8) (slice) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + + if extra > cbg.ByteArrayMaxLen { + return fmt.Errorf("t.Data: byte array too large (%d)", extra) + } + if maj != cbg.MajByteString { + return fmt.Errorf("expected byte array") + } + t.Data = make([]byte, extra) + if _, err := io.ReadFull(br, t.Data); err != nil { + return err + } + return nil +} + +func (t *Merge) MarshalCBOR(w io.Writer) error { + if t == nil { + _, err := w.Write(cbg.CborNull) + return err + } + if _, err := w.Write([]byte{130}); err != nil { + return err + } + + // t.Lane (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Lane))); err != nil { + return err + } + + // t.Nonce (uint64) (uint64) + if _, err := w.Write(cbg.CborEncodeMajorType(cbg.MajUnsignedInt, uint64(t.Nonce))); err != nil { + return err + } + return nil +} + +func (t *Merge) UnmarshalCBOR(r io.Reader) error { + br := cbg.GetPeeker(r) + + maj, extra, err := cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajArray { + return fmt.Errorf("cbor input should be of type array") + } + + if extra != 2 { + return fmt.Errorf("cbor input had wrong number of fields") + } + + // t.Lane (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.Lane = uint64(extra) + // t.Nonce (uint64) (uint64) + + maj, extra, err = cbg.CborReadHeader(br) + if err != nil { + return err + } + if maj != cbg.MajUnsignedInt { + return fmt.Errorf("wrong type for uint64 field") + } + t.Nonce = uint64(extra) + return nil +} diff --git a/tools.go b/tools.go new file mode 100644 index 00000000..51b8ceae --- /dev/null +++ b/tools.go @@ -0,0 +1,7 @@ +// +build tools + +package tools + +import ( + _ "github.com/hannahhoward/cbor-gen-for" +)