Skip to content

Commit

Permalink
XDRill ledger low level helpers example
Browse files Browse the repository at this point in the history
  • Loading branch information
chowbao committed Nov 4, 2024
1 parent 64efc32 commit d222d6e
Show file tree
Hide file tree
Showing 6 changed files with 398 additions and 0 deletions.
1 change: 1 addition & 0 deletions exp/xdrill/ledgerentries/ledger_entries.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package ledgerentries
191 changes: 191 additions & 0 deletions exp/xdrill/ledgers/ledgers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
package ledgers

import (
"encoding/base64"
"fmt"
"time"

"github.com/stellar/go/exp/xdrill/utils"
"github.com/stellar/go/xdr"
)

type Ledgers struct {
xdr.LedgerCloseMeta
}

func (l Ledgers) Sequence() uint32 {
return uint32(l.LedgerHeaderHistoryEntry().Header.LedgerSeq)

Check failure on line 17 in exp/xdrill/ledgers/ledgers.go

View workflow job for this annotation

GitHub Actions / golangci

l.LedgerHeaderHistoryEntry undefined (type Ledgers has no field or method LedgerHeaderHistoryEntry) (typecheck)
}

func (l Ledgers) ID() int64 {
return utils.NewID(int32(l.LedgerSequence()), 0, 0).ToInt64()

Check failure on line 21 in exp/xdrill/ledgers/ledgers.go

View workflow job for this annotation

GitHub Actions / golangci

l.LedgerSequence undefined (type Ledgers has no field or method LedgerSequence) (typecheck)
}

func (l Ledgers) Hash() string {
return utils.HashToHexString(l.LedgerHeaderHistoryEntry().Hash)

Check failure on line 25 in exp/xdrill/ledgers/ledgers.go

View workflow job for this annotation

GitHub Actions / golangci

l.LedgerHeaderHistoryEntry undefined (type Ledgers has no field or method LedgerHeaderHistoryEntry) (typecheck)
}

func (l Ledgers) PreviousHash() string {
return utils.HashToHexString(l.PreviousLedgerHash())

Check failure on line 29 in exp/xdrill/ledgers/ledgers.go

View workflow job for this annotation

GitHub Actions / golangci

l.PreviousLedgerHash undefined (type Ledgers has no field or method PreviousLedgerHash) (typecheck)
}

func (l Ledgers) CloseTime() int64 {
return l.LedgerCloseTime()

Check failure on line 33 in exp/xdrill/ledgers/ledgers.go

View workflow job for this annotation

GitHub Actions / golangci

l.LedgerCloseTime undefined (type Ledgers has no field or method LedgerCloseTime) (typecheck)
}

func (l Ledgers) ClosedAt() time.Time {
return time.Unix(l.CloseTime(), 0).UTC()
}

func (l Ledgers) TotalCoins() int64 {
return int64(l.LedgerHeaderHistoryEntry().Header.TotalCoins)

Check failure on line 41 in exp/xdrill/ledgers/ledgers.go

View workflow job for this annotation

GitHub Actions / golangci

l.LedgerHeaderHistoryEntry undefined (type Ledgers has no field or method LedgerHeaderHistoryEntry) (typecheck)
}

func (l Ledgers) FeePool() int64 {
return int64(l.LedgerHeaderHistoryEntry().Header.FeePool)
}

func (l Ledgers) BaseFee() uint32 {
return uint32(l.LedgerHeaderHistoryEntry().Header.BaseFee)
}

func (l Ledgers) BaseReserve() uint32 {
return uint32(l.LedgerHeaderHistoryEntry().Header.BaseReserve)
}

func (l Ledgers) MaxTxSetSize() uint32 {
return uint32(l.LedgerHeaderHistoryEntry().Header.MaxTxSetSize)
}

func (l Ledgers) LedgerVersion() uint32 {
return uint32(l.LedgerHeaderHistoryEntry().Header.LedgerVersion)
}

func (l Ledgers) GetSorobanFeeWrite1Kb() (int64, bool) {
lcmV1, ok := l.GetV1()

Check failure on line 65 in exp/xdrill/ledgers/ledgers.go

View workflow job for this annotation

GitHub Actions / golangci

l.GetV1 undefined (type Ledgers has no field or method GetV1) (typecheck)
if ok {
extV1, ok := lcmV1.Ext.GetV1()
if ok {
return int64(extV1.SorobanFeeWrite1Kb), true
}
}

return 0, false
}

func (l Ledgers) GetTotalByteSizeOfBucketList() (uint64, bool) {
lcmV1, ok := l.GetV1()

Check failure on line 77 in exp/xdrill/ledgers/ledgers.go

View workflow job for this annotation

GitHub Actions / golangci

l.GetV1 undefined (type Ledgers has no field or method GetV1) (typecheck)
if ok {
return uint64(lcmV1.TotalByteSizeOfBucketList), true
}

return 0, false
}

func (l Ledgers) GetNodeID() (string, bool) {
LedgerCloseValueSignature, ok := l.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature()
if ok {
nodeID, ok := utils.GetAddress(LedgerCloseValueSignature.NodeId)
if ok {
return nodeID, true
}
}

return "", false
}

func (l Ledgers) GetSignature() (string, bool) {
LedgerCloseValueSignature, ok := l.LedgerHeaderHistoryEntry().Header.ScpValue.Ext.GetLcValueSignature()
if ok {
return base64.StdEncoding.EncodeToString(LedgerCloseValueSignature.Signature), true
}

return "", false
}

func (l Ledgers) GetTransactionCounts() (successTxCount, failedTxCount int32, ok bool) {
transactions := getTransactionSet(l)
results := l.V0.TxProcessing

Check failure on line 108 in exp/xdrill/ledgers/ledgers.go

View workflow job for this annotation

GitHub Actions / golangci

l.V0 undefined (type Ledgers has no field or method V0) (typecheck)
txCount := len(transactions)
if txCount != len(results) {
return 0, 0, false
}

for i := 0; i < txCount; i++ {
if results[i].Result.Successful() {
successTxCount++
} else {
failedTxCount++
}
}

return successTxCount, failedTxCount, true
}

func (l Ledgers) GetOperationCounts() (operationCount, txSetOperationCount int32, ok bool) {
transactions := getTransactionSet(l)
results := l.V0.TxProcessing

Check failure on line 127 in exp/xdrill/ledgers/ledgers.go

View workflow job for this annotation

GitHub Actions / golangci

l.V0 undefined (type Ledgers has no field or method V0) (typecheck)
txCount := len(transactions)
if txCount != len(results) {
return 0, 0, false
}

for i := 0; i < txCount; i++ {
operations := transactions[i].Operations()
numberOfOps := int32(len(operations))
txSetOperationCount += numberOfOps

// for successful transactions, the operation count is based on the operations results slice
if results[i].Result.Successful() {
operationResults, ok := results[i].Result.OperationResults()
if !ok {
return 0, 0, false
}

operationCount += int32(len(operationResults))
}

}

return operationCount, txSetOperationCount, true
}

func getTransactionSet(l Ledgers) (transactionProcessing []xdr.TransactionEnvelope) {
switch l.V {
case 0:
return l.V0.TxSet.Txs
case 1:
switch l.V1.TxSet.V {
case 0:
return getTransactionPhase(l.V1.TxSet.V1TxSet.Phases)
default:
panic(fmt.Sprintf("unsupported LedgerCloseMeta.V1.TxSet.V: %d", l.V1.TxSet.V))
}
default:
panic(fmt.Sprintf("unsupported LedgerCloseMeta.V: %d", l.V))
}
}

func getTransactionPhase(transactionPhase []xdr.TransactionPhase) (transactionEnvelope []xdr.TransactionEnvelope) {
transactionSlice := []xdr.TransactionEnvelope{}
for _, phase := range transactionPhase {
switch phase.V {
case 0:
components := phase.MustV0Components()
for _, component := range components {
switch component.Type {
case 0:
transactionSlice = append(transactionSlice, component.TxsMaybeDiscountedFee.Txs...)

default:
panic(fmt.Sprintf("Unsupported TxSetComponentType: %d", component.Type))
}

}
default:
panic(fmt.Sprintf("Unsupported TransactionPhase.V: %d", phase.V))
}
}

return transactionSlice
}
1 change: 1 addition & 0 deletions exp/xdrill/operations/operations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package operations
9 changes: 9 additions & 0 deletions exp/xdrill/transactions/transactions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package transactions

import (
"github.com/stellar/go/ingest"
)

type Transactions struct {
ingest.LedgerTransaction
}
104 changes: 104 additions & 0 deletions exp/xdrill/transform_ledger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package xdrill

import (
"fmt"
"time"

"github.com/stellar/go/exp/xdrill/ledgers"
"github.com/stellar/go/xdr"
)

type LedgerOutput struct {
Sequence uint32 `json:"sequence"` // sequence number of the ledger
LedgerHash string `json:"ledger_hash"`
PreviousLedgerHash string `json:"previous_ledger_hash"`
LedgerHeader string `json:"ledger_header"` // base 64 encoding of the ledger header
TransactionCount int32 `json:"transaction_count"`
OperationCount int32 `json:"operation_count"` // counts only operations that were a part of successful transactions
SuccessfulTransactionCount int32 `json:"successful_transaction_count"`
FailedTransactionCount int32 `json:"failed_transaction_count"`
TxSetOperationCount string `json:"tx_set_operation_count"` // counts all operations, even those that are part of failed transactions
ClosedAt time.Time `json:"closed_at"` // UTC timestamp
TotalCoins int64 `json:"total_coins"`
FeePool int64 `json:"fee_pool"`
BaseFee uint32 `json:"base_fee"`
BaseReserve uint32 `json:"base_reserve"`
MaxTxSetSize uint32 `json:"max_tx_set_size"`
ProtocolVersion uint32 `json:"protocol_version"`
LedgerID int64 `json:"id"`
SorobanFeeWrite1Kb int64 `json:"soroban_fee_write_1kb"`
NodeID string `json:"node_id"`
Signature string `json:"signature"`
TotalByteSizeOfBucketList uint64 `json:"total_byte_size_of_bucket_list"`
}

func TransformLedger(lcm xdr.LedgerCloseMeta) (LedgerOutput, error) {
ledger := ledgers.Ledgers{
LedgerCloseMeta: lcm,
}

outputLedgerHeader, err := xdr.MarshalBase64(ledger.LedgerHeaderHistoryEntry().Header)
if err != nil {
return LedgerOutput{}, err
}

outputSuccessfulTransactionCount, outputFailedTransactionCount, ok := ledger.GetTransactionCounts()
if !ok {
return LedgerOutput{}, fmt.Errorf("could not get transaction counts")
}

outputOperationCount, outputTxSetOperationCount, ok := ledger.GetOperationCounts()
if !ok {
return LedgerOutput{}, fmt.Errorf("could not get operation counts")
}

var outputSorobanFeeWrite1Kb int64
sorobanFeeWrite1Kb, ok := ledger.GetSorobanFeeWrite1Kb()
if ok {
outputSorobanFeeWrite1Kb = sorobanFeeWrite1Kb
}

var outputTotalByteSizeOfBucketList uint64
totalByteSizeOfBucketList, ok := ledger.GetTotalByteSizeOfBucketList()
if ok {
outputTotalByteSizeOfBucketList = totalByteSizeOfBucketList
}

var outputNodeID string
nodeID, ok := ledger.GetNodeID()
if ok {
outputNodeID = nodeID
}

var outputSigature string
signature, ok := ledger.GetSignature()
if ok {
outputSigature = signature
}

ledgerOutput := LedgerOutput{
Sequence: ledger.LedgerSequence(),
LedgerHash: ledger.Hash(),
PreviousLedgerHash: ledger.Hash(),
LedgerHeader: outputLedgerHeader,
TransactionCount: outputSuccessfulTransactionCount,
OperationCount: outputOperationCount,
SuccessfulTransactionCount: outputSuccessfulTransactionCount,
FailedTransactionCount: outputFailedTransactionCount,
TxSetOperationCount: string(outputTxSetOperationCount),
ClosedAt: ledger.ClosedAt(),
TotalCoins: ledger.TotalCoins(),
FeePool: ledger.FeePool(),
BaseFee: ledger.BaseFee(),
BaseReserve: ledger.BaseReserve(),
MaxTxSetSize: ledger.MaxTxSetSize(),
ProtocolVersion: ledger.LedgerVersion(),
LedgerID: ledger.ID(),
SorobanFeeWrite1Kb: outputSorobanFeeWrite1Kb,
NodeID: outputNodeID,
Signature: outputSigature,
TotalByteSizeOfBucketList: outputTotalByteSizeOfBucketList,
}

return ledgerOutput, nil
}
Loading

0 comments on commit d222d6e

Please sign in to comment.