Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(cli): object add-link: do not allow blocks over BS limit #8414

Merged
merged 6 commits into from
Sep 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
49 changes: 49 additions & 0 deletions core/commands/object/patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ import (
"fmt"
"io"

"github.com/ipfs/go-cid"
cmds "github.com/ipfs/go-ipfs-cmds"
"github.com/ipfs/go-ipfs/core/commands/cmdenv"
coreiface "github.com/ipfs/interface-go-ipfs-core"

"github.com/ipfs/interface-go-ipfs-core/options"
"github.com/ipfs/interface-go-ipfs-core/path"
)

const (
softBlockLimit = 1024 * 1024 // https://github.com/ipfs/go-ipfs/issues/7421#issuecomment-910833499
allowBigBlock = "allow-big-block"
)

var ObjectPatchCmd = &cmds.Command{
Helptext: cmds.HelpText{
Tagline: "Deprecated way to create a new merkledag object based on an existing one. Use MFS with 'files cp|rm' instead.",
Expand Down Expand Up @@ -41,6 +48,9 @@ For modern use cases, use MFS with 'files' commands: 'ipfs files --help'.
"rm-link": patchRmLinkCmd,
"set-data": patchSetDataCmd,
},
Options: []cmds.Option{
cmds.BoolOption(allowBigBlock, "Disable block size check and allow creation of blocks bigger than 1MB. WARNING: such blocks won't be transferable over the standard bitswap.").WithDefault(false),
},
}

var patchAppendDataCmd = &cmds.Command{
Expand Down Expand Up @@ -82,6 +92,10 @@ DEPRECATED and provided for legacy reasons. Use 'ipfs add' or 'ipfs files' inste
return err
}

if err := checkBlockSize(req, p.Cid(), api.Dag()); err != nil {
return err
}

return cmds.EmitOnce(res, &Object{Hash: p.Cid().String()})
},
Type: &Object{},
Expand Down Expand Up @@ -128,6 +142,10 @@ DEPRECATED and provided for legacy reasons. Use 'files cp' and 'dag put' instead
return err
}

if err := checkBlockSize(req, p.Cid(), api.Dag()); err != nil {
return err
}

return cmds.EmitOnce(res, &Object{Hash: p.Cid().String()})
},
Type: Object{},
Expand Down Expand Up @@ -166,6 +184,10 @@ DEPRECATED and provided for legacy reasons. Use 'files rm' instead.
return err
}

if err := checkBlockSize(req, p.Cid(), api.Dag()); err != nil {
return err
}

return cmds.EmitOnce(res, &Object{Hash: p.Cid().String()})
},
Type: Object{},
Expand Down Expand Up @@ -232,6 +254,10 @@ Use MFS and 'files' commands instead:
return err
}

if err := checkBlockSize(req, p.Cid(), api.Dag()); err != nil {
return err
}

return cmds.EmitOnce(res, &Object{Hash: p.Cid().String()})
},
Type: Object{},
Expand All @@ -242,3 +268,26 @@ Use MFS and 'files' commands instead:
}),
},
}

func checkBlockSize(req *cmds.Request, c cid.Cid, dagAPI coreiface.APIDagService) error {
allowAnyBlockSize, _ := req.Options[allowBigBlock].(bool)
if allowAnyBlockSize {
return nil
}

// We do not allow producing blocks bigger than 1 MiB to avoid errors
// when transmitting them over BitSwap. The 1 MiB constant is an
// unenforced and undeclared rule of thumb hard-coded here.
modifiedNode, err := dagAPI.Get(req.Context, c)
if err != nil {
return err
}
modifiedNodeSize, err := modifiedNode.Size()
if err != nil {
return err
}
if modifiedNodeSize > softBlockLimit {
return fmt.Errorf("produced block is over 1MB, object API is deprecated and does not support HAMT-sharding: to create big directories, please use the files API (MFS)")
}
return nil
}
18 changes: 18 additions & 0 deletions test/sharness/t0051-object.sh
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,24 @@ test_object_cmd() {
ipfs object stat $OUTPUT
'

test_expect_success "'ipfs object patch' check output block size" '
DIR=$(ipfs object new unixfs-dir)
for i in {1..13}
do
DIR=$(ipfs object patch "$DIR" add-link "$DIR.jpg" "$DIR")
done
# Fail when new block goes over the BS limit of 1MB, but allow manual override
test_expect_code 1 ipfs object patch "$DIR" add-link "$DIR.jpg" "$DIR" >patch_out 2>&1
'

test_expect_success "ipfs object patch add-link output has the correct error" '
grep "produced block is over 1MB, object API is deprecated and does not support HAMT-sharding: to create big directories, please use the files API (MFS)" patch_out
'

test_expect_success "ipfs object patch --allow-big-block=true add-link works" '
test_expect_code 0 ipfs object patch --allow-big-block=true "$DIR" add-link "$DIR.jpg" "$DIR"
'

test_expect_success "'ipfs object new foo' shouldn't crash" '
test_expect_code 1 ipfs object new foo
'
Expand Down