[#465] settlement: Use unified details format for all asset transfers

Unified format uses transfer type as the first byte
and extra details next. List of transfer types used in
contracts defined in `details.go`. It includes:
- audit settlement,
- basic income collection,
- basic income distribution.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2021-04-07 15:12:36 +03:00 committed by Alex Vanin
parent 1d68e74636
commit 3e9c578e62
9 changed files with 75 additions and 29 deletions

View file

@ -387,13 +387,13 @@ func New(ctx context.Context, log *zap.Logger, cfg *viper.Viper) (*Server, error
// create settlement processor dependencies
settlementDeps := &settlementDeps{
globalConfig: globalConfig,
log: server.log,
cnrSrc: cnrClient,
auditClient: server.auditClient,
nmSrc: nmClient,
clientCache: clientCache,
balanceClient: balClient,
cfg: globalConfig,
}
auditCalcDeps := &auditSettlementDeps{

View file

@ -65,8 +65,9 @@ func (c *Calculator) Calculate(p *CalculatePrm) {
log.Info("calculate audit settlements")
log.Debug("getting results for the previous epoch")
prevEpoch := p.Epoch - 1
auditResults, err := c.prm.ResultStorage.AuditResultsForEpoch(p.Epoch - 1)
auditResults, err := c.prm.ResultStorage.AuditResultsForEpoch(prevEpoch)
if err != nil {
log.Error("could not collect audit results")
return
@ -99,7 +100,7 @@ func (c *Calculator) Calculate(p *CalculatePrm) {
log.Debug("processing transfers")
common.TransferAssets(c.prm.Exchanger, table)
common.TransferAssets(c.prm.Exchanger, table, common.AuditSettlementDetails(prevEpoch))
}
func (c *Calculator) processResult(ctx *singleResultCtx) {

View file

@ -70,7 +70,7 @@ func (inc *IncomeSettlementContext) Collect() {
})
}
common.TransferAssets(inc.exchange, txTable)
common.TransferAssets(inc.exchange, txTable, common.BasicIncomeCollectionDetails(inc.epoch))
}
// avgEstimation returns estimation value for single container. Right now it

View file

@ -41,7 +41,7 @@ func (inc *IncomeSettlementContext) Distribute() {
})
})
common.TransferAssets(inc.exchange, txTable)
common.TransferAssets(inc.exchange, txTable, common.BasicIncomeDistributionDetails(inc.epoch))
}
func normalizedValue(n, total, limit *big.Int) *big.Int {

View file

@ -0,0 +1,33 @@
package common
import (
"encoding/binary"
)
var (
auditPrefix = []byte{0x40}
basicIncomeCollectionPrefix = []byte{0x41}
basicIncomeDistributionPrefix = []byte{0x42}
)
func AuditSettlementDetails(epoch uint64) []byte {
return details(auditPrefix, epoch)
}
func BasicIncomeCollectionDetails(epoch uint64) []byte {
return details(basicIncomeCollectionPrefix, epoch)
}
func BasicIncomeDistributionDetails(epoch uint64) []byte {
return details(basicIncomeDistributionPrefix, epoch)
}
func details(prefix []byte, epoch uint64) []byte {
prefixLen := len(prefix)
buf := make([]byte, prefixLen+8)
copy(buf, prefix)
binary.LittleEndian.PutUint64(buf[prefixLen:], epoch)
return buf
}

View file

@ -0,0 +1,28 @@
package common
import (
"testing"
"github.com/stretchr/testify/require"
)
func TestAuditSettlementDetails(t *testing.T) {
var n uint64 = 1994 // 0x7CA
exp := []byte{0x40, 0xCA, 0x07, 0, 0, 0, 0, 0, 0}
got := AuditSettlementDetails(n)
require.Equal(t, exp, got)
}
func TestBasicIncomeCollectionDetails(t *testing.T) {
var n uint64 = 1994 // 0x7CA
exp := []byte{0x41, 0xCA, 0x07, 0, 0, 0, 0, 0, 0}
got := BasicIncomeCollectionDetails(n)
require.Equal(t, exp, got)
}
func TestBasicIncomeDistributionDetails(t *testing.T) {
var n uint64 = 1994 // 0x7CA
exp := []byte{0x42, 0xCA, 0x07, 0, 0, 0, 0, 0, 0}
got := BasicIncomeDistributionDetails(n)
require.Equal(t, exp, got)
}

View file

@ -50,5 +50,5 @@ type Exchanger interface {
// Must transfer amount of GASe-12 from sender to recipient.
//
// Amount must be positive.
Transfer(sender, recipient *owner.ID, amount *big.Int)
Transfer(sender, recipient *owner.ID, amount *big.Int, details []byte)
}

View file

@ -56,7 +56,7 @@ func (t *TransferTable) Iterate(f func(*TransferTx)) {
}
}
func TransferAssets(e Exchanger, t *TransferTable) {
func TransferAssets(e Exchanger, t *TransferTable, details []byte) {
t.Iterate(func(tx *TransferTx) {
sign := tx.Amount.Sign()
if sign == 0 {
@ -68,6 +68,6 @@ func TransferAssets(e Exchanger, t *TransferTable) {
tx.Amount.Neg(tx.Amount)
}
e.Transfer(tx.From, tx.To, tx.Amount)
e.Transfer(tx.From, tx.To, tx.Amount, details)
})
}

View file

@ -32,6 +32,8 @@ type globalConfig interface {
}
type settlementDeps struct {
globalConfig
log *logger.Logger
cnrSrc container.Source
@ -43,8 +45,6 @@ type settlementDeps struct {
clientCache *ClientCache
balanceClient *balanceClient.Wrapper
cfg globalConfig
}
type auditSettlementDeps struct {
@ -191,16 +191,12 @@ func (s settlementDeps) ResolveKey(ni common.NodeInfo) (*owner.ID, error) {
return id, nil
}
var (
transferAuditDetails = []byte("settlement-audit")
basicIncomeAuditDetails = []byte("settlement-basic-income")
)
func (s settlementDeps) transfer(sender, recipient *owner.ID, amount *big.Int, details []byte) {
func (s settlementDeps) Transfer(sender, recipient *owner.ID, amount *big.Int, details []byte) {
log := s.log.With(
zap.Stringer("sender", sender),
zap.Stringer("recipient", recipient),
zap.Stringer("amount (GASe-12)", amount),
zap.String("details", hex.EncodeToString(details)),
)
if !amount.IsInt64() {
@ -225,20 +221,8 @@ func (s settlementDeps) transfer(sender, recipient *owner.ID, amount *big.Int, d
log.Debug("transfer transaction for audit was successfully sent")
}
func (a auditSettlementDeps) Transfer(sender, recipient *owner.ID, amount *big.Int) {
a.transfer(sender, recipient, amount, transferAuditDetails)
}
func (a auditSettlementDeps) AuditFee() (uint64, error) {
return a.cfg.AuditFee()
}
func (b basicIncomeSettlementDeps) Transfer(sender, recipient *owner.ID, amount *big.Int) {
b.transfer(sender, recipient, amount, basicIncomeAuditDetails)
}
func (b basicIncomeSettlementDeps) BasicRate() (uint64, error) {
return b.cfg.BasicIncomeRate()
return b.BasicIncomeRate()
}
func (b basicIncomeSettlementDeps) Estimations(epoch uint64) ([]*wrapper.Estimations, error) {