Files
ark/asp/internal/infrastructure/tx-builder/dummy/builder.go
Pietralberto Mazza 0210d39866 Monorepo scaffolding (#16)
* Change scaffolding

* Fix gh action
2023-11-27 14:23:22 +01:00

224 lines
4.7 KiB
Go

package txbuilder
import (
"context"
"encoding/hex"
"github.com/ark-network/ark/common"
"github.com/ark-network/ark/internal/core/domain"
"github.com/ark-network/ark/internal/core/ports"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
"github.com/vulpemventures/go-elements/network"
"github.com/vulpemventures/go-elements/psetv2"
)
const (
connectorAmount = 450
)
type txBuilder struct {
net *network.Network
aspPublicKey *secp256k1.PublicKey
}
func toElementsNetwork(net common.Network) *network.Network {
switch net {
case common.MainNet:
return &network.Liquid
case common.TestNet:
return &network.Testnet
default:
return nil
}
}
func NewTxBuilder(aspPublicKey *secp256k1.PublicKey, net common.Network) ports.TxBuilder {
return &txBuilder{
aspPublicKey: aspPublicKey,
net: toElementsNetwork(net),
}
}
// BuildCongestionTree implements ports.TxBuilder.
func (b *txBuilder) BuildCongestionTree(poolTx string, payments []domain.Payment) (congestionTree []string, err error) {
poolTxID, err := getTxID(poolTx)
if err != nil {
return nil, err
}
receivers := receiversFromPayments(payments)
return buildCongestionTree(
newOutputScriptFactory(b.aspPublicKey, b.net),
b.net,
poolTxID,
receivers,
)
}
// BuildForfeitTxs implements ports.TxBuilder.
func (b *txBuilder) BuildForfeitTxs(poolTx string, payments []domain.Payment) (connectors []string, forfeitTxs []string, err error) {
poolTxID, err := getTxID(poolTx)
if err != nil {
return nil, nil, err
}
aspScript, err := p2wpkhScript(b.aspPublicKey, b.net)
if err != nil {
return nil, nil, err
}
numberOfConnectors := numberOfVTXOs(payments)
connectors, err = createConnectors(
poolTxID,
1,
psetv2.OutputArgs{
Asset: b.net.AssetID,
Amount: connectorAmount,
Script: aspScript,
},
aspScript,
numberOfConnectors,
)
if err != nil {
return nil, nil, err
}
connectorsAsInputs, err := connectorsToInputArgs(connectors)
if err != nil {
return nil, nil, err
}
forfeitTxs = make([]string, 0)
for _, payment := range payments {
for _, vtxo := range payment.Inputs {
for _, connector := range connectorsAsInputs {
forfeitTx, err := createForfeitTx(
connector,
psetv2.InputArgs{
Txid: vtxo.Txid,
TxIndex: vtxo.VOut,
},
vtxo.Amount,
aspScript,
b.net,
)
if err != nil {
return nil, nil, err
}
forfeitTxs = append(forfeitTxs, forfeitTx)
}
}
}
return connectors, forfeitTxs, nil
}
// BuildPoolTx implements ports.TxBuilder.
func (b *txBuilder) BuildPoolTx(wallet ports.WalletService, payments []domain.Payment) (poolTx string, err error) {
aspScriptBytes, err := p2wpkhScript(b.aspPublicKey, b.net)
if err != nil {
return "", err
}
aspScript := hex.EncodeToString(aspScriptBytes)
receivers := receiversFromPayments(payments)
sharedOutputAmount := sumReceivers(receivers)
numberOfConnectors := numberOfVTXOs(payments)
connectorOutputAmount := connectorAmount * numberOfConnectors
ctx := context.Background()
return wallet.Transaction().Transfer(ctx, []ports.TxOutput{
newOutput(aspScript, sharedOutputAmount),
newOutput(aspScript, connectorOutputAmount),
})
}
func connectorsToInputArgs(connectors []string) ([]psetv2.InputArgs, error) {
inputs := make([]psetv2.InputArgs, 0, len(connectors)+1)
for i, psetb64 := range connectors {
txID, err := getTxID(psetb64)
if err != nil {
return nil, err
}
input := psetv2.InputArgs{
Txid: txID,
TxIndex: 0,
}
inputs = append(inputs, input)
if i == len(connectors)-1 {
input := psetv2.InputArgs{
Txid: txID,
TxIndex: 1,
}
inputs = append(inputs, input)
}
}
return inputs, nil
}
func getTxID(psetBase64 string) (string, error) {
pset, err := psetv2.NewPsetFromBase64(psetBase64)
if err != nil {
return "", err
}
utx, err := pset.UnsignedTx()
if err != nil {
return "", err
}
return utx.TxHash().String(), nil
}
func numberOfVTXOs(payments []domain.Payment) uint64 {
var sum uint64
for _, payment := range payments {
sum += uint64(len(payment.Inputs))
}
return sum
}
func receiversFromPayments(payments []domain.Payment) []domain.Receiver {
receivers := make([]domain.Receiver, 0)
for _, payment := range payments {
receivers = append(receivers, payment.Receivers...)
}
return receivers
}
func sumReceivers(receivers []domain.Receiver) uint64 {
var sum uint64
for _, r := range receivers {
sum += r.Amount
}
return sum
}
type output struct {
script string
amount uint64
}
func newOutput(script string, amount uint64) ports.TxOutput {
return &output{
script: script,
amount: amount,
}
}
func (o *output) GetAmount() uint64 {
return o.amount
}
func (o *output) GetScript() string {
return o.script
}