swarm.go 4.85 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package swarm contains most basic and general Swarm concepts.
package swarm

8 9
import (
	"bytes"
acud's avatar
acud committed
10
	"encoding"
11
	"encoding/hex"
12
	"encoding/json"
13
	"errors"
14
	"fmt"
15 16

	"golang.org/x/crypto/sha3"
17 18 19
)

const (
20 21 22
	SpanSize                = 8
	SectionSize             = 32
	Branches                = 128
23
	EncryptedBranches       = Branches / 2
acud's avatar
acud committed
24
	BmtBranches             = 128
25 26
	ChunkSize               = SectionSize * Branches
	HashSize                = 32
27
	MaxPO             uint8 = 31
28
	ExtendedPO        uint8 = MaxPO + 5
29 30
	MaxBins                 = MaxPO + 1
	ChunkWithSpanSize       = ChunkSize + SpanSize
31 32 33 34
)

var (
	NewHasher = sha3.NewLegacyKeccak256
35
)
36

37 38 39 40
var (
	ErrInvalidChunk = errors.New("invalid chunk")
)

41 42
// Address represents an address in Swarm metric space of
// Node and Chunk addresses.
43 44 45 46
type Address struct {
	b []byte
}

47
// NewAddress constructs Address from a byte slice.
48 49 50
func NewAddress(b []byte) Address {
	return Address{b: b}
}
51

52 53 54 55 56 57 58
// ParseHexAddress returns an Address from a hex-encoded string representation.
func ParseHexAddress(s string) (a Address, err error) {
	b, err := hex.DecodeString(s)
	if err != nil {
		return a, err
	}
	return NewAddress(b), nil
59 60
}

61 62 63 64 65 66 67 68 69 70
// MustParseHexAddress returns an Address from a hex-encoded string
// representation, and panics if there is a parse error.
func MustParseHexAddress(s string) Address {
	a, err := ParseHexAddress(s)
	if err != nil {
		panic(err)
	}
	return a
}

71 72
// String returns a hex-encoded representation of the Address.
func (a Address) String() string {
73
	return hex.EncodeToString(a.b)
74
}
75 76 77

// Equal returns true if two addresses are identical.
func (a Address) Equal(b Address) bool {
78
	return bytes.Equal(a.b, b.b)
79 80
}

81 82 83 84 85 86 87 88 89 90 91
// MemberOf returns true if the address is a member of the
// provided set.
func (a Address) MemberOf(addrs []Address) bool {
	for _, v := range addrs {
		if v.Equal(a) {
			return true
		}
	}
	return false
}

92 93 94 95 96
// IsZero returns true if the Address is not set to any value.
func (a Address) IsZero() bool {
	return a.Equal(ZeroAddress)
}

97
// Bytes returns bytes representation of the Address.
98 99 100 101
func (a Address) Bytes() []byte {
	return a.b
}

102 103 104 105 106
// ByteString returns raw Address string without encoding.
func (a Address) ByteString() string {
	return string(a.Bytes())
}

107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
// UnmarshalJSON sets Address to a value from JSON-encoded representation.
func (a *Address) UnmarshalJSON(b []byte) (err error) {
	var s string
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	*a, err = ParseHexAddress(s)
	return err
}

// MarshalJSON returns JSON-encoded representation of Address.
func (a Address) MarshalJSON() ([]byte, error) {
	return json.Marshal(a.String())
}

122
// ZeroAddress is the address that has no value.
123
var ZeroAddress = NewAddress(nil)
124

125
// AddressIterFunc is a callback on every address that is found by the iterator.
126
type AddressIterFunc func(address Address) error
127

128
type Chunk interface {
acud's avatar
acud committed
129
	// Address returns the chunk address.
130
	Address() Address
acud's avatar
acud committed
131
	// Data returns the chunk data.
132
	Data() []byte
acud's avatar
acud committed
133
	// TagID returns the tag ID for this chunk.
134
	TagID() uint32
acud's avatar
acud committed
135
	// WithTagID attaches the tag ID to the chunk.
136
	WithTagID(t uint32) Chunk
acud's avatar
acud committed
137 138 139 140 141 142 143 144 145 146 147
	// Stamp returns the postage stamp associated with this chunk.
	Stamp() Stamp
	// WithStamp attaches a postage stamp to the chunk.
	WithStamp(Stamp) Chunk
	// Radius is the PO above which the batch is preserved.
	Radius() uint8
	// Depth returns the batch depth of the stamp - allowed batch size = 2^{depth}.
	Depth() uint8
	// WithBatch attaches batch parameters to the chunk.
	WithBatch(radius, depth uint8) Chunk
	// Equal checks if the chunk is equal to another.
148
	Equal(Chunk) bool
149 150
}

acud's avatar
acud committed
151 152 153 154 155 156 157 158
// Stamp interface for postage.Stamp to avoid circular dependency
type Stamp interface {
	BatchID() []byte
	Sig() []byte
	encoding.BinaryMarshaler
	encoding.BinaryUnmarshaler
}

159
type chunk struct {
acud's avatar
acud committed
160 161 162 163 164 165
	addr   Address
	sdata  []byte
	tagID  uint32
	stamp  Stamp
	radius uint8
	depth  uint8
166 167 168 169 170 171 172 173 174 175 176 177 178 179
}

func NewChunk(addr Address, data []byte) Chunk {
	return &chunk{
		addr:  addr,
		sdata: data,
	}
}

func (c *chunk) WithTagID(t uint32) Chunk {
	c.tagID = t
	return c
}

acud's avatar
acud committed
180 181 182 183 184 185 186 187 188 189 190
func (c *chunk) WithStamp(stamp Stamp) Chunk {
	c.stamp = stamp
	return c
}

func (c *chunk) WithBatch(radius, depth uint8) Chunk {
	c.radius = radius
	c.depth = depth
	return c
}

191 192 193 194 195 196 197 198 199 200 201 202
func (c *chunk) Address() Address {
	return c.addr
}

func (c *chunk) Data() []byte {
	return c.sdata
}

func (c *chunk) TagID() uint32 {
	return c.tagID
}

acud's avatar
acud committed
203 204 205 206 207 208 209 210 211 212 213 214
func (c *chunk) Stamp() Stamp {
	return c.stamp
}

func (c *chunk) Radius() uint8 {
	return c.radius
}

func (c *chunk) Depth() uint8 {
	return c.depth
}

215 216 217 218 219 220
func (c *chunk) String() string {
	return fmt.Sprintf("Address: %v Chunksize: %v", c.addr.String(), len(c.sdata))
}

func (c *chunk) Equal(cp Chunk) bool {
	return c.Address().Equal(cp.Address()) && bytes.Equal(c.Data(), cp.Data())
221
}