mirror of
https://github.com/QuilibriumNetwork/ceremonyclient.git
synced 2026-02-21 10:27:26 +08:00
233 lines
5.9 KiB
Go
233 lines
5.9 KiB
Go
package application
|
|
|
|
import (
|
|
"github.com/pkg/errors"
|
|
"go.uber.org/zap"
|
|
"google.golang.org/protobuf/proto"
|
|
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
|
|
"source.quilibrium.com/quilibrium/monorepo/node/store"
|
|
"source.quilibrium.com/quilibrium/monorepo/node/tries"
|
|
)
|
|
|
|
var ErrInvalidStateTransition = errors.New("invalid state transition")
|
|
|
|
var TOKEN_ADDRESS = []byte{
|
|
// poseidon("q_mainnet_token")
|
|
0x11, 0x55, 0x85, 0x84, 0xaf, 0x70, 0x17, 0xa9,
|
|
0xbf, 0xd1, 0xff, 0x18, 0x64, 0x30, 0x2d, 0x64,
|
|
0x3f, 0xbe, 0x58, 0xc6, 0x2d, 0xcf, 0x90, 0xcb,
|
|
0xcd, 0x8f, 0xde, 0x74, 0xa2, 0x67, 0x94, 0xd9,
|
|
}
|
|
|
|
type TokenApplication struct {
|
|
TokenOutputs *protobufs.TokenOutputs
|
|
Tries []*tries.RollingFrecencyCritbitTrie
|
|
CoinStore store.CoinStore
|
|
Logger *zap.Logger
|
|
Difficulty uint32
|
|
}
|
|
|
|
func GetOutputsFromClockFrame(
|
|
frame *protobufs.ClockFrame,
|
|
) (
|
|
*protobufs.TokenRequests,
|
|
*protobufs.TokenOutputs,
|
|
error,
|
|
) {
|
|
var associatedProof []byte
|
|
var tokenOutputs *protobufs.TokenOutputs
|
|
if len(frame.AggregateProofs) > 0 {
|
|
for _, proofs := range frame.AggregateProofs {
|
|
for _, inclusion := range proofs.InclusionCommitments {
|
|
if inclusion.TypeUrl == protobufs.IntrinsicExecutionOutputType {
|
|
output := protobufs.IntrinsicExecutionOutput{}
|
|
if err := proto.Unmarshal(inclusion.Data, &output); err != nil {
|
|
return nil, nil, errors.Wrap(err, "get outputs from clock frame")
|
|
}
|
|
|
|
tokenOutputs = &protobufs.TokenOutputs{}
|
|
if err := proto.Unmarshal(output.Output, tokenOutputs); err != nil {
|
|
return nil, nil, errors.Wrap(err, "get outputs from clock frame")
|
|
}
|
|
|
|
associatedProof = output.Proof
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
transition := &protobufs.TokenRequests{}
|
|
if frame.FrameNumber != 0 {
|
|
if err := proto.Unmarshal(associatedProof, transition); err != nil {
|
|
return nil, nil, errors.Wrap(err, "get outputs from clock frame")
|
|
}
|
|
}
|
|
|
|
return transition, tokenOutputs, nil
|
|
}
|
|
|
|
func MaterializeApplicationFromFrame(
|
|
frame *protobufs.ClockFrame,
|
|
tries []*tries.RollingFrecencyCritbitTrie,
|
|
store store.CoinStore,
|
|
logger *zap.Logger,
|
|
) (*TokenApplication, error) {
|
|
_, tokenOutputs, err := GetOutputsFromClockFrame(frame)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "materialize application from frame")
|
|
}
|
|
|
|
return &TokenApplication{
|
|
TokenOutputs: tokenOutputs,
|
|
Tries: tries,
|
|
CoinStore: store,
|
|
Logger: logger,
|
|
Difficulty: frame.Difficulty,
|
|
}, nil
|
|
}
|
|
|
|
func (a *TokenApplication) ApplyTransitions(
|
|
currentFrameNumber uint64,
|
|
transitions *protobufs.TokenRequests,
|
|
skipFailures bool,
|
|
) (
|
|
*TokenApplication,
|
|
*protobufs.TokenRequests,
|
|
*protobufs.TokenRequests,
|
|
error,
|
|
) {
|
|
finalizedTransitions := &protobufs.TokenRequests{}
|
|
failedTransitions := &protobufs.TokenRequests{}
|
|
outputs := &protobufs.TokenOutputs{}
|
|
lockMap := map[string]struct{}{}
|
|
|
|
for _, transition := range transitions.Requests {
|
|
req:
|
|
switch t := transition.Request.(type) {
|
|
case *protobufs.TokenRequest_Announce:
|
|
success, err := a.handleAnnounce(currentFrameNumber, lockMap, t.Announce)
|
|
if err != nil {
|
|
if !skipFailures {
|
|
return nil, nil, nil, errors.Wrap(
|
|
ErrInvalidStateTransition,
|
|
"apply transitions",
|
|
)
|
|
}
|
|
failedTransitions.Requests = append(
|
|
failedTransitions.Requests,
|
|
transition,
|
|
)
|
|
break req
|
|
}
|
|
outputs.Outputs = append(outputs.Outputs, success...)
|
|
finalizedTransitions.Requests = append(
|
|
finalizedTransitions.Requests,
|
|
transition,
|
|
)
|
|
case *protobufs.TokenRequest_Merge:
|
|
success, err := a.handleMerge(currentFrameNumber, lockMap, t.Merge)
|
|
if err != nil {
|
|
if !skipFailures {
|
|
return nil, nil, nil, errors.Wrap(
|
|
ErrInvalidStateTransition,
|
|
"apply transitions",
|
|
)
|
|
}
|
|
failedTransitions.Requests = append(
|
|
failedTransitions.Requests,
|
|
transition,
|
|
)
|
|
break req
|
|
}
|
|
outputs.Outputs = append(outputs.Outputs, success...)
|
|
finalizedTransitions.Requests = append(
|
|
finalizedTransitions.Requests,
|
|
transition,
|
|
)
|
|
case *protobufs.TokenRequest_Split:
|
|
success, err := a.handleSplit(currentFrameNumber, lockMap, t.Split)
|
|
if err != nil {
|
|
if !skipFailures {
|
|
return nil, nil, nil, errors.Wrap(
|
|
ErrInvalidStateTransition,
|
|
"apply transitions",
|
|
)
|
|
}
|
|
failedTransitions.Requests = append(
|
|
failedTransitions.Requests,
|
|
transition,
|
|
)
|
|
break req
|
|
}
|
|
outputs.Outputs = append(outputs.Outputs, success...)
|
|
finalizedTransitions.Requests = append(
|
|
finalizedTransitions.Requests,
|
|
transition,
|
|
)
|
|
case *protobufs.TokenRequest_Transfer:
|
|
success, err := a.handleTransfer(currentFrameNumber, lockMap, t.Transfer)
|
|
if err != nil {
|
|
if !skipFailures {
|
|
return nil, nil, nil, errors.Wrap(
|
|
ErrInvalidStateTransition,
|
|
"apply transitions",
|
|
)
|
|
}
|
|
failedTransitions.Requests = append(
|
|
failedTransitions.Requests,
|
|
transition,
|
|
)
|
|
break req
|
|
}
|
|
outputs.Outputs = append(outputs.Outputs, success...)
|
|
finalizedTransitions.Requests = append(
|
|
finalizedTransitions.Requests,
|
|
transition,
|
|
)
|
|
case *protobufs.TokenRequest_Mint:
|
|
success, err := a.handleMint(currentFrameNumber, lockMap, t.Mint)
|
|
if err != nil {
|
|
if !skipFailures {
|
|
return nil, nil, nil, errors.Wrap(
|
|
ErrInvalidStateTransition,
|
|
"apply transitions",
|
|
)
|
|
}
|
|
failedTransitions.Requests = append(
|
|
failedTransitions.Requests,
|
|
transition,
|
|
)
|
|
break req
|
|
}
|
|
outputs.Outputs = append(outputs.Outputs, success...)
|
|
finalizedTransitions.Requests = append(
|
|
finalizedTransitions.Requests,
|
|
transition,
|
|
)
|
|
}
|
|
}
|
|
|
|
a.TokenOutputs = outputs
|
|
|
|
return a, finalizedTransitions, failedTransitions, nil
|
|
}
|
|
|
|
func nearestApplicablePowerOfTwo(number uint64) uint64 {
|
|
power := uint64(128)
|
|
if number > 2048 {
|
|
power = 65536
|
|
} else if number > 1024 {
|
|
power = 2048
|
|
} else if number > 128 {
|
|
power = 1024
|
|
}
|
|
return power
|
|
}
|
|
|
|
func (a *TokenApplication) MaterializeStateFromApplication() (
|
|
*protobufs.TokenOutputs,
|
|
error,
|
|
) {
|
|
return a.TokenOutputs, nil
|
|
}
|