mirror of
https://github.com/ipfs/kubo.git
synced 2026-02-22 02:47:48 +08:00
Some checks failed
CodeQL / codeql (push) Has been cancelled
Docker Check / lint (push) Has been cancelled
Docker Check / build (push) Has been cancelled
Gateway Conformance / gateway-conformance (push) Has been cancelled
Gateway Conformance / gateway-conformance-libp2p-experiment (push) Has been cancelled
Go Build / go-build (push) Has been cancelled
Go Check / go-check (push) Has been cancelled
Go Lint / go-lint (push) Has been cancelled
Go Test / unit-tests (push) Has been cancelled
Go Test / cli-tests (push) Has been cancelled
Go Test / example-tests (push) Has been cancelled
Interop / interop-prep (push) Has been cancelled
Sharness / sharness-test (push) Has been cancelled
Spell Check / spellcheck (push) Has been cancelled
Interop / helia-interop (push) Has been cancelled
Interop / ipfs-webui (push) Has been cancelled
IPIP-499's unixfs-v1-2025 profile uses 1MiB chunks. with --raw-leaves=false, protobuf wrapping pushes blocks slightly over 1MiB. the previous 1MiB SoftBlockLimit rejected these blocks on dag import. raise SoftBlockLimit to 2MiB to match the bitswap spec, which requires implementations to support blocks up to 2MiB. - raise SoftBlockLimit to 2MiB per the bitswap spec - update error messages and help text - bump boxo to main with ipfs/boxo#1101 (raised ChunkSizeLimit/BlockSizeLimit, 256-byte overhead budget) - update sharness tests for 2MiB boundary - add test/cli boundary tests for block put, dag put, dag import, ipfs add (raw and wrapped leaves), and bitswap exchange including regression tests for the libp2p message size hard limit
100 lines
3.0 KiB
Go
100 lines
3.0 KiB
Go
package cmdutils
|
|
|
|
import (
|
|
"fmt"
|
|
"slices"
|
|
|
|
cmds "github.com/ipfs/go-ipfs-cmds"
|
|
|
|
"github.com/ipfs/boxo/path"
|
|
"github.com/ipfs/go-cid"
|
|
coreiface "github.com/ipfs/kubo/core/coreiface"
|
|
"github.com/libp2p/go-libp2p/core/peer"
|
|
)
|
|
|
|
const (
|
|
AllowBigBlockOptionName = "allow-big-block"
|
|
// SoftBlockLimit is the maximum block size for bitswap transfer.
|
|
// If this value changes, update the "2MiB" strings in error messages below.
|
|
SoftBlockLimit = 2 * 1024 * 1024 // https://specs.ipfs.tech/bitswap-protocol/#block-sizes
|
|
MaxPinNameBytes = 255 // Maximum number of bytes allowed for a pin name
|
|
)
|
|
|
|
var AllowBigBlockOption cmds.Option
|
|
|
|
func init() {
|
|
AllowBigBlockOption = cmds.BoolOption(AllowBigBlockOptionName, "Disable block size check and allow creation of blocks bigger than 2MiB. WARNING: such blocks won't be transferable over the standard bitswap.").WithDefault(false)
|
|
}
|
|
|
|
func CheckCIDSize(req *cmds.Request, c cid.Cid, dagAPI coreiface.APIDagService) error {
|
|
n, err := dagAPI.Get(req.Context, c)
|
|
if err != nil {
|
|
return fmt.Errorf("CheckCIDSize: getting dag: %w", err)
|
|
}
|
|
|
|
nodeSize, err := n.Size()
|
|
if err != nil {
|
|
return fmt.Errorf("CheckCIDSize: getting node size: %w", err)
|
|
}
|
|
|
|
return CheckBlockSize(req, nodeSize)
|
|
}
|
|
|
|
func CheckBlockSize(req *cmds.Request, size uint64) error {
|
|
allowAnyBlockSize, _ := req.Options[AllowBigBlockOptionName].(bool)
|
|
if allowAnyBlockSize {
|
|
return nil
|
|
}
|
|
|
|
// Block size is limited to SoftBlockLimit (2MiB) as defined in the bitswap spec.
|
|
// https://specs.ipfs.tech/bitswap-protocol/#block-sizes
|
|
if size > SoftBlockLimit {
|
|
return fmt.Errorf("produced block is over 2MiB: big blocks can't be exchanged with other peers. consider using UnixFS for automatic chunking of bigger files, or pass --allow-big-block to override")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ValidatePinName validates that a pin name does not exceed the maximum allowed byte length.
|
|
// Returns an error if the name exceeds MaxPinNameBytes (255 bytes).
|
|
func ValidatePinName(name string) error {
|
|
if name == "" {
|
|
// Empty names are allowed
|
|
return nil
|
|
}
|
|
|
|
nameBytes := len([]byte(name))
|
|
if nameBytes > MaxPinNameBytes {
|
|
return fmt.Errorf("pin name is %d bytes (max %d bytes)", nameBytes, MaxPinNameBytes)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// PathOrCidPath returns a path.Path built from the argument. It keeps the old
|
|
// behaviour by building a path from a CID string.
|
|
func PathOrCidPath(str string) (path.Path, error) {
|
|
p, err := path.NewPath(str)
|
|
if err == nil {
|
|
return p, nil
|
|
}
|
|
|
|
// Save the original error before attempting fallback
|
|
originalErr := err
|
|
|
|
if p, err := path.NewPath("/ipfs/" + str); err == nil {
|
|
return p, nil
|
|
}
|
|
|
|
// Send back original err.
|
|
return nil, originalErr
|
|
}
|
|
|
|
// CloneAddrInfo returns a copy of the AddrInfo with a cloned Addrs slice.
|
|
// This prevents data races if the sender reuses the backing array.
|
|
// See: https://github.com/ipfs/kubo/issues/11116
|
|
func CloneAddrInfo(ai peer.AddrInfo) peer.AddrInfo {
|
|
return peer.AddrInfo{
|
|
ID: ai.ID,
|
|
Addrs: slices.Clone(ai.Addrs),
|
|
}
|
|
}
|