Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
connectrpc.com/connect v1.19.1
connectrpc.com/grpchealth v1.4.0
connectrpc.com/grpcreflect v1.3.0
github.com/blinklabs-io/gouroboros v0.138.0
github.com/blinklabs-io/gouroboros v0.139.0
github.com/blinklabs-io/ouroboros-mock v0.3.9
github.com/blinklabs-io/plutigo v0.0.13
github.com/btcsuite/btcd/btcutil v1.1.6
Expand All @@ -19,7 +19,7 @@ require (
github.com/kelseyhightower/envconfig v1.4.0
github.com/prometheus/client_golang v1.23.2
github.com/spf13/cobra v1.10.1
github.com/utxorpc/go-codegen v0.17.0
github.com/utxorpc/go-codegen v0.18.1
go.opentelemetry.io/otel v1.38.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.38.0
Expand Down Expand Up @@ -189,7 +189,7 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect
google.golang.org/grpc v1.75.1 // indirect
google.golang.org/protobuf v1.36.9 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gorm.io/driver/clickhouse v0.7.0 // indirect
gorm.io/driver/mysql v1.5.7 // indirect
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3M
github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blinklabs-io/gouroboros v0.138.0 h1:yQF18YmC/hOz6g0/z/SdwsLB1bHD8019wQRQPwabUck=
github.com/blinklabs-io/gouroboros v0.138.0/go.mod h1:xwDWF3wRp/9l7uZ6DLfy/OFGdO4GjKomsWmv9i3le6s=
github.com/blinklabs-io/gouroboros v0.139.0 h1:ctoHFEuXhJlMcUC1fe5x6IX1tqZnS/BAaBDeHiXskeU=
github.com/blinklabs-io/gouroboros v0.139.0/go.mod h1:FxKQNNNRQN5F/Cl4pnW7SHhpPo7fD57mTPGo4N9ulnY=
github.com/blinklabs-io/ouroboros-mock v0.3.9 h1:UnciDccJ5tZCR1xI0BcxGZcYjJ/PS5MpnjiiGtrZ680=
github.com/blinklabs-io/ouroboros-mock v0.3.9/go.mod h1:uTkE8/LAYL7yQSntH48Pudf5Xn+jaBWMj+9udbzYXhI=
github.com/blinklabs-io/plutigo v0.0.13 h1:JztPigFmknQmQ3Ti1+mdTY96ihOUDh6wJ3pPnN2YYBU=
Expand Down Expand Up @@ -452,8 +452,8 @@ github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/urfave/cli v1.22.17 h1:SYzXoiPfQjHBbkYxbew5prZHS1TOLT3ierW8SYLqtVQ=
github.com/urfave/cli v1.22.17/go.mod h1:b0ht0aqgH/6pBYzzxURyrM4xXNgsoT/n2ZzwQiEhNVo=
github.com/utxorpc/go-codegen v0.17.0 h1:cJ7Df9r8Az39lveIcmzcRciIDc3UJFdMSmXg8IAtBPM=
github.com/utxorpc/go-codegen v0.17.0/go.mod h1:LBVGFns4YAHMhy+Pc8tF5ExkU+N8Wm3srst4omKZy4g=
github.com/utxorpc/go-codegen v0.18.1 h1:2eenzXCkqvB2+g8MCq70MBR6koWs9CeTihZ0AqUvLDY=
github.com/utxorpc/go-codegen v0.18.1/go.mod h1:DFij3zIGDM39BYCuzrz1rSuO3kTIIiHglWV0043wQxo=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
Expand Down Expand Up @@ -596,8 +596,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
Expand Down
215 changes: 88 additions & 127 deletions utxorpc/submit.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ package utxorpc
import (
"bytes"
"context"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"math"

"connectrpc.com/connect"
"github.com/blinklabs-io/dingo/event"
Expand All @@ -42,86 +44,33 @@ func (s *submitServiceServer) SubmitTx(
ctx context.Context,
req *connect.Request[submit.SubmitTxRequest],
) (*connect.Response[submit.SubmitTxResponse], error) {
txRawList := req.Msg.GetTx() // []*AnyChainTx
txRaw := req.Msg.GetTx()

s.utxorpc.config.Logger.Info(
fmt.Sprintf(
"Got a SubmitTx request with %d transactions",
len(txRawList),
),
)
s.utxorpc.config.Logger.Info("Got a SubmitTx request")
resp := &submit.SubmitTxResponse{}

// Loop through the transactions and add each to the mempool
errorList := make([]error, len(txRawList))
hasError := false
placeholderRef := []byte{}
for i, txi := range txRawList {
txRawBytes := txi.GetRaw() // raw bytes
txType, err := gledger.DetermineTransactionType(txRawBytes)
if err != nil {
resp.Ref = append(resp.Ref, placeholderRef)
errorList[i] = err
s.utxorpc.config.Logger.Error(
fmt.Sprintf(
"failed decoding tx %d: %v",
i,
err,
),
)
hasError = true
continue
}
tx, err := gledger.NewTransactionFromCbor(txType, txRawBytes)
if err != nil {
resp.Ref = append(resp.Ref, placeholderRef)
errorList[i] = err
s.utxorpc.config.Logger.Error(
fmt.Sprint(
fmt.Errorf(
"failed to decode transaction from CBOR: %w",
err,
),
),
)
hasError = true
continue
}
if tx == nil {
resp.Ref = append(resp.Ref, placeholderRef)
errorList[i] = errors.New("decoded transaction is nil")
s.utxorpc.config.Logger.Error("decoded transaction is nil")
hasError = true
continue
}
txHash := tx.Hash()
// Add transaction to mempool
err = s.utxorpc.config.Mempool.AddTransaction(txType, txRawBytes)
if err != nil {
resp.Ref = append(resp.Ref, placeholderRef)
errorList[i] = fmt.Errorf("%s", err.Error())
s.utxorpc.config.Logger.Error(
fmt.Sprintf(
"failed to add tx %s to mempool: %s",
txHash.String(),
err,
),
)
hasError = true
continue
}
if err != nil {
resp.Ref = append(resp.Ref, placeholderRef)
errorList[i] = err
hasError = true
continue
}
resp.Ref = append(resp.Ref, txHash.Bytes())
txRawBytes := txRaw.GetRaw()
txType, err := gledger.DetermineTransactionType(txRawBytes)
if err != nil {
return nil, fmt.Errorf("failed decoding tx: %w", err)
}
tx, err := gledger.NewTransactionFromCbor(txType, txRawBytes)
if err != nil {
return nil, fmt.Errorf(
"failed to decode transaction from CBOR: %w",
err,
)
}
if hasError {
return connect.NewResponse(resp), fmt.Errorf("%v", errorList)
if tx == nil {
return nil, errors.New("decoded transaction is nil")
}

txHash := tx.Hash()
// Add transaction to mempool
err = s.utxorpc.config.Mempool.AddTransaction(txType, txRawBytes)
if err != nil {
return nil, fmt.Errorf("failed to add tx to mempool: %w", err)
}
resp.Ref = txHash.Bytes()
return connect.NewResponse(resp), nil
}

Expand Down Expand Up @@ -188,69 +137,81 @@ func (s *submitServiceServer) EvalTx(
req *connect.Request[submit.EvalTxRequest],
) (*connect.Response[submit.EvalTxResponse], error) {
s.utxorpc.config.Logger.Info("Got an EvalTx request")
txRawList := req.Msg.GetTx() // []*AnyChainTx
txRaw := req.Msg.GetTx()
resp := &submit.EvalTxResponse{}
for _, txi := range txRawList {
txRawBytes := txi.GetRaw()
// Decode TX
txType, err := gledger.DetermineTransactionType(txRawBytes)
if err != nil {
return nil, fmt.Errorf(
"could not parse transaction to determine type: %w",
err,
)
}
tx, err := gledger.NewTransactionFromCbor(txType, txRawBytes)
if err != nil {
return nil, fmt.Errorf("failed to parse transaction CBOR: %w", err)
}
// Evaluate TX
fee, totalExUnits, redeemerExUnits, err := s.utxorpc.config.LedgerState.EvaluateTx(
tx,

txRawBytes := txRaw.GetRaw()
// Decode TX
txType, err := gledger.DetermineTransactionType(txRawBytes)
if err != nil {
return nil, fmt.Errorf(
"could not parse transaction to determine type: %w",
err,
)
// Populate response
tmpRedeemers := make([]*cardano.Redeemer, 0, len(redeemerExUnits))
for key, val := range redeemerExUnits {
tmpRedeemers = append(
tmpRedeemers,
&cardano.Redeemer{
Purpose: cardano.RedeemerPurpose(key.Tag),
Index: key.Index,
ExUnits: &cardano.ExUnits{
Steps: uint64(val.Steps), // nolint:gosec
Memory: uint64(val.Memory), // nolint:gosec
},
// TODO: Payload
}
tx, err := gledger.NewTransactionFromCbor(txType, txRawBytes)
if err != nil {
return nil, fmt.Errorf("failed to parse transaction CBOR: %w", err)
}
// Evaluate TX
fee, totalExUnits, redeemerExUnits, err := s.utxorpc.config.LedgerState.EvaluateTx(
tx,
)
// Populate response
tmpRedeemers := make([]*cardano.Redeemer, 0, len(redeemerExUnits))
for key, val := range redeemerExUnits {
tmpRedeemers = append(
tmpRedeemers,
&cardano.Redeemer{
Purpose: cardano.RedeemerPurpose(key.Tag),
Index: key.Index,
ExUnits: &cardano.ExUnits{
Steps: uint64(val.Steps), // nolint:gosec
Memory: uint64(val.Memory), // nolint:gosec
},
// TODO: Payload
},
)
}
var txEval *cardano.TxEval
if err != nil {
txEval = &cardano.TxEval{
Errors: []*cardano.EvalError{
{
Msg: err.Error(),
},
)
},
}
var txEval *cardano.TxEval
if err != nil {
txEval = &cardano.TxEval{
Errors: []*cardano.EvalError{
{
Msg: err.Error(),
},
} else {
var feeBigInt *cardano.BigInt
if fee <= math.MaxInt64 {
feeBigInt = &cardano.BigInt{
BigInt: &cardano.BigInt_Int{
Int: int64(fee),
},
}
} else {
txEval = &cardano.TxEval{
Fee: fee,
ExUnits: &cardano.ExUnits{
Steps: uint64(totalExUnits.Steps), // nolint:gosec
Memory: uint64(totalExUnits.Memory), // nolint:gosec
buf := make([]byte, 8)
binary.BigEndian.PutUint64(buf, fee)
feeBigInt = &cardano.BigInt{
BigInt: &cardano.BigInt_BigUInt{
BigUInt: buf,
},
Redeemers: tmpRedeemers,
}
}
resp.Report = append(
resp.Report,
&submit.AnyChainEval{
Chain: &submit.AnyChainEval_Cardano{
Cardano: txEval,
},
txEval = &cardano.TxEval{
Fee: feeBigInt,
ExUnits: &cardano.ExUnits{
Steps: uint64(totalExUnits.Steps), // nolint:gosec
Memory: uint64(totalExUnits.Memory), // nolint:gosec
},
)
Redeemers: tmpRedeemers,
}
}
resp.Report = &submit.AnyChainEval{
Chain: &submit.AnyChainEval_Cardano{
Cardano: txEval,
},
}
return connect.NewResponse(resp), nil
}
Expand Down
Loading