Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mybee
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
mybee
Commits
1de167ea
Unverified
Commit
1de167ea
authored
Mar 17, 2021
by
Rodrigo Q. Saramago
Committed by
GitHub
Mar 17, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Soc package refactor (#1394)
parent
99aaaa79
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
567 additions
and
356 deletions
+567
-356
bzz_test.go
pkg/api/bzz_test.go
+1
-3
feed.go
pkg/api/feed.go
+3
-5
feed_test.go
pkg/api/feed_test.go
+7
-29
soc.go
pkg/api/soc.go
+13
-5
soc_test.go
pkg/api/soc_test.go
+21
-73
feed.go
pkg/feeds/feed.go
+8
-7
getter.go
pkg/feeds/getter.go
+1
-1
putter.go
pkg/feeds/putter.go
+2
-1
export_test.go
pkg/soc/export_test.go
+18
-2
soc.go
pkg/soc/soc.go
+95
-154
soc_test.go
pkg/soc/soc_test.go
+233
-36
soc.go
pkg/soc/testing/soc.go
+72
-0
validator.go
pkg/soc/validator.go
+1
-1
validator_test.go
pkg/soc/validator_test.go
+92
-39
No files found.
pkg/api/bzz_test.go
View file @
1de167ea
...
@@ -84,7 +84,6 @@ func TestBzz(t *testing.T) {
...
@@ -84,7 +84,6 @@ func TestBzz(t *testing.T) {
}
}
fileMetadataReference
,
err
:=
pipeWriteAll
(
bytes
.
NewReader
(
fileMetadataBytes
),
int64
(
len
(
fileMetadataBytes
)))
fileMetadataReference
,
err
:=
pipeWriteAll
(
bytes
.
NewReader
(
fileMetadataBytes
),
int64
(
len
(
fileMetadataBytes
)))
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
...
@@ -171,7 +170,6 @@ func TestBzz(t *testing.T) {
...
@@ -171,7 +170,6 @@ func TestBzz(t *testing.T) {
}),
}),
)
)
})
})
}
}
func
TestFeedIndirection
(
t
*
testing
.
T
)
{
func
TestFeedIndirection
(
t
*
testing
.
T
)
{
...
@@ -219,7 +217,7 @@ func TestFeedIndirection(t *testing.T) {
...
@@ -219,7 +217,7 @@ func TestFeedIndirection(t *testing.T) {
// called from the bzz endpoint. then call the bzz endpoint with
// called from the bzz endpoint. then call the bzz endpoint with
// the pregenerated feed root manifest hash
// the pregenerated feed root manifest hash
feedUpdate
,
_
:=
toChunk
(
121212
,
resp
.
Reference
.
Bytes
())
feedUpdate
:=
toChunk
(
t
,
121212
,
resp
.
Reference
.
Bytes
())
var
(
var
(
feedChunkAddr
=
swarm
.
MustParseHexAddress
(
"891a1d1c8436c792d02fc2e8883fef7ab387eaeaacd25aa9f518be7be7856d54"
)
feedChunkAddr
=
swarm
.
MustParseHexAddress
(
"891a1d1c8436c792d02fc2e8883fef7ab387eaeaacd25aa9f518be7be7856d54"
)
...
...
pkg/api/feed.go
View file @
1de167ea
...
@@ -29,9 +29,7 @@ const (
...
@@ -29,9 +29,7 @@ const (
feedMetadataEntryType
=
"swarm-feed-type"
feedMetadataEntryType
=
"swarm-feed-type"
)
)
var
(
var
errInvalidFeedUpdate
=
errors
.
New
(
"invalid feed update"
)
errInvalidFeedUpdate
=
errors
.
New
(
"invalid feed update"
)
)
type
feedReferenceResponse
struct
{
type
feedReferenceResponse
struct
{
Reference
swarm
.
Address
`json:"reference"`
Reference
swarm
.
Address
`json:"reference"`
...
@@ -176,12 +174,12 @@ func (s *server) feedPostHandler(w http.ResponseWriter, r *http.Request) {
...
@@ -176,12 +174,12 @@ func (s *server) feedPostHandler(w http.ResponseWriter, r *http.Request) {
}
}
func
parseFeedUpdate
(
ch
swarm
.
Chunk
)
(
swarm
.
Address
,
int64
,
error
)
{
func
parseFeedUpdate
(
ch
swarm
.
Chunk
)
(
swarm
.
Address
,
int64
,
error
)
{
s
ch
,
err
:=
soc
.
FromChunk
(
ch
)
s
,
err
:=
soc
.
FromChunk
(
ch
)
if
err
!=
nil
{
if
err
!=
nil
{
return
swarm
.
ZeroAddress
,
0
,
fmt
.
Errorf
(
"soc unmarshal: %w"
,
err
)
return
swarm
.
ZeroAddress
,
0
,
fmt
.
Errorf
(
"soc unmarshal: %w"
,
err
)
}
}
update
:=
s
ch
.
Chunk
.
Data
()
update
:=
s
.
WrappedChunk
()
.
Data
()
// split the timestamp and reference
// split the timestamp and reference
// possible values right now:
// possible values right now:
// unencrypted ref: span+timestamp+ref => 8+8+32=48
// unencrypted ref: span+timestamp+ref => 8+8+32=48
...
...
pkg/api/feed_test.go
View file @
1de167ea
...
@@ -16,15 +16,13 @@ import (
...
@@ -16,15 +16,13 @@ import (
"testing"
"testing"
"github.com/ethersphere/bee/pkg/api"
"github.com/ethersphere/bee/pkg/api"
"github.com/ethersphere/bee/pkg/cac"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/feeds"
"github.com/ethersphere/bee/pkg/feeds"
"github.com/ethersphere/bee/pkg/file/loadsave"
"github.com/ethersphere/bee/pkg/file/loadsave"
"github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/jsonhttp/jsonhttptest"
"github.com/ethersphere/bee/pkg/jsonhttp/jsonhttptest"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/manifest"
"github.com/ethersphere/bee/pkg/manifest"
"github.com/ethersphere/bee/pkg/soc
"
testingsoc
"github.com/ethersphere/bee/pkg/soc/testing
"
statestore
"github.com/ethersphere/bee/pkg/statestore/mock"
statestore
"github.com/ethersphere/bee/pkg/statestore/mock"
"github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/bee/pkg/storage"
"github.com/ethersphere/bee/pkg/storage/mock"
"github.com/ethersphere/bee/pkg/storage/mock"
...
@@ -84,7 +82,7 @@ func TestFeed_Get(t *testing.T) {
...
@@ -84,7 +82,7 @@ func TestFeed_Get(t *testing.T) {
t
.
Run
(
"with at"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"with at"
,
func
(
t
*
testing
.
T
)
{
var
(
var
(
timestamp
=
int64
(
12121212
)
timestamp
=
int64
(
12121212
)
ch
,
_
=
toChunk
(
uint64
(
timestamp
),
expReference
.
Bytes
())
ch
=
toChunk
(
t
,
uint64
(
timestamp
),
expReference
.
Bytes
())
look
=
newMockLookup
(
12
,
0
,
ch
,
nil
,
&
id
{},
&
id
{})
look
=
newMockLookup
(
12
,
0
,
ch
,
nil
,
&
id
{},
&
id
{})
factory
=
newMockFactory
(
look
)
factory
=
newMockFactory
(
look
)
idBytes
,
_
=
(
&
id
{})
.
MarshalBinary
()
idBytes
,
_
=
(
&
id
{})
.
MarshalBinary
()
...
@@ -115,7 +113,7 @@ func TestFeed_Get(t *testing.T) {
...
@@ -115,7 +113,7 @@ func TestFeed_Get(t *testing.T) {
t
.
Run
(
"latest"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"latest"
,
func
(
t
*
testing
.
T
)
{
var
(
var
(
timestamp
=
int64
(
12121212
)
timestamp
=
int64
(
12121212
)
ch
,
_
=
toChunk
(
uint64
(
timestamp
),
expReference
.
Bytes
())
ch
=
toChunk
(
t
,
uint64
(
timestamp
),
expReference
.
Bytes
())
look
=
newMockLookup
(
-
1
,
2
,
ch
,
nil
,
&
id
{},
&
id
{})
look
=
newMockLookup
(
-
1
,
2
,
ch
,
nil
,
&
id
{},
&
id
{})
factory
=
newMockFactory
(
look
)
factory
=
newMockFactory
(
look
)
idBytes
,
_
=
(
&
id
{})
.
MarshalBinary
()
idBytes
,
_
=
(
&
id
{})
.
MarshalBinary
()
...
@@ -237,36 +235,16 @@ func (l *mockLookup) At(_ context.Context, at, after int64) (swarm.Chunk, feeds.
...
@@ -237,36 +235,16 @@ func (l *mockLookup) At(_ context.Context, at, after int64) (swarm.Chunk, feeds.
return
nil
,
nil
,
nil
,
errors
.
New
(
"no feed update found"
)
return
nil
,
nil
,
nil
,
errors
.
New
(
"no feed update found"
)
}
}
func
toChunk
(
at
uint64
,
payload
[]
byte
)
(
swarm
.
Chunk
,
error
)
{
func
toChunk
(
t
*
testing
.
T
,
at
uint64
,
payload
[]
byte
)
swarm
.
Chunk
{
ts
:=
make
([]
byte
,
8
)
ts
:=
make
([]
byte
,
8
)
binary
.
BigEndian
.
PutUint64
(
ts
,
at
)
binary
.
BigEndian
.
PutUint64
(
ts
,
at
)
content
:=
append
(
ts
,
payload
...
)
content
:=
append
(
ts
,
payload
...
)
ch
,
err
:=
cac
.
New
(
content
)
if
err
!=
nil
{
return
nil
,
err
}
id
:=
make
([]
byte
,
soc
.
IdSize
)
privKey
,
err
:=
crypto
.
GenerateSecp256k1Key
()
if
err
!=
nil
{
return
nil
,
err
}
signer
:=
crypto
.
NewDefaultSigner
(
privKey
)
sch
:=
soc
.
New
(
id
,
ch
)
s
:=
testingsoc
.
GenerateMockSOC
(
t
,
content
)
if
err
!=
nil
{
return
s
.
Chunk
()
return
nil
,
err
}
err
=
sch
.
AddSigner
(
signer
)
if
err
!=
nil
{
return
nil
,
err
}
return
sch
.
ToChunk
()
}
}
type
id
struct
{
type
id
struct
{}
}
func
(
i
*
id
)
MarshalBinary
()
([]
byte
,
error
)
{
func
(
i
*
id
)
MarshalBinary
()
([]
byte
,
error
)
{
return
[]
byte
(
"accd"
),
nil
return
[]
byte
(
"accd"
),
nil
...
...
pkg/api/soc.go
View file @
1de167ea
...
@@ -88,7 +88,15 @@ func (s *server) socUploadHandler(w http.ResponseWriter, r *http.Request) {
...
@@ -88,7 +88,15 @@ func (s *server) socUploadHandler(w http.ResponseWriter, r *http.Request) {
return
return
}
}
chunk
,
err
:=
soc
.
NewSignedChunk
(
id
,
ch
,
owner
,
sig
)
ss
,
err
:=
soc
.
NewSigned
(
id
,
ch
,
owner
,
sig
)
if
err
!=
nil
{
s
.
logger
.
Debugf
(
"soc upload: address soc error: %v"
,
err
)
s
.
logger
.
Error
(
"soc upload: address soc error"
)
jsonhttp
.
Unauthorized
(
w
,
"invalid address"
)
return
}
sch
,
err
:=
ss
.
Chunk
()
if
err
!=
nil
{
if
err
!=
nil
{
s
.
logger
.
Debugf
(
"soc upload: read chunk data error: %v"
,
err
)
s
.
logger
.
Debugf
(
"soc upload: read chunk data error: %v"
,
err
)
s
.
logger
.
Error
(
"soc upload: read chunk data error"
)
s
.
logger
.
Error
(
"soc upload: read chunk data error"
)
...
@@ -96,7 +104,7 @@ func (s *server) socUploadHandler(w http.ResponseWriter, r *http.Request) {
...
@@ -96,7 +104,7 @@ func (s *server) socUploadHandler(w http.ResponseWriter, r *http.Request) {
return
return
}
}
if
!
soc
.
Valid
(
chunk
)
{
if
!
soc
.
Valid
(
sch
)
{
s
.
logger
.
Debugf
(
"soc upload: invalid chunk: %v"
,
err
)
s
.
logger
.
Debugf
(
"soc upload: invalid chunk: %v"
,
err
)
s
.
logger
.
Error
(
"soc upload: invalid chunk"
)
s
.
logger
.
Error
(
"soc upload: invalid chunk"
)
jsonhttp
.
Unauthorized
(
w
,
"invalid chunk"
)
jsonhttp
.
Unauthorized
(
w
,
"invalid chunk"
)
...
@@ -106,7 +114,7 @@ func (s *server) socUploadHandler(w http.ResponseWriter, r *http.Request) {
...
@@ -106,7 +114,7 @@ func (s *server) socUploadHandler(w http.ResponseWriter, r *http.Request) {
ctx
:=
r
.
Context
()
ctx
:=
r
.
Context
()
has
,
err
:=
s
.
storer
.
Has
(
ctx
,
chunk
.
Address
())
has
,
err
:=
s
.
storer
.
Has
(
ctx
,
sch
.
Address
())
if
err
!=
nil
{
if
err
!=
nil
{
s
.
logger
.
Debugf
(
"soc upload: store has: %v"
,
err
)
s
.
logger
.
Debugf
(
"soc upload: store has: %v"
,
err
)
s
.
logger
.
Error
(
"soc upload: store has"
)
s
.
logger
.
Error
(
"soc upload: store has"
)
...
@@ -119,7 +127,7 @@ func (s *server) socUploadHandler(w http.ResponseWriter, r *http.Request) {
...
@@ -119,7 +127,7 @@ func (s *server) socUploadHandler(w http.ResponseWriter, r *http.Request) {
return
return
}
}
_
,
err
=
s
.
storer
.
Put
(
ctx
,
requestModePut
(
r
),
chunk
)
_
,
err
=
s
.
storer
.
Put
(
ctx
,
requestModePut
(
r
),
sch
)
if
err
!=
nil
{
if
err
!=
nil
{
s
.
logger
.
Debugf
(
"soc upload: chunk write error: %v"
,
err
)
s
.
logger
.
Debugf
(
"soc upload: chunk write error: %v"
,
err
)
s
.
logger
.
Error
(
"soc upload: chunk write error"
)
s
.
logger
.
Error
(
"soc upload: chunk write error"
)
...
@@ -127,5 +135,5 @@ func (s *server) socUploadHandler(w http.ResponseWriter, r *http.Request) {
...
@@ -127,5 +135,5 @@ func (s *server) socUploadHandler(w http.ResponseWriter, r *http.Request) {
return
return
}
}
jsonhttp
.
Created
(
w
,
chunkAddressResponse
{
Reference
:
chunk
.
Address
()})
jsonhttp
.
Created
(
w
,
chunkAddressResponse
{
Reference
:
sch
.
Address
()})
}
}
pkg/api/soc_test.go
View file @
1de167ea
...
@@ -6,7 +6,6 @@ package api_test
...
@@ -6,7 +6,6 @@ package api_test
import
(
import
(
"bytes"
"bytes"
"encoding/binary"
"encoding/hex"
"encoding/hex"
"fmt"
"fmt"
"io/ioutil"
"io/ioutil"
...
@@ -14,19 +13,19 @@ import (
...
@@ -14,19 +13,19 @@ import (
"testing"
"testing"
"github.com/ethersphere/bee/pkg/api"
"github.com/ethersphere/bee/pkg/api"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/jsonhttp"
"github.com/ethersphere/bee/pkg/jsonhttp/jsonhttptest"
"github.com/ethersphere/bee/pkg/jsonhttp/jsonhttptest"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/soc"
"github.com/ethersphere/bee/pkg/soc"
testingsoc
"github.com/ethersphere/bee/pkg/soc/testing"
statestore
"github.com/ethersphere/bee/pkg/statestore/mock"
statestore
"github.com/ethersphere/bee/pkg/statestore/mock"
"github.com/ethersphere/bee/pkg/storage/mock"
"github.com/ethersphere/bee/pkg/storage/mock"
"github.com/ethersphere/bee/pkg/swarm"
"github.com/ethersphere/bee/pkg/tags"
"github.com/ethersphere/bee/pkg/tags"
)
)
func
TestS
oc
(
t
*
testing
.
T
)
{
func
TestS
OC
(
t
*
testing
.
T
)
{
var
(
var
(
testData
=
[]
byte
(
"foo"
)
socResource
=
func
(
owner
,
id
,
sig
string
)
string
{
return
fmt
.
Sprintf
(
"/soc/%s/%s?sig=%s"
,
owner
,
id
,
sig
)
}
socResource
=
func
(
owner
,
id
,
sig
string
)
string
{
return
fmt
.
Sprintf
(
"/soc/%s/%s?sig=%s"
,
owner
,
id
,
sig
)
}
mockStatestore
=
statestore
.
NewStateStore
()
mockStatestore
=
statestore
.
NewStateStore
()
logger
=
logging
.
New
(
ioutil
.
Discard
,
0
)
logger
=
logging
.
New
(
ioutil
.
Discard
,
0
)
...
@@ -37,7 +36,6 @@ func TestSoc(t *testing.T) {
...
@@ -37,7 +36,6 @@ func TestSoc(t *testing.T) {
Tags
:
tag
,
Tags
:
tag
,
})
})
)
)
t
.
Run
(
"cmpty data"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"cmpty data"
,
func
(
t
*
testing
.
T
)
{
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
socResource
(
"8d3766440f0d7b949a5e32995d09619a7f86e632"
,
"bb"
,
"cc"
),
http
.
StatusBadRequest
,
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
socResource
(
"8d3766440f0d7b949a5e32995d09619a7f86e632"
,
"bb"
,
"cc"
),
http
.
StatusBadRequest
,
jsonhttptest
.
WithExpectedJSONResponse
(
jsonhttp
.
StatusResponse
{
jsonhttptest
.
WithExpectedJSONResponse
(
jsonhttp
.
StatusResponse
{
...
@@ -75,16 +73,16 @@ func TestSoc(t *testing.T) {
...
@@ -75,16 +73,16 @@ func TestSoc(t *testing.T) {
})
})
t
.
Run
(
"signature invalid"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"signature invalid"
,
func
(
t
*
testing
.
T
)
{
s
,
owner
,
payload
:=
mockSoc
(
t
)
s
:=
testingsoc
.
GenerateMockSOC
(
t
,
testData
)
id
:=
make
([]
byte
,
soc
.
IdSize
)
// modify the sign
// modify the sign
sig
:=
s
.
Signature
()
sig
:=
make
([]
byte
,
soc
.
SignatureSize
)
copy
(
sig
,
s
.
Signature
)
sig
[
12
]
=
0x98
sig
[
12
]
=
0x98
sig
[
10
]
=
0x12
sig
[
10
]
=
0x12
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
socResource
(
hex
.
EncodeToString
(
owner
),
hex
.
EncodeToString
(
id
),
hex
.
EncodeToString
(
sig
)),
http
.
StatusUnauthorized
,
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
socResource
(
hex
.
EncodeToString
(
s
.
Owner
),
hex
.
EncodeToString
(
s
.
ID
),
hex
.
EncodeToString
(
sig
)),
http
.
StatusUnauthorized
,
jsonhttptest
.
WithRequestBody
(
bytes
.
NewReader
(
payload
)),
jsonhttptest
.
WithRequestBody
(
bytes
.
NewReader
(
s
.
WrappedChunk
.
Data
()
)),
jsonhttptest
.
WithExpectedJSONResponse
(
jsonhttp
.
StatusResponse
{
jsonhttptest
.
WithExpectedJSONResponse
(
jsonhttp
.
StatusResponse
{
Message
:
"invalid chunk"
,
Message
:
"invalid chunk"
,
Code
:
http
.
StatusUnauthorized
,
Code
:
http
.
StatusUnauthorized
,
...
@@ -93,55 +91,39 @@ func TestSoc(t *testing.T) {
...
@@ -93,55 +91,39 @@ func TestSoc(t *testing.T) {
})
})
t
.
Run
(
"ok"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"ok"
,
func
(
t
*
testing
.
T
)
{
s
,
owner
,
payload
:=
mockSoc
(
t
)
s
:=
testingsoc
.
GenerateMockSOC
(
t
,
testData
)
id
:=
make
([]
byte
,
soc
.
IdSize
)
sig
:=
s
.
Signature
()
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
socResource
(
hex
.
EncodeToString
(
s
.
Owner
),
hex
.
EncodeToString
(
s
.
ID
),
hex
.
EncodeToString
(
s
.
Signature
)),
http
.
StatusCreated
,
addr
,
err
:=
s
.
Address
()
jsonhttptest
.
WithRequestBody
(
bytes
.
NewReader
(
s
.
WrappedChunk
.
Data
())),
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
socResource
(
hex
.
EncodeToString
(
owner
),
hex
.
EncodeToString
(
id
),
hex
.
EncodeToString
(
sig
)),
http
.
StatusCreated
,
jsonhttptest
.
WithRequestBody
(
bytes
.
NewReader
(
payload
)),
jsonhttptest
.
WithExpectedJSONResponse
(
api
.
SocPostResponse
{
jsonhttptest
.
WithExpectedJSONResponse
(
api
.
SocPostResponse
{
Reference
:
addr
,
Reference
:
s
.
Address
()
,
}),
}),
)
)
// try to fetch the same chunk
// try to fetch the same chunk
rsrc
:=
fmt
.
Sprintf
(
"/chunks/"
+
addr
.
String
())
rsrc
:=
fmt
.
Sprintf
(
"/chunks/"
+
s
.
Address
()
.
String
())
resp
:=
request
(
t
,
client
,
http
.
MethodGet
,
rsrc
,
nil
,
http
.
StatusOK
)
resp
:=
request
(
t
,
client
,
http
.
MethodGet
,
rsrc
,
nil
,
http
.
StatusOK
)
data
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
data
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
ch
,
err
:=
s
.
ToChunk
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
bytes
.
Equal
(
ch
.
Data
(),
data
)
{
if
!
bytes
.
Equal
(
s
.
Chunk
()
.
Data
(),
data
)
{
t
.
Fatal
(
"data retrieved doesnt match uploaded content"
)
t
.
Fatal
(
"data retrieved doesn
'
t match uploaded content"
)
}
}
})
})
t
.
Run
(
"already exists"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"already exists"
,
func
(
t
*
testing
.
T
)
{
s
,
owner
,
payload
:=
mockSoc
(
t
)
s
:=
testingsoc
.
GenerateMockSOC
(
t
,
testData
)
id
:=
make
([]
byte
,
soc
.
IdSize
)
sig
:=
s
.
Signature
()
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
socResource
(
hex
.
EncodeToString
(
s
.
Owner
),
hex
.
EncodeToString
(
s
.
ID
),
hex
.
EncodeToString
(
s
.
Signature
)),
http
.
StatusCreated
,
addr
,
err
:=
s
.
Address
()
jsonhttptest
.
WithRequestBody
(
bytes
.
NewReader
(
s
.
WrappedChunk
.
Data
())),
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
socResource
(
hex
.
EncodeToString
(
owner
),
hex
.
EncodeToString
(
id
),
hex
.
EncodeToString
(
sig
)),
http
.
StatusCreated
,
jsonhttptest
.
WithRequestBody
(
bytes
.
NewReader
(
payload
)),
jsonhttptest
.
WithExpectedJSONResponse
(
api
.
SocPostResponse
{
jsonhttptest
.
WithExpectedJSONResponse
(
api
.
SocPostResponse
{
Reference
:
addr
,
Reference
:
s
.
Address
()
,
}),
}),
)
)
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
socResource
(
hex
.
EncodeToString
(
owner
),
hex
.
EncodeToString
(
id
),
hex
.
EncodeToString
(
sig
)),
http
.
StatusConflict
,
jsonhttptest
.
Request
(
t
,
client
,
http
.
MethodPost
,
socResource
(
hex
.
EncodeToString
(
s
.
Owner
),
hex
.
EncodeToString
(
s
.
ID
),
hex
.
EncodeToString
(
s
.
Signature
)),
http
.
StatusConflict
,
jsonhttptest
.
WithRequestBody
(
bytes
.
NewReader
(
payload
)),
jsonhttptest
.
WithRequestBody
(
bytes
.
NewReader
(
s
.
WrappedChunk
.
Data
()
)),
jsonhttptest
.
WithExpectedJSONResponse
(
jsonhttptest
.
WithExpectedJSONResponse
(
jsonhttp
.
StatusResponse
{
jsonhttp
.
StatusResponse
{
Message
:
"chunk already exists"
,
Message
:
"chunk already exists"
,
...
@@ -149,38 +131,4 @@ func TestSoc(t *testing.T) {
...
@@ -149,38 +131,4 @@ func TestSoc(t *testing.T) {
}),
}),
)
)
})
})
}
// returns a valid, mocked SOC
func
mockSoc
(
t
*
testing
.
T
)
(
*
soc
.
Soc
,
[]
byte
,
[]
byte
)
{
// create a valid soc
id
:=
make
([]
byte
,
soc
.
IdSize
)
privKey
,
err
:=
crypto
.
GenerateSecp256k1Key
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
signer
:=
crypto
.
NewDefaultSigner
(
privKey
)
bmtHashOfFoo
:=
"2387e8e7d8a48c2a9339c97c1dc3461a9a7aa07e994c5cb8b38fd7c1b3e6ea48"
address
:=
swarm
.
MustParseHexAddress
(
bmtHashOfFoo
)
foo
:=
"foo"
fooLength
:=
len
(
foo
)
fooBytes
:=
make
([]
byte
,
8
+
fooLength
)
binary
.
LittleEndian
.
PutUint64
(
fooBytes
,
uint64
(
fooLength
))
copy
(
fooBytes
[
8
:
],
foo
)
ch
:=
swarm
.
NewChunk
(
address
,
fooBytes
)
sch
:=
soc
.
New
(
id
,
ch
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
err
=
sch
.
AddSigner
(
signer
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
_
,
_
=
sch
.
ToChunk
()
return
sch
,
sch
.
OwnerAddress
(),
ch
.
Data
()
}
}
pkg/feeds/feed.go
View file @
1de167ea
...
@@ -112,10 +112,16 @@ func NewUpdate(f *Feed, idx Index, timestamp int64, payload []byte, sig []byte)
...
@@ -112,10 +112,16 @@ func NewUpdate(f *Feed, idx Index, timestamp int64, payload []byte, sig []byte)
return
nil
,
fmt
.
Errorf
(
"toChunk: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"toChunk: %w"
,
err
)
}
}
ch
,
err
:=
soc
.
NewSignedChunk
(
id
,
cac
,
f
.
Owner
.
Bytes
(),
sig
)
ss
,
err
:=
soc
.
NewSigned
(
id
,
cac
,
f
.
Owner
.
Bytes
(),
sig
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"new signed soc: %w"
,
err
)
}
ch
,
err
:=
ss
.
Chunk
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"new chunk: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"new chunk: %w"
,
err
)
}
}
if
!
soc
.
Valid
(
ch
)
{
if
!
soc
.
Valid
(
ch
)
{
return
nil
,
storage
.
ErrInvalidChunk
return
nil
,
storage
.
ErrInvalidChunk
}
}
...
@@ -135,7 +141,6 @@ func Id(topic []byte, index Index) ([]byte, error) {
...
@@ -135,7 +141,6 @@ func Id(topic []byte, index Index) ([]byte, error) {
}
}
i
:=
&
id
{
topic
,
indexBytes
}
i
:=
&
id
{
topic
,
indexBytes
}
return
i
.
MarshalBinary
()
return
i
.
MarshalBinary
()
}
}
// Address calculates the soc address of a feed update
// Address calculates the soc address of a feed update
...
@@ -145,9 +150,5 @@ func (u *Update) Address() (swarm.Address, error) {
...
@@ -145,9 +150,5 @@ func (u *Update) Address() (swarm.Address, error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
addr
,
err
return
addr
,
err
}
}
owner
,
err
:=
soc
.
NewOwner
(
u
.
Owner
[
:
])
return
soc
.
CreateAddress
(
i
,
u
.
Owner
[
:
])
if
err
!=
nil
{
return
addr
,
err
}
return
soc
.
CreateAddress
(
i
,
owner
)
}
}
pkg/feeds/getter.go
View file @
1de167ea
...
@@ -55,7 +55,7 @@ func FromChunk(ch swarm.Chunk) (uint64, []byte, error) {
...
@@ -55,7 +55,7 @@ func FromChunk(ch swarm.Chunk) (uint64, []byte, error) {
if
err
!=
nil
{
if
err
!=
nil
{
return
0
,
nil
,
err
return
0
,
nil
,
err
}
}
cac
:=
s
.
Chunk
cac
:=
s
.
WrappedChunk
()
if
len
(
cac
.
Data
())
<
16
{
if
len
(
cac
.
Data
())
<
16
{
return
0
,
nil
,
fmt
.
Errorf
(
"feed update payload too short"
)
return
0
,
nil
,
fmt
.
Errorf
(
"feed update payload too short"
)
}
}
...
...
pkg/feeds/putter.go
View file @
1de167ea
...
@@ -48,7 +48,8 @@ func (u *Putter) Put(ctx context.Context, i Index, at int64, payload []byte) err
...
@@ -48,7 +48,8 @@ func (u *Putter) Put(ctx context.Context, i Index, at int64, payload []byte) err
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
ch
,
err
:=
soc
.
NewChunk
(
id
,
cac
,
u
.
signer
)
s
:=
soc
.
New
(
id
,
cac
)
ch
,
err
:=
s
.
Sign
(
u
.
signer
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
err
}
}
...
...
pkg/soc/export_test.go
View file @
1de167ea
...
@@ -5,6 +5,22 @@
...
@@ -5,6 +5,22 @@
package
soc
package
soc
var
(
var
(
ToSignDigest
=
toSignDigest
ErrInvalidAddress
=
errInvalidAddress
RecoverAddress
=
recoverAddress
Hash
=
hash
RecoverAddress
=
recoverAddress
)
)
// Signature returns the SOC signature.
func
(
s
*
SOC
)
Signature
()
[]
byte
{
return
s
.
signature
}
// OwnerAddress returns the ethereum address of the SOC owner.
func
(
s
*
SOC
)
OwnerAddress
()
[]
byte
{
return
s
.
owner
}
// ID returns the SOC id.
func
(
s
*
SOC
)
ID
()
[]
byte
{
return
s
.
id
}
pkg/soc/soc.go
View file @
1de167ea
...
@@ -2,14 +2,13 @@
...
@@ -2,14 +2,13 @@
// Use of this source code is governed by a BSD-style
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// license that can be found in the LICENSE file.
// Package soc provides the single-owner chunk implemenation
// Package soc provides the single-owner chunk implemen
t
ation
// and validator.
// and validator.
package
soc
package
soc
import
(
import
(
"bytes"
"bytes"
"errors"
"errors"
"fmt"
"github.com/ethersphere/bee/pkg/cac"
"github.com/ethersphere/bee/pkg/cac"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/crypto"
...
@@ -22,130 +21,118 @@ const (
...
@@ -22,130 +21,118 @@ const (
minChunkSize
=
IdSize
+
SignatureSize
+
swarm
.
SpanSize
minChunkSize
=
IdSize
+
SignatureSize
+
swarm
.
SpanSize
)
)
// Id is a soc identifier
var
(
type
Id
[]
byte
errInvalidAddress
=
errors
.
New
(
"soc: invalid address"
)
errWrongChunkSize
=
errors
.
New
(
"soc: chunk length is less than minimum"
)
// Owner is a wrapper that enforces valid length address of soc owner.
)
type
Owner
struct
{
address
[]
byte
}
// NewOwner creates a new Owner.
// ID is a SOC identifier
func
NewOwner
(
address
[]
byte
)
(
*
Owner
,
error
)
{
type
ID
[]
byte
if
len
(
address
)
!=
crypto
.
AddressSize
{
return
nil
,
fmt
.
Errorf
(
"invalid address %x"
,
address
)
}
return
&
Owner
{
address
:
address
,
},
nil
}
// Soc wraps a single soc.
// SOC wraps a content-addressed chunk.
type
Soc
struct
{
type
SOC
struct
{
id
Id
id
ID
owner
[]
byte
// owner is the address in bytes of SOC owner.
signature
[]
byte
signature
[]
byte
signer
crypto
.
Signer
chunk
swarm
.
Chunk
// wrapped chunk.
owner
*
Owner
Chunk
swarm
.
Chunk
}
}
// NewChunk is a convenience function to create a single-owner chunk ready to be sent
// New creates a new SOC representation from arbitrary id and
// on the network.
// a content-addressed chunk.
func
NewChunk
(
id
Id
,
ch
swarm
.
Chunk
,
signer
crypto
.
Signer
)
(
swarm
.
Chunk
,
error
)
{
func
New
(
id
ID
,
ch
swarm
.
Chunk
)
*
SOC
{
s
:=
New
(
id
,
ch
)
return
&
SOC
{
err
:=
s
.
AddSigner
(
signer
)
id
:
id
,
if
err
!=
nil
{
chunk
:
ch
,
return
nil
,
err
}
}
return
s
.
ToChunk
()
}
}
// NewChunk is a convenience function to create a single-owner chunk ready to be sent
// NewSigned creates a single-owner chunk based on already signed data.
// on the network.
func
NewSigned
(
id
ID
,
ch
swarm
.
Chunk
,
owner
,
sig
[]
byte
)
(
*
SOC
,
error
)
{
func
NewSignedChunk
(
id
Id
,
ch
swarm
.
Chunk
,
owner
,
sig
[]
byte
)
(
swarm
.
Chunk
,
error
)
{
s
:=
New
(
id
,
ch
)
s
:=
New
(
id
,
ch
)
if
len
(
owner
)
!=
crypto
.
AddressSize
{
return
nil
,
errInvalidAddress
}
s
.
owner
=
owner
s
.
signature
=
sig
s
.
signature
=
sig
o
,
err
:=
NewOwner
(
owner
)
return
s
,
nil
if
err
!=
nil
{
}
return
nil
,
err
// address returns the SOC chunk address.
func
(
s
*
SOC
)
address
()
(
swarm
.
Address
,
error
)
{
if
len
(
s
.
owner
)
!=
crypto
.
AddressSize
{
return
swarm
.
ZeroAddress
,
errInvalidAddress
}
}
s
.
owner
=
o
return
CreateAddress
(
s
.
id
,
s
.
owner
)
}
// create chunk
// WrappedChunk returns the chunk wrapped by the SOC.
socAddress
,
err
:=
s
.
Address
()
func
(
s
*
SOC
)
WrappedChunk
()
swarm
.
Chunk
{
return
s
.
chunk
}
// Chunk returns the SOC chunk.
func
(
s
*
SOC
)
Chunk
()
(
swarm
.
Chunk
,
error
)
{
socAddress
,
err
:=
s
.
address
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
return
swarm
.
NewChunk
(
socAddress
,
s
.
toBytes
()),
nil
return
swarm
.
NewChunk
(
socAddress
,
s
.
toBytes
()),
nil
}
}
// New creates a new Soc representation from arbitrary soc id and
// toBytes is a helper function to convert the SOC data to bytes.
// a content-addressed chunk.
func
(
s
*
SOC
)
toBytes
()
[]
byte
{
//
buf
:=
bytes
.
NewBuffer
(
nil
)
// By default the span of the soc data is set to the length
buf
.
Write
(
s
.
id
)
// of the payload.
buf
.
Write
(
s
.
signature
)
func
New
(
id
Id
,
ch
swarm
.
Chunk
)
*
Soc
{
buf
.
Write
(
s
.
chunk
.
Data
())
return
&
Soc
{
return
buf
.
Bytes
()
id
:
id
,
Chunk
:
ch
,
}
}
// WithOwnerAddress provides the possibility of setting the ethereum
// address for the owner of an soc in the absence of a signer.
func
(
s
*
Soc
)
WithOwnerAddress
(
ownerAddress
*
Owner
)
*
Soc
{
s
.
owner
=
ownerAddress
return
s
}
}
// AddSigner currently sets a single signer for the soc.
// Sign signs a SOC using the given signer.
//
// It returns a signed SOC chunk ready for submission to the network.
// This method will overwrite any value set with WithOwnerAddress with
func
(
s
*
SOC
)
Sign
(
signer
crypto
.
Signer
)
(
swarm
.
Chunk
,
error
)
{
// the address derived from the given signer.
// create owner
func
(
s
*
Soc
)
AddSigner
(
signer
crypto
.
Signer
)
error
{
publicKey
,
err
:=
signer
.
PublicKey
()
publicKey
,
err
:=
signer
.
PublicKey
()
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
nil
,
err
}
}
ownerAddressBytes
,
err
:=
crypto
.
NewEthereumAddress
(
*
publicKey
)
ownerAddressBytes
,
err
:=
crypto
.
NewEthereumAddress
(
*
publicKey
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
nil
,
err
}
}
ownerAddress
,
err
:=
NewOwner
(
ownerAddressBytes
)
if
len
(
ownerAddressBytes
)
!=
crypto
.
AddressSize
{
if
err
!=
nil
{
return
nil
,
errInvalidAddress
return
err
}
}
s
.
signer
=
signer
s
.
owner
=
ownerAddressBytes
s
.
owner
=
ownerAddress
return
nil
}
// OwnerAddress returns the ethereum address of the signer of the Chunk.
// generate the data to sign
func
(
s
*
Soc
)
OwnerAddress
()
[]
byte
{
toSignBytes
,
err
:=
hash
(
s
.
id
,
s
.
chunk
.
Address
()
.
Bytes
())
return
s
.
owner
.
address
if
err
!=
nil
{
}
return
nil
,
err
}
// Address returns the soc Chunk address.
// sign the chunk
func
(
s
*
Soc
)
Address
()
(
swarm
.
Address
,
error
)
{
signature
,
err
:=
signer
.
Sign
(
toSignBytes
)
return
CreateAddress
(
s
.
id
,
s
.
owner
)
if
err
!=
nil
{
}
return
nil
,
err
}
s
.
signature
=
signature
func
(
s
*
Soc
)
Signature
()
[]
byte
{
return
s
.
Chunk
()
return
s
.
signature
}
}
// FromChunk recreates a
n Soc
representation from swarm.Chunk data.
// FromChunk recreates a
SOC
representation from swarm.Chunk data.
func
FromChunk
(
sch
swarm
.
Chunk
)
(
*
S
oc
,
error
)
{
func
FromChunk
(
sch
swarm
.
Chunk
)
(
*
S
OC
,
error
)
{
chunkData
:=
sch
.
Data
()
chunkData
:=
sch
.
Data
()
if
len
(
chunkData
)
<
minChunkSize
{
if
len
(
chunkData
)
<
minChunkSize
{
return
nil
,
err
ors
.
New
(
"less than minimum length"
)
return
nil
,
err
WrongChunkSize
}
}
// add all the data fields
// add all the data fields
to the SOC
s
:=
&
S
oc
{}
s
:=
&
S
OC
{}
cursor
:=
0
cursor
:=
0
s
.
id
=
chunkData
[
cursor
:
cursor
+
IdSize
]
s
.
id
=
chunkData
[
cursor
:
IdSize
]
cursor
+=
IdSize
cursor
+=
IdSize
s
.
signature
=
chunkData
[
cursor
:
cursor
+
SignatureSize
]
s
.
signature
=
chunkData
[
cursor
:
cursor
+
SignatureSize
]
...
@@ -156,94 +143,48 @@ func FromChunk(sch swarm.Chunk) (*Soc, error) {
...
@@ -156,94 +143,48 @@ func FromChunk(sch swarm.Chunk) (*Soc, error) {
return
nil
,
err
return
nil
,
err
}
}
toSignBytes
,
err
:=
toSignDigest
(
s
.
id
,
ch
.
Address
()
.
Bytes
())
toSignBytes
,
err
:=
hash
(
s
.
id
,
ch
.
Address
()
.
Bytes
())
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
// recover owner information
// recover owner information
recovered
Ethereum
Address
,
err
:=
recoverAddress
(
s
.
signature
,
toSignBytes
)
recovered
Owner
Address
,
err
:=
recoverAddress
(
s
.
signature
,
toSignBytes
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
owner
,
err
:=
NewOwner
(
recoveredEthereumAddress
)
if
len
(
recoveredOwnerAddress
)
!=
crypto
.
AddressSize
{
if
err
!=
nil
{
return
nil
,
errInvalidAddress
return
nil
,
err
}
}
s
.
owner
=
owner
s
.
owner
=
recoveredOwnerAddress
s
.
C
hunk
=
ch
s
.
c
hunk
=
ch
return
s
,
nil
return
s
,
nil
}
}
// ToChunk generates a signed chunk payload ready for submission to the swarm network.
// CreateAddress creates a new SOC address from the id and
//
// the ethereum address of the owner.
// The method will fail if no signer has been added.
func
CreateAddress
(
id
ID
,
owner
[]
byte
)
(
swarm
.
Address
,
error
)
{
func
(
s
*
Soc
)
ToChunk
()
(
swarm
.
Chunk
,
error
)
{
sum
,
err
:=
hash
(
id
,
owner
)
var
err
error
if
s
.
signer
==
nil
{
return
nil
,
errors
.
New
(
"signer missing"
)
}
// generate the data to sign
toSignBytes
,
err
:=
toSignDigest
(
s
.
id
,
s
.
Chunk
.
Address
()
.
Bytes
())
if
err
!=
nil
{
return
nil
,
err
}
// sign the chunk
signature
,
err
:=
s
.
signer
.
Sign
(
toSignBytes
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
swarm
.
ZeroAddress
,
err
}
s
.
signature
=
signature
// create chunk
socAddress
,
err
:=
s
.
Address
()
if
err
!=
nil
{
return
nil
,
err
}
}
return
swarm
.
NewChunk
(
socAddress
,
s
.
toBytes
()),
nil
return
swarm
.
NewAddress
(
sum
),
nil
}
func
(
s
*
Soc
)
toBytes
()
[]
byte
{
buf
:=
bytes
.
NewBuffer
(
nil
)
buf
.
Write
(
s
.
id
)
buf
.
Write
(
s
.
signature
)
buf
.
Write
(
s
.
Chunk
.
Data
())
return
buf
.
Bytes
()
}
}
//
toSignDigest creates a digest suitable for signing to represent the soc
.
//
hash hashes the given values in order
.
func
toSignDigest
(
id
Id
,
sum
[]
byte
)
([]
byte
,
error
)
{
func
hash
(
values
...
[]
byte
)
([]
byte
,
error
)
{
h
:=
swarm
.
NewHasher
()
h
:=
swarm
.
NewHasher
()
_
,
err
:=
h
.
Write
(
id
)
for
_
,
v
:=
range
values
{
if
err
!=
nil
{
_
,
err
:=
h
.
Write
(
v
)
return
nil
,
err
if
err
!=
nil
{
}
return
nil
,
err
_
,
err
=
h
.
Write
(
sum
)
}
if
err
!=
nil
{
return
nil
,
err
}
}
return
h
.
Sum
(
nil
),
nil
return
h
.
Sum
(
nil
),
nil
}
}
// CreateAddress creates a new soc address from the soc id and the ethereum address of the signer
// recoverAddress returns the ethereum address of the owner of a SOC.
func
CreateAddress
(
id
Id
,
owner
*
Owner
)
(
swarm
.
Address
,
error
)
{
h
:=
swarm
.
NewHasher
()
_
,
err
:=
h
.
Write
(
id
)
if
err
!=
nil
{
return
swarm
.
ZeroAddress
,
err
}
_
,
err
=
h
.
Write
(
owner
.
address
)
if
err
!=
nil
{
return
swarm
.
ZeroAddress
,
err
}
sum
:=
h
.
Sum
(
nil
)
return
swarm
.
NewAddress
(
sum
),
nil
}
// recoverOwner returns the ethereum address of the owner of an soc.
func
recoverAddress
(
signature
,
digest
[]
byte
)
([]
byte
,
error
)
{
func
recoverAddress
(
signature
,
digest
[]
byte
)
([]
byte
,
error
)
{
recoveredPublicKey
,
err
:=
crypto
.
Recover
(
signature
,
digest
)
recoveredPublicKey
,
err
:=
crypto
.
Recover
(
signature
,
digest
)
if
err
!=
nil
{
if
err
!=
nil
{
...
...
pkg/soc/soc_test.go
View file @
1de167ea
...
@@ -7,118 +7,315 @@ package soc_test
...
@@ -7,118 +7,315 @@ package soc_test
import
(
import
(
"bytes"
"bytes"
"encoding/binary"
"encoding/binary"
"encoding/hex"
"errors"
"testing"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethersphere/bee/pkg/cac"
"github.com/ethersphere/bee/pkg/cac"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/soc"
"github.com/ethersphere/bee/pkg/soc"
"github.com/ethersphere/bee/pkg/swarm"
"github.com/ethersphere/bee/pkg/swarm"
)
)
// TestToChunk verifies that the chunk create from the Soc object
func
TestNew
(
t
*
testing
.
T
)
{
// corresponds to the soc spec.
payload
:=
[]
byte
(
"foo"
)
func
TestToChunk
(
t
*
testing
.
T
)
{
ch
,
err
:=
cac
.
New
(
payload
)
privKey
,
err
:=
crypto
.
GenerateSecp256k1Key
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
signer
:=
crypto
.
NewDefaultSigner
(
privKey
)
id
:=
make
([]
byte
,
32
)
id
:=
make
([]
byte
,
soc
.
IdSize
)
s
:=
soc
.
New
(
id
,
ch
)
// check SOC fields
if
!
bytes
.
Equal
(
s
.
ID
(),
id
)
{
t
.
Fatalf
(
"id mismatch. got %x want %x"
,
s
.
ID
(),
id
)
}
chunkData
:=
s
.
WrappedChunk
()
.
Data
()
spanBytes
:=
make
([]
byte
,
swarm
.
SpanSize
)
binary
.
LittleEndian
.
PutUint64
(
spanBytes
,
uint64
(
len
(
payload
)))
if
!
bytes
.
Equal
(
chunkData
[
:
swarm
.
SpanSize
],
spanBytes
)
{
t
.
Fatalf
(
"span mismatch. got %x want %x"
,
chunkData
[
:
swarm
.
SpanSize
],
spanBytes
)
}
if
!
bytes
.
Equal
(
chunkData
[
swarm
.
SpanSize
:
],
payload
)
{
t
.
Fatalf
(
"payload mismatch. got %x want %x"
,
chunkData
[
swarm
.
SpanSize
:
],
payload
)
}
}
func
TestNewSigned
(
t
*
testing
.
T
)
{
owner
:=
common
.
HexToAddress
(
"8d3766440f0d7b949a5e32995d09619a7f86e632"
)
// signature of hash(id + chunk address of foo)
sig
,
err
:=
hex
.
DecodeString
(
"5acd384febc133b7b245e5ddc62d82d2cded9182d2716126cd8844509af65a053deb418208027f548e3e88343af6f84a8772fb3cebc0a1833a0ea7ec0c1348311b"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
payload
:=
[]
byte
(
"foo"
)
payload
:=
[]
byte
(
"foo"
)
ch
,
err
:=
cac
.
New
(
payload
)
ch
,
err
:=
cac
.
New
(
payload
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
sch
,
err
:=
soc
.
NewChunk
(
id
,
ch
,
signer
)
id
:=
make
([]
byte
,
soc
.
IdSize
)
s
,
err
:=
soc
.
NewSigned
(
id
,
ch
,
owner
.
Bytes
(),
sig
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
chunkData
:=
sch
.
Data
()
// verify that id, signature, payload is in place
// check signed SOC fields
if
!
bytes
.
Equal
(
s
.
ID
(),
id
)
{
t
.
Fatalf
(
"id mismatch. got %x want %x"
,
s
.
ID
(),
id
)
}
if
!
bytes
.
Equal
(
s
.
OwnerAddress
(),
owner
.
Bytes
())
{
t
.
Fatalf
(
"owner mismatch. got %x want %x"
,
s
.
OwnerAddress
(),
owner
.
Bytes
())
}
if
!
bytes
.
Equal
(
s
.
Signature
(),
sig
)
{
t
.
Fatalf
(
"signature mismatch. got %x want %x"
,
s
.
Signature
(),
sig
)
}
chunkData
:=
s
.
WrappedChunk
()
.
Data
()
spanBytes
:=
make
([]
byte
,
swarm
.
SpanSize
)
binary
.
LittleEndian
.
PutUint64
(
spanBytes
,
uint64
(
len
(
payload
)))
if
!
bytes
.
Equal
(
chunkData
[
:
swarm
.
SpanSize
],
spanBytes
)
{
t
.
Fatalf
(
"span mismatch. got %x want %x"
,
chunkData
[
:
swarm
.
SpanSize
],
spanBytes
)
}
if
!
bytes
.
Equal
(
chunkData
[
swarm
.
SpanSize
:
],
payload
)
{
t
.
Fatalf
(
"payload mismatch. got %x want %x"
,
chunkData
[
swarm
.
SpanSize
:
],
payload
)
}
}
// TestChunk verifies that the chunk created from the SOC object
// corresponds to the SOC spec.
func
TestChunk
(
t
*
testing
.
T
)
{
owner
:=
common
.
HexToAddress
(
"8d3766440f0d7b949a5e32995d09619a7f86e632"
)
sig
,
err
:=
hex
.
DecodeString
(
"5acd384febc133b7b245e5ddc62d82d2cded9182d2716126cd8844509af65a053deb418208027f548e3e88343af6f84a8772fb3cebc0a1833a0ea7ec0c1348311b"
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
payload
:=
[]
byte
(
"foo"
)
ch
,
err
:=
cac
.
New
(
payload
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
id
:=
make
([]
byte
,
soc
.
IdSize
)
// creates a new signed SOC
s
,
err
:=
soc
.
NewSigned
(
id
,
ch
,
owner
.
Bytes
(),
sig
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
sum
,
err
:=
soc
.
Hash
(
id
,
owner
.
Bytes
())
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
expectedSOCAddress
:=
swarm
.
NewAddress
(
sum
)
// creates SOC chunk
sch
,
err
:=
s
.
Chunk
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
if
!
bytes
.
Equal
(
sch
.
Address
()
.
Bytes
(),
expectedSOCAddress
.
Bytes
())
{
t
.
Fatalf
(
"soc address mismatch. got %x want %x"
,
sch
.
Address
()
.
Bytes
(),
expectedSOCAddress
.
Bytes
())
}
chunkData
:=
sch
.
Data
()
// verifies that id, signature, payload is in place in the SOC chunk
cursor
:=
0
cursor
:=
0
if
!
bytes
.
Equal
(
chunkData
[
cursor
:
cursor
+
soc
.
IdSize
],
id
)
{
if
!
bytes
.
Equal
(
chunkData
[
cursor
:
soc
.
IdSize
],
id
)
{
t
.
Fatal
(
"id mismatch"
)
t
.
Fatal
f
(
"id mismatch. got %x want %x"
,
chunkData
[
cursor
:
soc
.
IdSize
],
id
)
}
}
cursor
+=
soc
.
IdSize
cursor
+=
soc
.
IdSize
signature
:=
chunkData
[
cursor
:
cursor
+
soc
.
SignatureSize
]
signature
:=
chunkData
[
cursor
:
cursor
+
soc
.
SignatureSize
]
if
!
bytes
.
Equal
(
signature
,
sig
)
{
t
.
Fatalf
(
"signature mismatch. got %x want %x"
,
signature
,
sig
)
}
cursor
+=
soc
.
SignatureSize
cursor
+=
soc
.
SignatureSize
spanBytes
:=
make
([]
byte
,
8
)
spanBytes
:=
make
([]
byte
,
swarm
.
SpanSize
)
binary
.
LittleEndian
.
PutUint64
(
spanBytes
,
uint64
(
len
(
payload
)))
binary
.
LittleEndian
.
PutUint64
(
spanBytes
,
uint64
(
len
(
payload
)))
if
!
bytes
.
Equal
(
chunkData
[
cursor
:
cursor
+
swarm
.
SpanSize
],
spanBytes
)
{
if
!
bytes
.
Equal
(
chunkData
[
cursor
:
cursor
+
swarm
.
SpanSize
],
spanBytes
)
{
t
.
Fatal
(
"span mismatch"
)
t
.
Fatal
f
(
"span mismatch. got %x want %x"
,
chunkData
[
cursor
:
cursor
+
swarm
.
SpanSize
],
spanBytes
)
}
}
cursor
+=
swarm
.
SpanSize
cursor
+=
swarm
.
SpanSize
if
!
bytes
.
Equal
(
chunkData
[
cursor
:
],
payload
)
{
if
!
bytes
.
Equal
(
chunkData
[
cursor
:
],
payload
)
{
t
.
Fatal
(
"payload mismatch"
)
t
.
Fatalf
(
"payload mismatch. got %x want %x"
,
chunkData
[
cursor
:
],
payload
)
}
}
func
TestChunkErrorWithoutOwner
(
t
*
testing
.
T
)
{
payload
:=
[]
byte
(
"foo"
)
ch
,
err
:=
cac
.
New
(
payload
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
id
:=
make
([]
byte
,
soc
.
IdSize
)
// creates a new soc
s
:=
soc
.
New
(
id
,
ch
)
_
,
err
=
s
.
Chunk
()
if
!
errors
.
Is
(
err
,
soc
.
ErrInvalidAddress
)
{
t
.
Fatalf
(
"expect error. got `%v` want `%v`"
,
err
,
soc
.
ErrInvalidAddress
)
}
}
}
// TestSign tests whether a soc is correctly signed.
func
TestSign
(
t
*
testing
.
T
)
{
privKey
,
err
:=
crypto
.
GenerateSecp256k1Key
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
signer
:=
crypto
.
NewDefaultSigner
(
privKey
)
// get the public key of the signer that was used
payload
:=
[]
byte
(
"foo"
)
ch
,
err
:=
cac
.
New
(
payload
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
id
:=
make
([]
byte
,
soc
.
IdSize
)
// creates the soc
s
:=
soc
.
New
(
id
,
ch
)
// signs the chunk
sch
,
err
:=
s
.
Sign
(
signer
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
chunkData
:=
sch
.
Data
()
// get signature in the chunk
cursor
:=
soc
.
IdSize
signature
:=
chunkData
[
cursor
:
cursor
+
soc
.
SignatureSize
]
// get the public key of the signer
publicKey
,
err
:=
signer
.
PublicKey
()
publicKey
,
err
:=
signer
.
PublicKey
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
ethereumAddress
,
err
:=
crypto
.
NewEthereumAddress
(
*
publicKey
)
owner
,
err
:=
crypto
.
NewEthereumAddress
(
*
publicKey
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
toSignBytes
,
err
:=
soc
.
ToSignDigest
(
id
,
ch
.
Address
()
.
Bytes
())
toSignBytes
,
err
:=
soc
.
Hash
(
id
,
ch
.
Address
()
.
Bytes
())
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
// verif
y owner match
// verif
ies if the owner matches
recovered
EthereumAddress
,
err
:=
soc
.
RecoverAddress
(
signature
,
toSignBytes
)
recovered
Owner
,
err
:=
soc
.
RecoverAddress
(
signature
,
toSignBytes
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
if
!
bytes
.
Equal
(
recoveredEthereumAddress
,
ethereumAddress
)
{
t
.
Fatalf
(
"address mismatch %x %x"
,
recoveredEthereumAddress
,
ethereumAddress
)
if
!
bytes
.
Equal
(
recoveredOwner
,
owner
)
{
t
.
Fatalf
(
"owner address mismatch. got %x want %x"
,
recoveredOwner
,
owner
)
}
}
}
}
// TestFromChunk verifies that valid chunk data deserializes to
// TestFromChunk verifies that valid chunk data deserializes to
// a fully populated
Chunk
object.
// a fully populated
soc
object.
func
TestFromChunk
(
t
*
testing
.
T
)
{
func
TestFromChunk
(
t
*
testing
.
T
)
{
privKey
,
err
:=
crypto
.
GenerateSecp256k1Key
()
socAddress
:=
swarm
.
MustParseHexAddress
(
"9d453ebb73b2fedaaf44ceddcf7a0aa37f3e3d6453fea5841c31f0ea6d61dc85"
)
// signed soc chunk of:
// id: 0
// wrapped chunk of: `foo`
// owner: 0x8d3766440f0d7b949a5e32995d09619a7f86e632
sch
:=
swarm
.
NewChunk
(
socAddress
,
[]
byte
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
90
,
205
,
56
,
79
,
235
,
193
,
51
,
183
,
178
,
69
,
229
,
221
,
198
,
45
,
130
,
210
,
205
,
237
,
145
,
130
,
210
,
113
,
97
,
38
,
205
,
136
,
68
,
80
,
154
,
246
,
90
,
5
,
61
,
235
,
65
,
130
,
8
,
2
,
127
,
84
,
142
,
62
,
136
,
52
,
58
,
246
,
248
,
74
,
135
,
114
,
251
,
60
,
235
,
192
,
161
,
131
,
58
,
14
,
167
,
236
,
12
,
19
,
72
,
49
,
27
,
3
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
102
,
111
,
111
})
cursor
:=
soc
.
IdSize
+
soc
.
SignatureSize
data
:=
sch
.
Data
()
id
:=
data
[
:
soc
.
IdSize
]
sig
:=
data
[
soc
.
IdSize
:
cursor
]
chunkData
:=
data
[
cursor
:
]
chunkAddress
:=
swarm
.
MustParseHexAddress
(
"2387e8e7d8a48c2a9339c97c1dc3461a9a7aa07e994c5cb8b38fd7c1b3e6ea48"
)
ch
:=
swarm
.
NewChunk
(
chunkAddress
,
chunkData
)
signedDigest
,
err
:=
soc
.
Hash
(
id
,
ch
.
Address
()
.
Bytes
())
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
signer
:=
crypto
.
NewDefaultSigner
(
privKey
)
id
:=
make
([]
byte
,
32
)
ownerAddress
,
err
:=
soc
.
RecoverAddress
(
sig
,
signedDigest
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
payload
:=
[]
byte
(
"foo"
)
// attempt to recover soc from signed chunk
ch
,
err
:=
cac
.
New
(
payload
)
recoveredSOC
,
err
:=
soc
.
FromChunk
(
sch
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
sch
,
err
:=
soc
.
NewChunk
(
id
,
ch
,
signer
)
// owner matching means the address was successfully recovered from
// payload and signature
if
!
bytes
.
Equal
(
recoveredSOC
.
OwnerAddress
(),
ownerAddress
)
{
t
.
Fatalf
(
"owner address mismatch. got %x want %x"
,
recoveredSOC
.
OwnerAddress
(),
ownerAddress
)
}
if
!
bytes
.
Equal
(
recoveredSOC
.
ID
(),
id
)
{
t
.
Fatalf
(
"id mismatch. got %x want %x"
,
recoveredSOC
.
ID
(),
id
)
}
if
!
bytes
.
Equal
(
recoveredSOC
.
Signature
(),
sig
)
{
t
.
Fatalf
(
"signature mismatch. got %x want %x"
,
recoveredSOC
.
Signature
(),
sig
)
}
if
!
ch
.
Equal
(
recoveredSOC
.
WrappedChunk
())
{
t
.
Fatalf
(
"wrapped chunk mismatch. got %s want %s"
,
recoveredSOC
.
WrappedChunk
()
.
Address
(),
ch
.
Address
())
}
}
func
TestCreateAddress
(
t
*
testing
.
T
)
{
id
:=
make
([]
byte
,
soc
.
IdSize
)
owner
:=
common
.
HexToAddress
(
"8d3766440f0d7b949a5e32995d09619a7f86e632"
)
socAddress
:=
swarm
.
MustParseHexAddress
(
"9d453ebb73b2fedaaf44ceddcf7a0aa37f3e3d6453fea5841c31f0ea6d61dc85"
)
addr
,
err
:=
soc
.
CreateAddress
(
id
,
owner
.
Bytes
())
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
if
!
addr
.
Equal
(
socAddress
)
{
t
.
Fatalf
(
"soc address mismatch. got %s want %s"
,
addr
,
socAddress
)
}
}
u2
,
err
:=
soc
.
FromChunk
(
sch
)
func
TestRecoverAddress
(
t
*
testing
.
T
)
{
owner
:=
common
.
HexToAddress
(
"8d3766440f0d7b949a5e32995d09619a7f86e632"
)
id
:=
make
([]
byte
,
soc
.
IdSize
)
chunkAddress
:=
swarm
.
MustParseHexAddress
(
"2387e8e7d8a48c2a9339c97c1dc3461a9a7aa07e994c5cb8b38fd7c1b3e6ea48"
)
signedDigest
,
err
:=
soc
.
Hash
(
id
,
chunkAddress
.
Bytes
())
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
// owner matching means the address was successfully recovered from
sig
,
err
:=
hex
.
DecodeString
(
"5acd384febc133b7b245e5ddc62d82d2cded9182d2716126cd8844509af65a053deb418208027f548e3e88343af6f84a8772fb3cebc0a1833a0ea7ec0c1348311b"
)
// payload and signature
publicKey
,
err
:=
signer
.
PublicKey
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
ownerEthereumAddress
,
err
:=
crypto
.
NewEthereumAddress
(
*
publicKey
)
// attempt to recover address from signature
addr
,
err
:=
soc
.
RecoverAddress
(
sig
,
signedDigest
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
}
}
if
!
bytes
.
Equal
(
ownerEthereumAddress
,
u2
.
OwnerAddres
s
())
{
if
!
bytes
.
Equal
(
addr
,
owner
.
Byte
s
())
{
t
.
Fatalf
(
"owner address mismatch
%x %x"
,
ownerEthereumAddress
,
u2
.
OwnerAddres
s
())
t
.
Fatalf
(
"owner address mismatch
. got %x want %x"
,
addr
,
owner
.
Byte
s
())
}
}
}
}
pkg/soc/testing/soc.go
0 → 100644
View file @
1de167ea
// Copyright 2021 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
testing
import
(
"testing"
"github.com/ethersphere/bee/pkg/cac"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/soc"
"github.com/ethersphere/bee/pkg/swarm"
)
// MockSOC defines a mocked SOC with exported fields for easy testing.
type
MockSOC
struct
{
ID
soc
.
ID
Owner
[]
byte
Signature
[]
byte
WrappedChunk
swarm
.
Chunk
}
// Address returns the SOC address of the mocked SOC.
func
(
ms
MockSOC
)
Address
()
swarm
.
Address
{
addr
,
_
:=
soc
.
CreateAddress
(
ms
.
ID
,
ms
.
Owner
)
return
addr
}
// Chunk returns the SOC chunk of the mocked SOC.
func
(
ms
MockSOC
)
Chunk
()
swarm
.
Chunk
{
return
swarm
.
NewChunk
(
ms
.
Address
(),
append
(
ms
.
ID
,
append
(
ms
.
Signature
,
ms
.
WrappedChunk
.
Data
()
...
)
...
))
}
// GenerateMockSOC generates a valid mocked SOC from given data.
func
GenerateMockSOC
(
t
*
testing
.
T
,
data
[]
byte
)
*
MockSOC
{
t
.
Helper
()
privKey
,
err
:=
crypto
.
GenerateSecp256k1Key
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
signer
:=
crypto
.
NewDefaultSigner
(
privKey
)
owner
,
err
:=
signer
.
EthereumAddress
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
ch
,
err
:=
cac
.
New
(
data
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
id
:=
make
([]
byte
,
soc
.
IdSize
)
hasher
:=
swarm
.
NewHasher
()
_
,
err
=
hasher
.
Write
(
append
(
id
,
ch
.
Address
()
.
Bytes
()
...
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
signature
,
err
:=
signer
.
Sign
(
hasher
.
Sum
(
nil
))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
return
&
MockSOC
{
ID
:
id
,
Owner
:
owner
.
Bytes
(),
Signature
:
signature
,
WrappedChunk
:
ch
,
}
}
pkg/soc/validator.go
View file @
1de167ea
...
@@ -15,7 +15,7 @@ func Valid(ch swarm.Chunk) bool {
...
@@ -15,7 +15,7 @@ func Valid(ch swarm.Chunk) bool {
return
false
return
false
}
}
address
,
err
:=
s
.
A
ddress
()
address
,
err
:=
s
.
a
ddress
()
if
err
!=
nil
{
if
err
!=
nil
{
return
false
return
false
}
}
...
...
pkg/soc/validator_test.go
View file @
1de167ea
...
@@ -5,57 +5,110 @@
...
@@ -5,57 +5,110 @@
package
soc_test
package
soc_test
import
(
import
(
"
encoding/binary
"
"
strings
"
"testing"
"testing"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/soc"
"github.com/ethersphere/bee/pkg/soc"
"github.com/ethersphere/bee/pkg/swarm"
"github.com/ethersphere/bee/pkg/swarm"
)
)
// TestValidator verifies that the validator can detect both
// TestValid verifies that the validator can detect
// valid soc chunks, as well as chunks with invalid data and invalid
// valid soc chunks.
// address.
func
TestValid
(
t
*
testing
.
T
)
{
func
TestValidator
(
t
*
testing
.
T
)
{
socAddress
:=
swarm
.
MustParseHexAddress
(
"9d453ebb73b2fedaaf44ceddcf7a0aa37f3e3d6453fea5841c31f0ea6d61dc85"
)
id
:=
make
([]
byte
,
soc
.
IdSize
)
privKey
,
err
:=
crypto
.
GenerateSecp256k1Key
()
// signed soc chunk of:
if
err
!=
nil
{
// id: 0
t
.
Fatal
(
err
)
// wrapped chunk of: `foo`
}
// owner: 0x8d3766440f0d7b949a5e32995d09619a7f86e632
signer
:=
crypto
.
NewDefaultSigner
(
privKey
)
sch
:=
swarm
.
NewChunk
(
socAddress
,
[]
byte
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
90
,
205
,
56
,
79
,
235
,
193
,
51
,
183
,
178
,
69
,
229
,
221
,
198
,
45
,
130
,
210
,
205
,
237
,
145
,
130
,
210
,
113
,
97
,
38
,
205
,
136
,
68
,
80
,
154
,
246
,
90
,
5
,
61
,
235
,
65
,
130
,
8
,
2
,
127
,
84
,
142
,
62
,
136
,
52
,
58
,
246
,
248
,
74
,
135
,
114
,
251
,
60
,
235
,
192
,
161
,
131
,
58
,
14
,
167
,
236
,
12
,
19
,
72
,
49
,
27
,
3
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
102
,
111
,
111
})
bmtHashOfFoo
:=
"2387e8e7d8a48c2a9339c97c1dc3461a9a7aa07e994c5cb8b38fd7c1b3e6ea48"
address
:=
swarm
.
MustParseHexAddress
(
bmtHashOfFoo
)
foo
:=
"foo"
fooLength
:=
len
(
foo
)
fooBytes
:=
make
([]
byte
,
8
+
fooLength
)
binary
.
LittleEndian
.
PutUint64
(
fooBytes
,
uint64
(
fooLength
))
copy
(
fooBytes
[
8
:
],
foo
)
ch
:=
swarm
.
NewChunk
(
address
,
fooBytes
)
sch
,
err
:=
soc
.
NewChunk
(
id
,
ch
,
signer
)
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
// check valid chunk
// check valid chunk
if
!
soc
.
Valid
(
sch
)
{
if
!
soc
.
Valid
(
sch
)
{
t
.
Fatal
(
"valid chunk evaluates to invalid"
)
t
.
Fatal
(
"valid chunk evaluates to invalid"
)
}
}
}
// check invalid data
// TestInvalid verifies that the validator can detect chunks
sch
.
Data
()[
0
]
=
0x01
// with invalid data and invalid address.
if
soc
.
Valid
(
sch
)
{
func
TestInvalid
(
t
*
testing
.
T
)
{
t
.
Fatal
(
"chunk with invalid data evaluates to valid"
)
socAddress
:=
swarm
.
MustParseHexAddress
(
"9d453ebb73b2fedaaf44ceddcf7a0aa37f3e3d6453fea5841c31f0ea6d61dc85"
)
}
// signed soc chunk of:
// id: 0
// wrapped chunk of: `foo`
// owner: 0x8d3766440f0d7b949a5e32995d09619a7f86e632
sch
:=
swarm
.
NewChunk
(
socAddress
,
[]
byte
{
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
90
,
205
,
56
,
79
,
235
,
193
,
51
,
183
,
178
,
69
,
229
,
221
,
198
,
45
,
130
,
210
,
205
,
237
,
145
,
130
,
210
,
113
,
97
,
38
,
205
,
136
,
68
,
80
,
154
,
246
,
90
,
5
,
61
,
235
,
65
,
130
,
8
,
2
,
127
,
84
,
142
,
62
,
136
,
52
,
58
,
246
,
248
,
74
,
135
,
114
,
251
,
60
,
235
,
192
,
161
,
131
,
58
,
14
,
167
,
236
,
12
,
19
,
72
,
49
,
27
,
3
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
102
,
111
,
111
})
// check invalid address
for
_
,
c
:=
range
[]
struct
{
sch
.
Data
()[
0
]
=
0x00
name
string
wrongAddressBytes
:=
sch
.
Address
()
.
Bytes
()
chunk
func
()
swarm
.
Chunk
wrongAddressBytes
[
0
]
=
255
-
wrongAddressBytes
[
0
]
}{
wrongAddress
:=
swarm
.
NewAddress
(
wrongAddressBytes
)
{
sch
=
swarm
.
NewChunk
(
wrongAddress
,
sch
.
Data
())
name
:
"wrong soc address"
,
if
soc
.
Valid
(
sch
)
{
chunk
:
func
()
swarm
.
Chunk
{
t
.
Fatal
(
"chunk with invalid address evaluates to valid"
)
wrongAddressBytes
:=
sch
.
Address
()
.
Bytes
()
wrongAddressBytes
[
0
]
=
255
-
wrongAddressBytes
[
0
]
wrongAddress
:=
swarm
.
NewAddress
(
wrongAddressBytes
)
return
swarm
.
NewChunk
(
wrongAddress
,
sch
.
Data
())
},
},
{
name
:
"invalid data"
,
chunk
:
func
()
swarm
.
Chunk
{
data
:=
make
([]
byte
,
len
(
sch
.
Data
()))
copy
(
data
,
sch
.
Data
())
cursor
:=
soc
.
IdSize
+
soc
.
SignatureSize
chunkData
:=
data
[
cursor
:
]
chunkData
[
0
]
=
0x01
return
swarm
.
NewChunk
(
socAddress
,
data
)
},
},
{
name
:
"invalid id"
,
chunk
:
func
()
swarm
.
Chunk
{
data
:=
make
([]
byte
,
len
(
sch
.
Data
()))
copy
(
data
,
sch
.
Data
())
id
:=
data
[
:
soc
.
IdSize
]
id
[
0
]
=
0x01
return
swarm
.
NewChunk
(
socAddress
,
data
)
},
},
{
name
:
"invalid signature"
,
chunk
:
func
()
swarm
.
Chunk
{
data
:=
make
([]
byte
,
len
(
sch
.
Data
()))
copy
(
data
,
sch
.
Data
())
// modify signature
cursor
:=
soc
.
IdSize
+
soc
.
SignatureSize
sig
:=
data
[
soc
.
IdSize
:
cursor
]
sig
[
0
]
=
0x01
return
swarm
.
NewChunk
(
socAddress
,
data
)
},
},
{
name
:
"nil data"
,
chunk
:
func
()
swarm
.
Chunk
{
return
swarm
.
NewChunk
(
socAddress
,
nil
)
},
},
{
name
:
"small data"
,
chunk
:
func
()
swarm
.
Chunk
{
return
swarm
.
NewChunk
(
socAddress
,
[]
byte
(
"small"
))
},
},
{
name
:
"large data"
,
chunk
:
func
()
swarm
.
Chunk
{
return
swarm
.
NewChunk
(
socAddress
,
[]
byte
(
strings
.
Repeat
(
"a"
,
swarm
.
ChunkSize
+
swarm
.
SpanSize
+
1
)))
},
},
}
{
t
.
Run
(
c
.
name
,
func
(
t
*
testing
.
T
)
{
if
soc
.
Valid
(
c
.
chunk
())
{
t
.
Fatal
(
"chunk with invalid data evaluates to valid"
)
}
})
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment