Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/commands/bitswap.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Print out all blocks currently on the bitswap wantlist for the local peer.`,
},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *KeyList) error {
enc, err := cmdenv.GetLowLevelCidEncoder(req)
enc, err := cmdenv.GetCidEncoder(req)
if err != nil {
return err
}
Expand Down Expand Up @@ -128,7 +128,7 @@ var bitswapStatCmd = &cmds.Command{
},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, s *bitswap.Stat) error {
enc, err := cmdenv.GetLowLevelCidEncoder(req)
enc, err := cmdenv.GetCidEncoder(req)
if err != nil {
return err
}
Expand Down
23 changes: 19 additions & 4 deletions core/commands/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ on raw IPFS blocks. It outputs the following to stdout:
return err
}

enc, err := cmdenv.GetCidEncoder(req)
if err != nil {
return err
}

p, err := cmdutils.PathOrCidPath(req.Arguments[0])
if err != nil {
return err
Expand All @@ -78,7 +83,7 @@ on raw IPFS blocks. It outputs the following to stdout:
}

return cmds.EmitOnce(res, &BlockStat{
Key: b.Path().RootCid().String(),
Key: enc.Encode(b.Path().RootCid()),
Size: b.Size(),
})
},
Expand Down Expand Up @@ -171,6 +176,11 @@ only for backward compatibility when a legacy CIDv0 is required (--format=v0).
return err
}

enc, err := cmdenv.GetCidEncoder(req)
if err != nil {
return err
}

nd, err := cmdenv.GetNode(env)
if err != nil {
return err
Expand Down Expand Up @@ -230,7 +240,7 @@ only for backward compatibility when a legacy CIDv0 is required (--format=v0).
}

err = res.Emit(&BlockStat{
Key: p.Path().RootCid().String(),
Key: enc.Encode(p.Path().RootCid()),
Size: p.Size(),
})
if err != nil {
Expand Down Expand Up @@ -280,6 +290,11 @@ It takes a list of CIDs to remove from the local datastore..
return err
}

enc, err := cmdenv.GetCidEncoder(req)
if err != nil {
return err
}

force, _ := req.Options[forceOptionName].(bool)
quiet, _ := req.Options[blockQuietOptionName].(bool)

Expand All @@ -298,7 +313,7 @@ It takes a list of CIDs to remove from the local datastore..
err = api.Block().Rm(req.Context, rp, options.Block.Force(force))
if err != nil {
if err := res.Emit(&removedBlock{
Hash: rp.RootCid().String(),
Hash: enc.Encode(rp.RootCid()),
Error: err.Error(),
}); err != nil {
return err
Expand All @@ -308,7 +323,7 @@ It takes a list of CIDs to remove from the local datastore..

if !quiet {
err := res.Emit(&removedBlock{
Hash: rp.RootCid().String(),
Hash: enc.Encode(rp.RootCid()),
})
if err != nil {
return err
Expand Down
33 changes: 17 additions & 16 deletions core/commands/cmdenv/cidbase.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,20 @@ import (
)

var (
OptionCidBase = cmds.StringOption("cid-base", "Multibase encoding used for version 1 CIDs in output.")
OptionUpgradeCidV0InOutput = cmds.BoolOption("upgrade-cidv0-in-output", "Upgrade version 0 to version 1 CIDs in output.")
OptionCidBase = cmds.StringOption("cid-base", "Multibase encoding for CIDs in output. CIDv0 is automatically converted to CIDv1 when a base other than base58btc is specified.")

// OptionUpgradeCidV0InOutput is deprecated. When --cid-base is set to
// anything other than base58btc, CIDv0 are now automatically upgraded
// to CIDv1. This flag is kept for backward compatibility and will be
// removed in a future release.
OptionUpgradeCidV0InOutput = cmds.BoolOption("upgrade-cidv0-in-output", "[DEPRECATED] Upgrade version 0 to version 1 CIDs in output.")
)

// GetCidEncoder processes the `cid-base` and `output-cidv1` options and
// returns an encoder to use based on those parameters.
// GetCidEncoder processes the --cid-base option and returns an encoder.
// When --cid-base is set to a non-base58btc encoding, CIDv0 values are
// automatically upgraded to CIDv1 because CIDv0 can only be represented
// in base58btc.
func GetCidEncoder(req *cmds.Request) (cidenc.Encoder, error) {
return getCidBase(req, true)
}

// GetLowLevelCidEncoder is like GetCidEncoder but meant to be used by lower
// level commands. It differs from GetCidEncoder in that CIDv0 are not, by
// default, auto-upgraded to CIDv1.
func GetLowLevelCidEncoder(req *cmds.Request) (cidenc.Encoder, error) {
return getCidBase(req, false)
}

func getCidBase(req *cmds.Request, autoUpgrade bool) (cidenc.Encoder, error) {
base, _ := req.Options[OptionCidBase.Name()].(string)
upgrade, upgradeDefined := req.Options[OptionUpgradeCidV0InOutput.Name()].(bool)

Expand All @@ -40,11 +36,16 @@ func getCidBase(req *cmds.Request, autoUpgrade bool) (cidenc.Encoder, error) {
if err != nil {
return e, err
}
if autoUpgrade {
// CIDv0 can only be represented in base58btc. When any other
// base is requested, always upgrade CIDv0 to CIDv1 so the
// output actually uses the requested encoding.
if e.Base.Encoding() != mbase.Base58BTC {
e.Upgrade = true
}
}

// Deprecated: --upgrade-cidv0-in-output still works as an explicit
// override for backward compatibility.
if upgradeDefined {
e.Upgrade = upgrade
}
Expand Down
73 changes: 73 additions & 0 deletions core/commands/cmdenv/cidbase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,82 @@ import (
"testing"

cidenc "github.com/ipfs/go-cidutil/cidenc"
cmds "github.com/ipfs/go-ipfs-cmds"
mbase "github.com/multiformats/go-multibase"
)

func TestGetCidEncoder(t *testing.T) {
makeReq := func(opts map[string]any) *cmds.Request {
if opts == nil {
opts = map[string]any{}
}
return &cmds.Request{Options: opts}
}

t.Run("no options returns default encoder", func(t *testing.T) {
enc, err := GetCidEncoder(makeReq(nil))
if err != nil {
t.Fatal(err)
}
if enc.Upgrade {
t.Error("expected Upgrade=false with no options")
}
})

t.Run("non-base58btc base auto-upgrades CIDv0", func(t *testing.T) {
enc, err := GetCidEncoder(makeReq(map[string]any{
"cid-base": "base32",
}))
if err != nil {
t.Fatal(err)
}
if !enc.Upgrade {
t.Error("expected Upgrade=true for base32")
}
if enc.Base.Encoding() != mbase.Base32 {
t.Errorf("expected base32 encoding, got %v", enc.Base.Encoding())
}
})

t.Run("base58btc does not auto-upgrade", func(t *testing.T) {
enc, err := GetCidEncoder(makeReq(map[string]any{
"cid-base": "base58btc",
}))
if err != nil {
t.Fatal(err)
}
if enc.Upgrade {
t.Error("expected Upgrade=false for base58btc")
}
})

t.Run("deprecated flag still works as override", func(t *testing.T) {
// Explicitly disable upgrade even with non-base58btc base
enc, err := GetCidEncoder(makeReq(map[string]any{
"cid-base": "base32",
"upgrade-cidv0-in-output": false,
}))
if err != nil {
t.Fatal(err)
}
if enc.Upgrade {
t.Error("expected Upgrade=false when explicitly disabled")
}

// Explicitly enable upgrade even with base58btc
enc, err = GetCidEncoder(makeReq(map[string]any{
"cid-base": "base58btc",
"upgrade-cidv0-in-output": true,
}))
if err != nil {
t.Fatal(err)
}
if !enc.Upgrade {
t.Error("expected Upgrade=true when explicitly enabled")
}
})
}

func TestEncoderFromPath(t *testing.T) {
test := func(path string, expected cidenc.Encoder) {
actual, err := CidEncoderFromPath(path)
Expand Down
63 changes: 14 additions & 49 deletions core/commands/dag/dag.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ into an object of the specified format.
Type: OutputObject{},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *OutputObject) error {
enc, err := cmdenv.GetLowLevelCidEncoder(req)
enc, err := cmdenv.GetCidEncoder(req)
if err != nil {
return err
}
Expand Down Expand Up @@ -153,7 +153,7 @@ var DagResolveCmd = &cmds.Command{
// Nope, fallback on the default.
fallthrough
default:
enc, err = cmdenv.GetLowLevelCidEncoder(req)
enc, err = cmdenv.GetCidEncoder(req)
if err != nil {
return err
}
Expand Down Expand Up @@ -244,7 +244,7 @@ Specification of CAR formats: https://ipld.io/specs/transport/car/
return fmt.Errorf("unexpected message from DAG import")
}

enc, err := cmdenv.GetLowLevelCidEncoder(req)
enc, err := cmdenv.GetCidEncoder(req)
if err != nil {
return err
}
Expand Down Expand Up @@ -292,55 +292,21 @@ CAR file follows the CARv1 format: https://ipld.io/specs/transport/car/carv1/
},
}

// DagStat is a dag stat command response
// DagStat is a dag stat command response. Cid is stored as a
// pre-encoded string (via GetCidEncoder in the Run handler) so that
// --cid-base is respected and no custom MarshalJSON is needed.
type DagStat struct {
Cid cid.Cid
Cid string `json:"Cid"`
Size uint64 `json:",omitempty"`
NumBlocks int64 `json:",omitempty"`
}

func (s *DagStat) String() string {
return fmt.Sprintf("%s %d %d", s.Cid.String()[:20], s.Size, s.NumBlocks)
}

func (s *DagStat) MarshalJSON() ([]byte, error) {
type Alias DagStat
/*
We can't rely on cid.Cid.MarshalJSON since it uses the {"/": "..."}
format. To make the output consistent and follow the Kubo API patterns
we use the Cid.String method
*/
return json.Marshal(struct {
Cid string `json:"Cid"`
*Alias
}{
Cid: s.Cid.String(),
Alias: (*Alias)(s),
})
}

func (s *DagStat) UnmarshalJSON(data []byte) error {
/*
We can't rely on cid.Cid.UnmarshalJSON since it uses the {"/": "..."}
format. To make the output consistent and follow the Kubo API patterns
we use the Cid.Parse method
*/
type Alias DagStat
aux := struct {
Cid string `json:"Cid"`
*Alias
}{
Alias: (*Alias)(s),
cidStr := s.Cid
if len(cidStr) > 20 {
cidStr = cidStr[:20]
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
Cid, err := cid.Parse(aux.Cid)
if err != nil {
return err
}
s.Cid = Cid
return nil
return fmt.Sprintf("%s %d %d", cidStr, s.Size, s.NumBlocks)
}

type DagStatSummary struct {
Expand Down Expand Up @@ -404,15 +370,15 @@ Note: This command skips duplicate blocks in reporting both size and the number
fmt.Fprintln(w)
csvWriter := csv.NewWriter(w)
csvWriter.Comma = '\t'
cidSpacing := len(event.DagStatsArray[0].Cid.String())
cidSpacing := len(event.DagStatsArray[0].Cid)
header := []string{fmt.Sprintf("%-*s", cidSpacing, "CID"), fmt.Sprintf("%-15s", "Blocks"), "Size"}
if err := csvWriter.Write(header); err != nil {
return err
}
for _, dagStat := range event.DagStatsArray {
numBlocksStr := fmt.Sprint(dagStat.NumBlocks)
err := csvWriter.Write([]string{
dagStat.Cid.String(),
dagStat.Cid,
fmt.Sprintf("%-15s", numBlocksStr),
fmt.Sprint(dagStat.Size),
})
Expand All @@ -432,7 +398,6 @@ Note: This command skips duplicate blocks in reporting both size and the number
}),
cmds.JSON: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, event *DagStatSummary) error {
return json.NewEncoder(w).Encode(event)
},
),
}),
},
}
8 changes: 7 additions & 1 deletion core/commands/dag/stat.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ func dagStat(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment)
if err != nil {
return err
}

enc, err := cmdenv.GetCidEncoder(req)
if err != nil {
return err
}

nodeGetter := mdag.NewSession(req.Context, api.Dag())

cidSet := cid.NewSet()
Expand All @@ -50,7 +56,7 @@ func dagStat(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment)
if err != nil {
return err
}
dagstats := &DagStat{Cid: rp.RootCid()}
dagstats := &DagStat{Cid: enc.Encode(rp.RootCid())}
dagStatSummary.appendStats(dagstats)
err = traverse.Traverse(obj, traverse.Options{
DAG: nodeGetter,
Expand Down
Loading
Loading