github.com/ethersphere/bee/v2@v2.2.0/pkg/swarm/swarm.go (about)

     1  // Copyright 2020 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package swarm contains most basic and general Swarm concepts.
     6  package swarm
     7  
     8  import (
     9  	"bytes"
    10  	"encoding"
    11  	"encoding/hex"
    12  	"encoding/json"
    13  	"errors"
    14  	"fmt"
    15  )
    16  
    17  const (
    18  	StampIndexSize           = 8 // TODO: use this size in related code.
    19  	StampTimestampSize       = 8 // TODO: use this size in related code.
    20  	SpanSize                 = 8
    21  	SectionSize              = 32
    22  	Branches                 = 128
    23  	EncryptedBranches        = Branches / 2
    24  	BmtBranches              = 128
    25  	ChunkSize                = SectionSize * Branches
    26  	HashSize                 = 32
    27  	MaxPO              uint8 = 31
    28  	ExtendedPO         uint8 = MaxPO + 5
    29  	MaxBins                  = MaxPO + 1
    30  	ChunkWithSpanSize        = ChunkSize + SpanSize
    31  	SocSignatureSize         = 65
    32  	SocMinChunkSize          = HashSize + SocSignatureSize + SpanSize
    33  	SocMaxChunkSize          = SocMinChunkSize + ChunkSize
    34  )
    35  
    36  var (
    37  	ErrInvalidChunk = errors.New("invalid chunk")
    38  )
    39  
    40  var (
    41  	// Ethereum Address for SOC owner of Dispersed Replicas
    42  	// generated from private key 0x0100000000000000000000000000000000000000000000000000000000000000
    43  	ReplicasOwner, _ = hex.DecodeString("dc5b20847f43d67928f49cd4f85d696b5a7617b5")
    44  )
    45  
    46  var (
    47  	// EmptyAddress is the address that is all zeroes.
    48  	EmptyAddress = NewAddress(make([]byte, HashSize))
    49  	// ZeroAddress is the address that has no value.
    50  	ZeroAddress = NewAddress(nil)
    51  )
    52  
    53  // Address represents an address in Swarm metric space of
    54  // Node and Chunk addresses.
    55  type Address struct {
    56  	b []byte
    57  }
    58  
    59  // NewAddress constructs Address from a byte slice.
    60  func NewAddress(b []byte) Address {
    61  	return Address{b: b}
    62  }
    63  
    64  // ParseHexAddress returns an Address from a hex-encoded string representation.
    65  func ParseHexAddress(s string) (a Address, err error) {
    66  	b, err := hex.DecodeString(s)
    67  	if err != nil {
    68  		return a, err
    69  	}
    70  	return NewAddress(b), nil
    71  }
    72  
    73  // MustParseHexAddress returns an Address from a hex-encoded string
    74  // representation, and panics if there is a parse error.
    75  func MustParseHexAddress(s string) Address {
    76  	a, err := ParseHexAddress(s)
    77  	if err != nil {
    78  		panic(err)
    79  	}
    80  	return a
    81  }
    82  
    83  // String returns a hex-encoded representation of the Address.
    84  func (a Address) String() string {
    85  	return hex.EncodeToString(a.b)
    86  }
    87  
    88  // Equal returns true if two addresses are identical.
    89  func (a Address) Equal(b Address) bool {
    90  	return bytes.Equal(a.b, b.b)
    91  }
    92  
    93  // MemberOf returns true if the address is a member of the
    94  // provided set.
    95  func (a Address) MemberOf(addrs []Address) bool {
    96  	return ContainsAddress(addrs, a)
    97  }
    98  
    99  // IsZero returns true if the Address is not set to any value.
   100  func (a Address) IsZero() bool {
   101  	return a.Equal(ZeroAddress)
   102  }
   103  
   104  // IsEmpty returns true if the Address is all zeroes.
   105  func (a Address) IsEmpty() bool {
   106  	return a.Equal(EmptyAddress)
   107  }
   108  
   109  // IsValidLength returns true if the Address is of valid length.
   110  func (a Address) IsValidLength() bool {
   111  	return len(a.b) == HashSize
   112  }
   113  
   114  // IsValidNonEmpty returns true if the Address has valid length and is not empty.
   115  func (a Address) IsValidNonEmpty() bool {
   116  	return a.IsValidLength() && !a.IsEmpty()
   117  }
   118  
   119  // Bytes returns bytes representation of the Address.
   120  func (a Address) Bytes() []byte {
   121  	return a.b
   122  }
   123  
   124  // ByteString returns raw Address string without encoding.
   125  func (a Address) ByteString() string {
   126  	return string(a.Bytes())
   127  }
   128  
   129  // UnmarshalJSON sets Address to a value from JSON-encoded representation.
   130  func (a *Address) UnmarshalJSON(b []byte) (err error) {
   131  	var s string
   132  	if err := json.Unmarshal(b, &s); err != nil {
   133  		return err
   134  	}
   135  	*a, err = ParseHexAddress(s)
   136  	return err
   137  }
   138  
   139  // MarshalJSON returns JSON-encoded representation of Address.
   140  func (a Address) MarshalJSON() ([]byte, error) {
   141  	return json.Marshal(a.String())
   142  }
   143  
   144  // Closer returns if x is closer to a than y
   145  func (x Address) Closer(a Address, y Address) (bool, error) {
   146  	cmp, err := DistanceCmp(a, x, y)
   147  	return cmp == 1, err
   148  }
   149  
   150  // Clone returns a new swarm address which is a copy of this one.
   151  func (a Address) Clone() Address {
   152  	if a.b == nil {
   153  		return Address{}
   154  	}
   155  	return Address{b: append(make([]byte, 0, len(a.b)), a.Bytes()...)}
   156  }
   157  
   158  // Compare returns an integer comparing two addresses lexicographically.
   159  // The result will be 0 if a == b, -1 if a < b, and +1 if a > b.
   160  func (a Address) Compare(b Address) int {
   161  	return bytes.Compare(a.b, b.b)
   162  }
   163  
   164  // AddressIterFunc is a callback on every address that is found by the iterator.
   165  type AddressIterFunc func(address Address) error
   166  
   167  type Chunk interface {
   168  	// Address returns the chunk address.
   169  	Address() Address
   170  	// Data returns the chunk data.
   171  	Data() []byte
   172  	// TagID returns the tag ID for this chunk.
   173  	TagID() uint32
   174  	// WithTagID attaches the tag ID to the chunk.
   175  	WithTagID(t uint32) Chunk
   176  	// Stamp returns the postage stamp associated with this chunk.
   177  	Stamp() Stamp
   178  	// WithStamp attaches a postage stamp to the chunk.
   179  	WithStamp(Stamp) Chunk
   180  	// Depth returns the batch depth of the stamp - allowed batch size = 2^{depth}.
   181  	Depth() uint8
   182  	// BucketDepth returns the bucket depth of the batch of the stamp - always < depth.
   183  	BucketDepth() uint8
   184  	// Immutable returns whether the batch is immutable
   185  	Immutable() bool
   186  	// WithBatch attaches batch parameters to the chunk.
   187  	WithBatch(depth, bucketDepth uint8, immutable bool) Chunk
   188  	// Equal checks if the chunk is equal to another.
   189  	Equal(Chunk) bool
   190  }
   191  
   192  // ChunkType indicates different categories of chunks.
   193  type ChunkType uint8
   194  
   195  // String implements Stringer interface.
   196  func (ct ChunkType) String() string {
   197  	switch ct {
   198  	case ChunkTypeContentAddressed:
   199  		return "CAC"
   200  	case ChunkTypeSingleOwner:
   201  		return "SOC"
   202  	default:
   203  		return "unspecified"
   204  	}
   205  }
   206  
   207  // DO NOT CHANGE ORDER
   208  const (
   209  	ChunkTypeUnspecified ChunkType = iota
   210  	ChunkTypeContentAddressed
   211  	ChunkTypeSingleOwner
   212  )
   213  
   214  // Stamp interface for postage.Stamp to avoid circular dependency
   215  type Stamp interface {
   216  	BatchID() []byte
   217  	Index() []byte
   218  	Sig() []byte
   219  	Timestamp() []byte
   220  	Clone() Stamp
   221  	Hash() ([]byte, error)
   222  	encoding.BinaryMarshaler
   223  	encoding.BinaryUnmarshaler
   224  }
   225  
   226  type chunk struct {
   227  	addr        Address
   228  	sdata       []byte
   229  	tagID       uint32
   230  	stamp       Stamp
   231  	depth       uint8
   232  	bucketDepth uint8
   233  	immutable   bool
   234  }
   235  
   236  func NewChunk(addr Address, data []byte) Chunk {
   237  	return &chunk{
   238  		addr:  addr,
   239  		sdata: data,
   240  	}
   241  }
   242  
   243  func (c *chunk) WithTagID(t uint32) Chunk {
   244  	c.tagID = t
   245  	return c
   246  }
   247  
   248  func (c *chunk) WithStamp(stamp Stamp) Chunk {
   249  	c.stamp = stamp
   250  	return c
   251  }
   252  
   253  func (c *chunk) WithBatch(depth, bucketDepth uint8, immutable bool) Chunk {
   254  	c.depth = depth
   255  	c.bucketDepth = bucketDepth
   256  	c.immutable = immutable
   257  	return c
   258  }
   259  
   260  func (c *chunk) Address() Address {
   261  	return c.addr
   262  }
   263  
   264  func (c *chunk) Data() []byte {
   265  	return c.sdata
   266  }
   267  
   268  func (c *chunk) TagID() uint32 {
   269  	return c.tagID
   270  }
   271  
   272  func (c *chunk) Stamp() Stamp {
   273  	return c.stamp
   274  }
   275  
   276  func (c *chunk) Depth() uint8 {
   277  	return c.depth
   278  }
   279  
   280  func (c *chunk) BucketDepth() uint8 {
   281  	return c.bucketDepth
   282  }
   283  
   284  func (c *chunk) Immutable() bool {
   285  	return c.immutable
   286  }
   287  
   288  func (c *chunk) String() string {
   289  	return fmt.Sprintf("Address: %v Chunksize: %v", c.addr.String(), len(c.sdata))
   290  }
   291  
   292  func (c *chunk) Equal(cp Chunk) bool {
   293  	return c.Address().Equal(cp.Address()) && bytes.Equal(c.Data(), cp.Data())
   294  }
   295  
   296  var errBadCharacter = errors.New("bad character in binary address")
   297  
   298  // ParseBitStrAddress parses overlay addresses in binary format (eg: 111101101) to it's corresponding overlay address.
   299  func ParseBitStrAddress(src string) (Address, error) {
   300  
   301  	bitPos := 7
   302  	b := uint8(0)
   303  
   304  	var a []byte
   305  
   306  	for _, s := range src {
   307  		if s == '1' {
   308  			b |= 1 << bitPos
   309  		} else if s != '0' {
   310  			return ZeroAddress, errBadCharacter
   311  		}
   312  		bitPos--
   313  		if bitPos < 0 {
   314  			a = append(a, b)
   315  			b = 0
   316  			bitPos = 7
   317  		}
   318  	}
   319  
   320  	a = append(a, b)
   321  
   322  	return bytesToAddr(a), nil
   323  }
   324  
   325  func bytesToAddr(b []byte) Address {
   326  	addr := make([]byte, HashSize)
   327  	copy(addr, b)
   328  	return NewAddress(addr)
   329  }