-
Notifications
You must be signed in to change notification settings - Fork 338
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
storage incentives: batch service and backing store #1069
Changes from 18 commits
6beb5db
76948b1
a5e8d4b
efde42e
3d3b8b2
20627d0
3842803
345f363
3191e60
5bb64cf
1643355
27bed28
b45cf02
e5f6544
9241dc6
3228bbc
6220111
2fdda54
b4d0b03
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// 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 postage | ||
|
||
import ( | ||
"encoding/binary" | ||
"math/big" | ||
) | ||
|
||
// Batch represents a postage batch, a payment on the blockchain. | ||
type Batch struct { | ||
ID []byte // batch ID | ||
Value *big.Int // overall balance of the batch | ||
Start uint64 // block number the batch was created | ||
Owner []byte // owner's ethereum address | ||
Depth uint8 // batch depth, i.e., size = 2^{depth} | ||
} | ||
|
||
// MarshalBinary serialises a postage batch to a byte slice len 117. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure 117 is correct |
||
func (b *Batch) MarshalBinary() ([]byte, error) { | ||
out := make([]byte, 93) | ||
copy(out, b.ID) | ||
value := b.Value.Bytes() | ||
copy(out[64-len(value):], value) | ||
binary.BigEndian.PutUint64(out[64:72], b.Start) | ||
copy(out[72:], b.Owner) | ||
out[92] = b.Depth | ||
return out, nil | ||
} | ||
|
||
// UnmarshalBinary deserialises the batch. | ||
// Unsafe on slice index (len(buf) = 117) as only internally used in db. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 117? |
||
func (b *Batch) UnmarshalBinary(buf []byte) error { | ||
b.ID = buf[:32] | ||
b.Value = big.NewInt(0).SetBytes(buf[32:64]) | ||
b.Start = binary.BigEndian.Uint64(buf[64:72]) | ||
b.Owner = buf[72:92] | ||
b.Depth = buf[92] | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package postage_test | ||
|
||
import ( | ||
"bytes" | ||
"testing" | ||
|
||
"github.com/ethersphere/bee/pkg/postage" | ||
postagetesting "github.com/ethersphere/bee/pkg/postage/testing" | ||
) | ||
|
||
// TestBatchMarshalling tests the idempotence of binary marshal/unmarshal for a Batch. | ||
func TestBatchMarshalling(t *testing.T) { | ||
a, err := postagetesting.NewBatch() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
buf, err := a.MarshalBinary() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
if len(buf) != 93 { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 117 -> 93 see above |
||
t.Fatalf("invalid length for serialised batch. expected 93, got %d", len(buf)) | ||
} | ||
b := &postage.Batch{} | ||
if err := b.UnmarshalBinary(buf); err != nil { | ||
t.Fatalf("unexpected error unmarshalling batch: %v", err) | ||
} | ||
if !bytes.Equal(b.ID, a.ID) { | ||
t.Fatalf("id mismatch, expected %x, got %x", a.ID, b.ID) | ||
} | ||
if !bytes.Equal(b.Owner, a.Owner) { | ||
t.Fatalf("owner mismatch, expected %x, got %x", a.Owner, b.Owner) | ||
} | ||
if a.Value.Uint64() != b.Value.Uint64() { | ||
t.Fatalf("value mismatch, expected %d, got %d", a.Value.Uint64(), b.Value.Uint64()) | ||
} | ||
if a.Start != b.Start { | ||
t.Fatalf("start mismatch, expected %d, got %d", a.Start, b.Start) | ||
} | ||
if a.Depth != b.Depth { | ||
t.Fatalf("depth mismatch, expected %d, got %d", a.Depth, b.Depth) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package batchservice | ||
|
||
import ( | ||
"encoding/hex" | ||
"fmt" | ||
"math/big" | ||
|
||
"github.com/ethersphere/bee/pkg/logging" | ||
"github.com/ethersphere/bee/pkg/postage" | ||
) | ||
|
||
// BatchService implements EventUpdater | ||
type BatchService struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. please do not call this service. This is a db/store/representation of onchain data |
||
cs postage.ChainState | ||
storer postage.BatchStorer | ||
logger logging.Logger | ||
} | ||
|
||
// NewBatchService will create a new BatchService | ||
func NewBatchService(storer postage.BatchStorer, logger logging.Logger) (postage.EventUpdater, error) { | ||
b := BatchService{ | ||
storer: storer, | ||
logger: logger, | ||
} | ||
|
||
cs, err := storer.GetChainState() | ||
if err != nil { | ||
return nil, fmt.Errorf("new batch service: %v", err) | ||
} | ||
b.cs = *cs | ||
|
||
return &b, nil | ||
} | ||
|
||
// Create will create a new batch and store it in the BatchStore. | ||
func (svc *BatchService) Create(id, owner []byte, value *big.Int, depth uint8) error { | ||
b := postage.Batch{ | ||
ID: id, | ||
Owner: owner, | ||
Value: value, | ||
Start: svc.cs.Block, | ||
Depth: depth, | ||
} | ||
|
||
err := svc.storer.Put(&b) | ||
if err != nil { | ||
return fmt.Errorf("CreateBatch: %w", err) | ||
} | ||
|
||
svc.logger.Debugf("created batch id %x", hex.EncodeToString(b.ID)) | ||
return nil | ||
} | ||
|
||
// TopUp implements the EventUpdater interface. It tops ups a batch with the | ||
// given ID with the given amount of BZZ. | ||
func (svc *BatchService) TopUp(id []byte, amount *big.Int) error { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use value instead of amount here |
||
b, err := svc.storer.Get(id) | ||
if err != nil { | ||
return fmt.Errorf("TopUp: %w", err) | ||
} | ||
|
||
b.Value.Add(b.Value, amount) | ||
|
||
err = svc.storer.Put(b) | ||
if err != nil { | ||
return fmt.Errorf("TopUp: %w", err) | ||
} | ||
|
||
svc.logger.Debugf("topped up batch id %x with %v", hex.EncodeToString(b.ID), b.Value) | ||
return nil | ||
} | ||
|
||
// UpdateDepth implements the EventUpdater inteface. It sets the new depth of a | ||
// batch with the given ID. | ||
func (svc *BatchService) UpdateDepth(id []byte, depth uint8) error { | ||
b, err := svc.storer.Get(id) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
b.Depth = depth | ||
|
||
err = svc.storer.Put(b) | ||
if err != nil { | ||
return fmt.Errorf("update depth: %w", err) | ||
} | ||
|
||
svc.logger.Debugf("updated depth of batch id %x to %d", hex.EncodeToString(b.ID), b.Depth) | ||
return nil | ||
} | ||
|
||
// UpdatePrice implements the EventUpdater interface. It sets the current | ||
// price from the chain in the service chain state. | ||
func (svc *BatchService) UpdatePrice(price *big.Int) error { | ||
svc.cs.Price = price | ||
|
||
if err := svc.storer.PutChainState(&svc.cs); err != nil { | ||
return fmt.Errorf("update price: %w", err) | ||
} | ||
|
||
svc.logger.Debugf("updated chain price to %s", svc.cs.Price) | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incorrect or misleading comment