-
Notifications
You must be signed in to change notification settings - Fork 338
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Postage BatchStore and BatchService (#1070)
Co-authored-by: zelig <viktor.tron@gmail.com>
- Loading branch information
Showing
23 changed files
with
1,101 additions
and
127 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// 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 implements BinaryMarshaller. It will attempt to serialize the | ||
// postage batch to a byte slice. | ||
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 implements BinaryUnmarshaller. It will attempt deserialize | ||
// the given byte slice into the batch. | ||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// 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_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 := postagetesting.MustNewBatch() | ||
|
||
buf, err := a.MarshalBinary() | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
if len(buf) != 93 { | ||
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) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// 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 batchservice | ||
|
||
import ( | ||
"encoding/hex" | ||
"fmt" | ||
"math/big" | ||
|
||
"github.com/ethersphere/bee/pkg/logging" | ||
"github.com/ethersphere/bee/pkg/postage" | ||
) | ||
|
||
type batchService struct { | ||
cs *postage.ChainState | ||
storer postage.Storer | ||
logger logging.Logger | ||
} | ||
|
||
// New will create a new BatchService. | ||
func New(storer postage.Storer, logger logging.Logger) (postage.EventUpdater, error) { | ||
b := &batchService{ | ||
storer: storer, | ||
logger: logger, | ||
} | ||
|
||
cs, err := storer.GetChainState() | ||
if err != nil { | ||
return nil, fmt.Errorf("get chain state: %w", err) | ||
} | ||
b.cs = cs | ||
|
||
return b, nil | ||
} | ||
|
||
// Create will create a new batch with the given ID, owner value and depth and | ||
// stores 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("put: %w", err) | ||
} | ||
|
||
svc.logger.Debugf("created batch id %s", hex.EncodeToString(b.ID)) | ||
return nil | ||
} | ||
|
||
// TopUp implements the EventUpdater interface. It tops ups a batch with the | ||
// given ID with the given amount. | ||
func (svc *batchService) TopUp(id []byte, amount *big.Int) error { | ||
b, err := svc.storer.Get(id) | ||
if err != nil { | ||
return fmt.Errorf("get: %w", err) | ||
} | ||
|
||
b.Value.Add(b.Value, amount) | ||
|
||
err = svc.storer.Put(b) | ||
if err != nil { | ||
return fmt.Errorf("put: %w", err) | ||
} | ||
|
||
svc.logger.Debugf("topped up batch id %s 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 fmt.Errorf("get: %w", err) | ||
} | ||
|
||
b.Depth = depth | ||
|
||
err = svc.storer.Put(b) | ||
if err != nil { | ||
return fmt.Errorf("put: %w", err) | ||
} | ||
|
||
svc.logger.Debugf("updated depth of batch id %s 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("put chain state: %w", err) | ||
} | ||
|
||
svc.logger.Debugf("updated chain price to %s", svc.cs.Price) | ||
return nil | ||
} |
Oops, something went wrong.